#include #include #include #include #include #include #include namespace xc7series = prjxray::xilinx::xc7series; struct Action { std::string name; std::function handler; }; int ListConfigPackets(int argc, char* argv[]) { if (argc < 1) { std::cerr << "ERROR: no input specified" << std::endl; std::cerr << "Usage: " << argv[0] << "list_config_packets " << std::endl; return 1; } auto in_file_name = argv[0]; auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name); if (!in_file) { std::cerr << "Unable to open bit file: " << in_file_name << std::endl; return 1; } auto reader = xc7series::BitstreamReader::InitWithBytes(in_file->as_bytes()); if (!reader) { std::cerr << "Input doesn't look like a bitstream" << std::endl; return 1; } for (auto packet : *reader) { std::cout << packet; } return 0; } int DumpDebugbitstreamFrameAddresses(int argc, char* argv[]) { if (argc < 1) { std::cerr << "ERROR: no input specified" << std::endl; std::cerr << "Usage: " << argv[0] << "dump_debugbitstream_frame_addresses " << std::endl; return 1; } auto in_file_name = argv[0]; auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name); if (!in_file) { std::cerr << "Unable to open bit file: " << in_file_name << std::endl; return 1; } auto in_bytes = absl::Span( static_cast(in_file->data()), in_file->size()); auto reader = xc7series::BitstreamReader::InitWithBytes(in_bytes); if (!reader) { std::cerr << "Input doesn't look like a bitstream" << std::endl; return 1; } bool found_one_lout = false; for (auto packet : *reader) { if ((packet.opcode() != xc7series::ConfigurationPacket::Opcode::Write) || (packet.address() != xc7series::ConfigurationRegister::LOUT)) { continue; } if (packet.data().size() != 1) { std::cerr << "Write to FAR with word_count != 1" << std::endl; continue; } found_one_lout = true; std::cout << std::dec << packet.data()[0] << std::endl; } if (!found_one_lout) { std::cerr << "No LOUT writes found. Was " << "BITSTREAM.GENERAL.DEBUGBITSTREAM set to YES?" << std::endl; return 1; } return 0; } int GetDeviceId(int argc, char* argv[]) { if (argc < 1) { std::cerr << "ERROR: no input specified" << std::endl; std::cerr << "Usage: " << argv[0] << "get_device_id " << std::endl; return 1; } auto in_file_name = argv[0]; auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name); if (!in_file) { std::cerr << "Unable to open bit file: " << in_file_name << std::endl; return 1; } auto in_bytes = absl::Span( static_cast(in_file->data()), in_file->size()); auto reader = xc7series::BitstreamReader::InitWithBytes(in_bytes); if (!reader) { std::cerr << "Input doesn't look like a bitstream" << std::endl; return 1; } auto idcode_packet = std::find_if( reader->begin(), reader->end(), [](const xc7series::ConfigurationPacket& packet) { return (packet.opcode() == xc7series::ConfigurationPacket::Opcode::Write) && (packet.address() == xc7series::ConfigurationRegister::IDCODE); }); if (idcode_packet != reader->end()) { if (idcode_packet->data().size() != 1) { std::cerr << "Write to IDCODE with word_count != 1" << std::endl; return 1; } std::cout << "0x" << std::hex << idcode_packet->data()[0] << std::endl; } return 0; } int main(int argc, char* argv[]) { Action actions[] = { {"list_config_packets", ListConfigPackets}, {"dump_debugbitstream_frame_addresses", DumpDebugbitstreamFrameAddresses}, {"get_device_id", GetDeviceId}, }; gflags::SetUsageMessage( absl::StrCat("Usage: ", argv[0], " [options] [bitfile]")); gflags::ParseCommandLineFlags(&argc, &argv, true); if (argc < 2) { std::cerr << "ERROR: no command specified" << std::endl; std::cerr << "Usage: " << argv[0] << " " << std::endl; return 1; } auto requested_action_str = argv[1]; auto requested_action = std::find_if( std::begin(actions), std::end(actions), [&](const Action& t) { return t.name == requested_action_str; }); if (requested_action == std::end(actions)) { std::cerr << "Unknown action: " << requested_action_str << std::endl; return 1; } return requested_action->handler(argc - 2, argv + 2); }