forked from f4pga/prjxray
-
Notifications
You must be signed in to change notification settings - Fork 0
/
xc7patch.cc
155 lines (137 loc) · 4.6 KB
/
xc7patch.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
* Copyright (C) 2017-2020 The Project X-Ray Authors.
*
* Use of this source code is governed by a ISC-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/ISC
*
* SPDX-License-Identifier: ISC
*/
#include <iostream>
#include <gflags/gflags.h>
#include <prjxray/memory_mapped_file.h>
#include <prjxray/xilinx/architectures.h>
#include <prjxray/xilinx/bitstream_reader.h>
#include <prjxray/xilinx/bitstream_writer.h>
#include <prjxray/xilinx/configuration.h>
DEFINE_string(part_name, "", "");
DEFINE_string(part_file, "", "Definition file for target 7-series part");
DEFINE_string(bitstream_file,
"",
"Initial bitstream to which the deltas are applied.");
DEFINE_string(
frm_file,
"",
"File containing a list of frame deltas to be applied to the base "
"bitstream. Each line in the file is of the form: "
"<frame_address> <word1>,...,<word101>.");
DEFINE_string(output_file, "", "Write patched bitsteam to file");
DEFINE_string(architecture,
"Series7",
"Architecture of the provided bitstream");
namespace xilinx = prjxray::xilinx;
template <typename ArchType>
int patch_frames(
const std::string& frm_file_str,
std::map<typename ArchType::FrameAddress, std::vector<uint32_t>>* frames) {
xilinx::Frames<ArchType> frames_from_file;
if (frames_from_file.readFrames(frm_file_str)) {
std::cerr << "Failed to read frames" << std::endl;
return 1;
}
// Apply the deltas.
for (auto& frame : frames_from_file.getFrames()) {
auto iter = frames->find(frame.first);
if (iter == frames->end()) {
std::cerr << "frame address 0x" << std::hex
<< static_cast<uint32_t>(frame.first)
<< " because it was not found in frames."
<< std::endl;
return 1;
}
auto& frame_data = iter->second;
frame_data = frame.second;
}
return 0;
}
struct BitstreamPatcher {
template <typename T>
int operator()(T& arg) {
using ArchType = std::decay_t<decltype(arg)>;
auto part = ArchType::Part::FromFile(FLAGS_part_file);
if (!part) {
std::cerr << "Part file not found or invalid"
<< std::endl;
return 1;
}
auto bitstream_file = prjxray::MemoryMappedFile::InitWithFile(
FLAGS_bitstream_file);
if (!bitstream_file) {
std::cerr << "Can't open base bitstream file: "
<< FLAGS_bitstream_file << std::endl;
return 1;
}
auto bitstream_reader =
xilinx::BitstreamReader<ArchType>::InitWithBytes(
bitstream_file->as_bytes());
if (!bitstream_reader) {
std::cout << "Bitstream does not appear to be a "
"7-series bitstream!"
<< std::endl;
return 1;
}
auto bitstream_config =
xilinx::Configuration<ArchType>::InitWithPackets(
*part, *bitstream_reader);
if (!bitstream_config) {
std::cerr
<< "Bitstream does not appear to be for this part"
<< std::endl;
return 1;
}
// Copy the base frames to a mutable collection
std::map<typename ArchType::FrameAddress, std::vector<uint32_t>>
frames;
for (auto& frame_val : bitstream_config->frames()) {
auto& cur_frame = frames[frame_val.first];
std::copy(frame_val.second.begin(),
frame_val.second.end(),
std::back_inserter(cur_frame));
}
if (!FLAGS_frm_file.empty()) {
int ret =
patch_frames<ArchType>(FLAGS_frm_file, &frames);
if (ret != 0) {
return ret;
}
}
// Create data for the type 2 configuration packet with
// information about all frames
typename xilinx::Configuration<ArchType>::PacketData
configuration_packet_data(
xilinx::Configuration<ArchType>::
createType2ConfigurationPacketData(frames, part));
// Put together a configuration package
typename ArchType::ConfigurationPackage configuration_package;
xilinx::Configuration<ArchType>::createConfigurationPackage(
configuration_package, configuration_packet_data, part);
// Write bitstream.
auto bitstream_writer =
xilinx::BitstreamWriter<ArchType>(configuration_package);
if (bitstream_writer.writeBitstream(
configuration_package, FLAGS_part_name, FLAGS_frm_file,
"xc7patch", FLAGS_output_file)) {
std::cerr << "Failed to write bitstream" << std::endl
<< "Exitting" << std::endl;
}
return 0;
}
};
int main(int argc, char* argv[]) {
gflags::SetUsageMessage(argv[0]);
gflags::ParseCommandLineFlags(&argc, &argv, true);
xilinx::Architecture::Container arch_container =
xilinx::ArchitectureFactory::create_architecture(
FLAGS_architecture);
return absl::visit(BitstreamPatcher(), arch_container);
}