#include #include #include namespace prjxray { namespace xilinx { namespace xc7series { absl::optional Part::FromFile(const std::string& path) { try { YAML::Node yaml = YAML::LoadFile(path); return yaml.as(); } catch (YAML::Exception e) { return {}; } } bool Part::IsValidFrameAddress(FrameAddress address) const { if (address.is_bottom_half_rows()) { return bottom_region_.IsValidFrameAddress(address); } else { return top_region_.IsValidFrameAddress(address); } } absl::optional Part::GetNextFrameAddress( FrameAddress address) const { // Ask the current global clock region first. absl::optional next_address = (address.is_bottom_half_rows() ? bottom_region_.GetNextFrameAddress(address) : top_region_.GetNextFrameAddress(address)); if (next_address) return next_address; // If the current address is in the top region, the bottom region is // next numerically. if (!address.is_bottom_half_rows()) { next_address = FrameAddress(address.block_type(), true, 0, 0, 0); if (bottom_region_.IsValidFrameAddress(*next_address)) return next_address; } // Block types are next numerically. if (address.block_type() < BlockType::BLOCK_RAM) { next_address = FrameAddress(BlockType::BLOCK_RAM, false, 0, 0, 0); if (IsValidFrameAddress(*next_address)) return next_address; } if (address.block_type() < BlockType::CFG_CLB) { next_address = FrameAddress(BlockType::CFG_CLB, false, 0, 0, 0); if (IsValidFrameAddress(*next_address)) return next_address; } return {}; } } // namespace xc7series } // namespace xilinx } // namespace prjxray namespace xc7series = prjxray::xilinx::xc7series; namespace YAML { Node convert::encode(const xc7series::Part& rhs) { Node node; node.SetTag("xilinx/xc7series/part"); std::ostringstream idcode_str; idcode_str << "0x" << std::hex << rhs.idcode_; node["idcode"] = idcode_str.str(); node["global_clock_regions"]["top"] = rhs.top_region_; node["global_clock_regions"]["bottom"] = rhs.bottom_region_; return node; } bool convert::decode(const Node& node, xc7series::Part& lhs) { if (!node.Tag().empty() && node.Tag() != "xilinx/xc7series/part") return false; if (!node["global_clock_regions"] && !node["configuration_ranges"]) { return false; } lhs.idcode_ = node["idcode"].as(); if (node["global_clock_regions"]) { lhs.top_region_ = node["global_clock_regions"]["top"] .as(); lhs.bottom_region_ = node["global_clock_regions"]["bottom"] .as(); } else if (node["configuration_ranges"]) { std::vector addresses; for (auto range : node["configuration_ranges"]) { auto begin = range["begin"].as(); auto end = range["end"].as(); for (uint32_t cur = begin; cur < end; ++cur) { addresses.push_back(cur); } } lhs = xc7series::Part(lhs.idcode_, addresses); } return true; }; } // namespace YAML