biststream_tools: Add support for other architectures

Signed-off-by: Tomasz Michalak <tmichalak@antmicro.com>
diff --git a/tools/gen_part_base_yaml.cc b/tools/gen_part_base_yaml.cc
index e5f965f..b07a032 100644
--- a/tools/gen_part_base_yaml.cc
+++ b/tools/gen_part_base_yaml.cc
@@ -16,9 +16,77 @@
 #include <yaml-cpp/yaml.h>
 
 DEFINE_bool(f, false, "Use FAR registers instead of LOUT ones");
-
+DEFINE_string(architecture,
+              "Series7",
+              "Architecture of the provided bitstream");
 namespace xilinx = prjxray::xilinx;
 
+struct YamlWriter {
+	YamlWriter(const absl::Span<uint8_t>& bytes) : bytes_(bytes) {}
+
+	const absl::Span<uint8_t>& bytes_;
+
+	template <typename T>
+	int operator()(T& arg) {
+		using ArchType =std::decay_t<decltype(arg)>;
+		auto reader = xilinx::BitstreamReader<ArchType>::InitWithBytes(bytes_);
+		if (!reader) {
+			std::cerr << "Input doesn't look like a bitstream" << std::endl;
+			return 1;
+		}
+
+		bool found_fdri_write = false;
+		std::vector<typename ArchType::FrameAddress> frame_addresses;
+		absl::optional<uint32_t> idcode;
+		for (auto packet : *reader) {
+			if (packet.opcode() !=
+					xilinx::ConfigurationPacket<
+					typename ArchType::ConfRegType>::Opcode::Write) {
+				continue;
+			}
+
+			if (packet.address() == ArchType::ConfRegType::FDRI) {
+				found_fdri_write = true;
+			} else if ((packet.address() ==
+						ArchType::ConfRegType::IDCODE) &&
+					packet.data().size() == 1) {
+				idcode = packet.data()[0];
+			} else if (found_fdri_write &&
+					(packet.address() ==
+					 ArchType::ConfRegType::LOUT) &&
+					(packet.data().size() == 1) && FLAGS_f == false) {
+				frame_addresses.push_back(packet.data()[0]);
+				found_fdri_write = false;
+			} else if (found_fdri_write &&
+					(packet.address() ==
+					 ArchType::ConfRegType::FAR) &&
+					(packet.data().size() == 1) && FLAGS_f == true) {
+				frame_addresses.push_back(packet.data()[0]);
+				found_fdri_write = false;
+			}
+		}
+
+		if (!idcode) {
+			std::cerr << "No IDCODE found." << std::endl;
+			return 1;
+		}
+
+		if (frame_addresses.empty()) {
+			std::cerr << "No LOUT or FAR writes found.  Was "
+				<< "BITSTREAM.GENERAL.DEBUGBITSTREAM or "
+				<< "BITSTREAM.GENERAL.PERFRAMECRC set to YES?"
+				<< std::endl;
+			return 1;
+		}
+
+		auto part = typename ArchType::Part(*idcode, frame_addresses.begin(),
+	                                  frame_addresses.end());
+		std::cout << YAML::Node(part) << std::endl;
+		return 0;
+	}
+
+};
+
 int main(int argc, char* argv[]) {
 	gflags::SetUsageMessage(
 	    absl::StrCat("Usage: ", argv[0], " [bitfile] [options]"));
@@ -38,61 +106,16 @@
 		          << std::endl;
 		return 1;
 	}
+ 	auto in_bytes = absl::Span<uint8_t>(
+            static_cast<uint8_t*>(in_file->data()), in_file->size());
 
-	auto reader = xilinx::BitstreamReader<xilinx::Series7>::InitWithBytes(
-	    in_file->as_bytes());
-	if (!reader) {
-		std::cerr << "Input doesn't look like a bitstream" << std::endl;
-		return 1;
+
+	try {
+		xilinx::Architecture::Container arch_container =
+			xilinx::ArchitectureFactory::create_architecture(FLAGS_architecture);
+		return absl::visit(YamlWriter(in_bytes), arch_container);
+	} catch (absl::bad_variant_access &e) {
+		std::cerr << "Error: Incorrect architecture. Supported architectures: Series7, Spartan6, UltraScale, UltraScalePlus.\n";
 	}
-
-	bool found_fdri_write = false;
-	std::vector<xilinx::Series7::FrameAddress> frame_addresses;
-	absl::optional<uint32_t> idcode;
-	for (auto packet : *reader) {
-		if (packet.opcode() !=
-		    xilinx::ConfigurationPacket<
-		        xilinx::Series7::ConfRegType>::Opcode::Write) {
-			continue;
-		}
-
-		if (packet.address() == xilinx::Series7::ConfRegType::FDRI) {
-			found_fdri_write = true;
-		} else if ((packet.address() ==
-		            xilinx::Series7::ConfRegType::IDCODE) &&
-		           packet.data().size() == 1) {
-			idcode = packet.data()[0];
-		} else if (found_fdri_write &&
-		           (packet.address() ==
-		            xilinx::Series7::ConfRegType::LOUT) &&
-		           (packet.data().size() == 1) && FLAGS_f == false) {
-			frame_addresses.push_back(packet.data()[0]);
-			found_fdri_write = false;
-		} else if (found_fdri_write &&
-		           (packet.address() ==
-		            xilinx::Series7::ConfRegType::FAR) &&
-		           (packet.data().size() == 1) && FLAGS_f == true) {
-			frame_addresses.push_back(packet.data()[0]);
-			found_fdri_write = false;
-		}
-	}
-
-	if (!idcode) {
-		std::cerr << "No IDCODE found." << std::endl;
-		return 1;
-	}
-
-	if (frame_addresses.empty()) {
-		std::cerr << "No LOUT or FAR writes found.  Was "
-		          << "BITSTREAM.GENERAL.DEBUGBITSTREAM or "
-		          << "BITSTREAM.GENERAL.PERFRAMECRC set to YES?"
-		          << std::endl;
-		return 1;
-	}
-
-	auto part = xilinx::Series7::Part(*idcode, frame_addresses.begin(),
-	                                  frame_addresses.end());
-	std::cout << YAML::Node(part) << std::endl;
-
-	return 0;
 }
+