| #ifndef PRJXRAY_LIB_XILINX_XCUSERIES_CONFIGURATION_BUS_H_ |
| #define PRJXRAY_LIB_XILINX_XCUSERIES_CONFIGURATION_BUS_H_ |
| |
| #include <algorithm> |
| #include <cassert> |
| #include <map> |
| #include <memory> |
| |
| #include <absl/types/optional.h> |
| #include <prjxray/xilinx/xcuseries/configuration_column.h> |
| #include <prjxray/xilinx/xcuseries/frame_address.h> |
| #include <yaml-cpp/yaml.h> |
| |
| namespace prjxray { |
| namespace xilinx { |
| namespace xcuseries { |
| |
| // ConfigurationBus represents a bus for sending frames to a specific BlockType |
| // within a Row. An instance of ConfigurationBus will contain one or more |
| // ConfigurationColumns. |
| class ConfigurationBus { |
| public: |
| ConfigurationBus() = default; |
| |
| // Constructs a ConfigurationBus from iterators yielding |
| // FrameAddresses. The frame address need not be contiguous or sorted |
| // but they must all have the same block type, row half, and row |
| // address components. |
| template <typename T> |
| ConfigurationBus(T first, T last); |
| |
| // Returns true if the provided address falls into a valid segment of |
| // the address range on this bus. Only the column and minor components |
| // of the address are considered as all other components are outside |
| // the scope of a bus. |
| bool IsValidFrameAddress(FrameAddress address) const; |
| |
| // Returns the next valid address on the bus in numerically increasing |
| // order. If the next address would fall outside this bus, no object is |
| // returned. |
| absl::optional<FrameAddress> GetNextFrameAddress( |
| FrameAddress address) const; |
| |
| private: |
| friend struct YAML::convert<ConfigurationBus>; |
| |
| std::map<unsigned int, ConfigurationColumn> configuration_columns_; |
| }; |
| |
| template <typename T> |
| ConfigurationBus::ConfigurationBus(T first, T last) { |
| assert( |
| std::all_of(first, last, [&](const typename T::value_type& addr) { |
| return (addr.block_type() == first->block_type() && |
| addr.row() == first->row()); |
| })); |
| |
| std::sort(first, last, |
| [](const FrameAddress& lhs, const FrameAddress& rhs) { |
| return lhs.column() < rhs.column(); |
| }); |
| |
| for (auto col_first = first; col_first != last;) { |
| auto col_last = std::upper_bound( |
| col_first, last, col_first->column(), |
| [](const unsigned int& lhs, const FrameAddress& rhs) { |
| return lhs < rhs.column(); |
| }); |
| |
| configuration_columns_.emplace( |
| col_first->column(), |
| std::move(ConfigurationColumn(col_first, col_last))); |
| col_first = col_last; |
| } |
| } |
| |
| } // namespace xcuseries |
| } // namespace xilinx |
| } // namespace prjxray |
| |
| namespace YAML { |
| template <> |
| struct convert<prjxray::xilinx::xcuseries::ConfigurationBus> { |
| static Node encode( |
| const prjxray::xilinx::xcuseries::ConfigurationBus& rhs); |
| static bool decode(const Node& node, |
| prjxray::xilinx::xcuseries::ConfigurationBus& lhs); |
| }; |
| } // namespace YAML |
| |
| #endif // PRJXRAY_LIB_XILINX_XCUSERIES_CONFIGURATION_BUS_H_ |