Skip to content

Commit 9cecb32

Browse files
committed
xilinx: generated working bitstream for the counter example
1 parent c00db34 commit 9cecb32

28 files changed

+2399
-149
lines changed

fpga/BUILD

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ load("@rules_license//rules:license.bzl", "license")
33

44
package(
55
default_applicable_licenses = [":license"],
6+
default_visibility = ["//:__subpackages__"],
67
)
78

89
license(
@@ -38,6 +39,7 @@ cc_library(
3839
"@abseil-cpp//absl/status",
3940
"@abseil-cpp//absl/status:statusor",
4041
"@abseil-cpp//absl/strings:str_format",
42+
"@abseil-cpp//absl/types:span",
4143
],
4244
)
4345

@@ -134,6 +136,8 @@ cc_binary(
134136
":database-parsers",
135137
":fasm-parser",
136138
":memory-mapped-file",
139+
"//fpga/xilinx:arch-types",
140+
"//fpga/xilinx:bitstream",
137141
"@abseil-cpp//absl/cleanup:cleanup",
138142
"@abseil-cpp//absl/container:flat_hash_map",
139143
"@abseil-cpp//absl/container:flat_hash_set",

fpga/assembler.cc

+14-2
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@
2323
#include "absl/strings/numbers.h"
2424
#include "absl/strings/str_cat.h"
2525
#include "absl/strings/str_format.h"
26-
#include "absl/strings/str_join.h"
2726
#include "absl/strings/str_split.h"
2827
#include "fpga/database-parsers.h"
2928
#include "fpga/database.h"
3029
#include "fpga/fasm-parser.h"
30+
#include "fpga/xilinx/arch-types.h"
31+
#include "fpga/xilinx/bitstream.h"
3132

3233
struct TileSiteInfo {
3334
std::string tile;
@@ -330,6 +331,7 @@ static absl::StatusOr<std::string> GetOptFlagOrFromEnv(
330331
return flag_value.value();
331332
}
332333

334+
#if 0
333335
static void GetPrettyFrameLine(
334336
const uint32_t address,
335337
const std::array<fpga::word_t, fpga::kFrameWordCount> &bits,
@@ -369,6 +371,7 @@ static void PrintFrames(const fpga::Frames &frames, std::ostream &out,
369371
}
370372
}
371373
}
374+
#endif
372375

373376
int main(int argc, char *argv[]) {
374377
const std::string usage = Usage(argv[0]);
@@ -430,7 +433,16 @@ int main(int argc, char *argv[]) {
430433
<< '\n';
431434
return EXIT_FAILURE;
432435
}
433-
PrintFrames(frames, std::cout, false);
436+
const fpga::Part &part_data = part_database_result->tiles().part;
437+
const auto bitstream_status =
438+
fpga::xilinx::BitStream<fpga::xilinx::Architecture::kXC7>::Encode<
439+
fpga::Frames>(part_data, "fasm", "fpga-source", frames, std::cout);
440+
if (!bitstream_status.ok()) {
441+
std::cerr << StatusToErrorMessage("could not generate bistream",
442+
bitstream_status)
443+
<< '\n';
444+
return EXIT_FAILURE;
445+
}
434446
// Write bitstream
435447
return EXIT_SUCCESS;
436448
}

fpga/database-parsers.cc

+8-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <optional>
1010
#include <string>
1111
#include <string_view>
12+
#include <utility>
1213
#include <vector>
1314

1415
#include "absl/base/optimization.h"
@@ -354,9 +355,13 @@ absl::StatusOr<Part> Unmarshal(const rapidjson::Value &json) {
354355
struct Part part;
355356
OK_OR_RETURN(IsObject(json));
356357
ASSIGN_OR_RETURN(part.idcode, GetMember<uint32_t>(json, "idcode"));
357-
ASSIGN_OR_RETURN(
358-
part.iobanks,
359-
(GetMember<absl::flat_hash_map<uint32_t, std::string>>(json, "iobanks")));
358+
std::optional<IOBanksIDsToLocation> iobanks;
359+
ASSIGN_OR_RETURN(iobanks,
360+
(OptGetMember<absl::flat_hash_map<uint32_t, std::string>>(
361+
json, "iobanks")));
362+
if (iobanks) {
363+
part.iobanks = std::move(iobanks.value());
364+
}
360365
ASSIGN_OR_RETURN(part.global_clock_regions, (GetMember<GlobalClockRegions>(
361366
json, "global_clock_regions")));
362367
return part;

fpga/database-parsers.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ struct SegmentBit {
8585
// Word index of the bit to enable.
8686
uint32_t word_bit;
8787

88-
// If the char '!' is prepended.
88+
// False if the char '!' is prepended.
8989
bool is_set;
9090
};
9191

fpga/database.cc

+19-20
Original file line numberDiff line numberDiff line change
@@ -280,19 +280,7 @@ absl::StatusOr<SegmentsBitsWithPseudoPIPs> ParseTileTypeDatabase(
280280
}
281281

282282
absl::StatusOr<fpga::BanksTilesRegistry> CreateBanksRegistry(
283-
const std::filesystem::path &part_json_path,
284-
const std::filesystem::path &package_pins_path) {
285-
// Parse part.json.
286-
const absl::StatusOr<std::unique_ptr<fpga::MemoryBlock>> part_json_result =
287-
fpga::MemoryMapFile(part_json_path);
288-
if (!part_json_result.ok()) return part_json_result.status();
289-
const absl::StatusOr<fpga::Part> part_result =
290-
fpga::ParsePartJSON(part_json_result.value()->AsStringView());
291-
if (!part_result.ok()) {
292-
return part_result.status();
293-
}
294-
const fpga::Part &part = part_result.value();
295-
283+
const fpga::Part &part, const std::filesystem::path &package_pins_path) {
296284
// Parse package pins.
297285
const absl::StatusOr<std::unique_ptr<fpga::MemoryBlock>>
298286
package_pins_csv_result = fpga::MemoryMapFile(package_pins_path);
@@ -344,16 +332,27 @@ absl::StatusOr<PartDatabase> PartDatabase::Parse(std::string_view database_path,
344332
}
345333
return {};
346334
};
347-
auto banks_tiles_registry_result = CreateBanksRegistry(
348-
std::filesystem::path(database_path) / part_name / "part.json",
349-
std::filesystem::path(database_path) / part_name / "package_pins.csv");
335+
// Parse part.json.
336+
const absl::StatusOr<std::unique_ptr<fpga::MemoryBlock>> part_json_result =
337+
fpga::MemoryMapFile(std::filesystem::path(database_path) / part_name /
338+
"part.json");
339+
if (!part_json_result.ok()) return part_json_result.status();
340+
const absl::StatusOr<fpga::Part> part_result =
341+
fpga::ParsePartJSON(part_json_result.value()->AsStringView());
342+
if (!part_result.ok()) {
343+
return part_result.status();
344+
}
345+
const fpga::Part &part = part_result.value();
346+
347+
auto banks_tiles_registry_result =
348+
CreateBanksRegistry(part, std::filesystem::path(database_path) / part_name /
349+
"package_pins.csv");
350350
if (!banks_tiles_registry_result.ok()) {
351351
return banks_tiles_registry_result.status();
352352
}
353-
const Tiles tiles_foo(std::move(tilegrid_result.value()),
354-
std::move(tiles_database),
355-
std::move(banks_tiles_registry_result.value()));
356-
const std::shared_ptr<Tiles> tiles = std::make_shared<Tiles>(tiles_foo);
353+
const std::shared_ptr<Tiles> tiles = std::make_shared<Tiles>(
354+
std::move(tilegrid_result.value()), std::move(tiles_database),
355+
std::move(banks_tiles_registry_result.value()), part);
357356
return absl::StatusOr<PartDatabase>(tiles);
358357
}
359358

fpga/database.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,15 @@ class PartDatabase {
7474
~PartDatabase() = default;
7575
struct Tiles {
7676
Tiles(TileGrid grid, TileTypesSegmentsBitsGetter bits,
77-
BanksTilesRegistry banks)
77+
BanksTilesRegistry banks, Part part)
7878
: grid(std::move(grid)),
7979
bits(std::move(bits)),
80-
banks(std::move(banks)) {}
80+
banks(std::move(banks)),
81+
part(std::move(part)) {}
8182
TileGrid grid;
8283
TileTypesSegmentsBitsGetter bits;
8384
BanksTilesRegistry banks;
85+
Part part;
8486
};
8587
explicit PartDatabase(std::shared_ptr<Tiles> part_tiles)
8688
: tiles_(std::move(part_tiles)) {}

fpga/memory-mapped-file.h

+6
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
#ifndef FPGA_MEMORY_MAPPED_FILE_H
22
#define FPGA_MEMORY_MAPPED_FILE_H
33

4+
#include <cstdint>
45
#include <filesystem>
56
#include <memory>
67
#include <string>
78
#include <string_view>
89

910
#include "absl/status/statusor.h"
11+
#include "absl/types/span.h"
1012

1113
namespace fpga {
1214
// Taken from: verible/common/strings/mem-block.h
1315
class MemoryBlock {
1416
public:
1517
virtual ~MemoryBlock() = default;
1618
virtual std::string_view AsStringView() const = 0;
19+
absl::Span<const uint8_t> AsBytesView() const {
20+
std::string_view const bytes = AsStringView();
21+
return {reinterpret_cast<const uint8_t *>(bytes.data()), bytes.size()};
22+
}
1723

1824
protected:
1925
MemoryBlock() = default;

fpga/xilinx/BUILD

+95
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ cc_library(
130130
],
131131
deps = [
132132
":arch-xc7-frame",
133+
"//fpga:database-parsers",
134+
"//fpga:memory-mapped-file",
135+
"@abseil-cpp//absl/log:check",
136+
"@abseil-cpp//absl/status:statusor",
133137
],
134138
)
135139

@@ -206,15 +210,106 @@ cc_test(
206210
srcs = [
207211
"configuration-xc7_test.cc",
208212
],
213+
data = [
214+
"testdata/xc7-configuration.bit",
215+
"testdata/xc7-configuration.debug.bit",
216+
"testdata/xc7-configuration.perframecrc.bit",
217+
"testdata/xc7-configuration-test.json",
218+
],
209219
deps = [
210220
":arch-types",
211221
":arch-xc7-frame",
222+
":bitstream-reader",
212223
":configuration",
213224
":configuration-packet",
214225
":frames",
226+
"//fpga:database-parsers",
227+
"//fpga:memory-mapped-file",
228+
"@abseil-cpp//absl/status:statusor",
215229
"@abseil-cpp//absl/types:optional",
216230
"@abseil-cpp//absl/types:span",
217231
"@googletest//:gtest",
218232
"@googletest//:gtest_main",
219233
],
220234
)
235+
236+
cc_library(
237+
name = "bitstream-reader",
238+
hdrs = [
239+
"bitstream-reader.h",
240+
],
241+
deps = [
242+
":arch-types",
243+
":big-endian-span",
244+
"@abseil-cpp//absl/types:optional",
245+
"@abseil-cpp//absl/types:span",
246+
],
247+
)
248+
249+
cc_test(
250+
name = "bitstream-reader_test",
251+
srcs = [
252+
"bitstream-reader-xc7_test.cc",
253+
],
254+
deps = [
255+
":arch-types",
256+
":bitstream-reader",
257+
"@abseil-cpp//absl/types:span",
258+
"@googletest//:gtest_main",
259+
],
260+
)
261+
262+
cc_library(
263+
name = "bitstream-writer",
264+
srcs = [
265+
"bitstream-writer.cc",
266+
],
267+
hdrs = [
268+
"bitstream-writer.h",
269+
],
270+
deps = [
271+
":arch-types",
272+
":arch-xc7-configuration-packet",
273+
":bit-ops",
274+
":configuration-packet",
275+
"@abseil-cpp//absl/log:check",
276+
"@abseil-cpp//absl/strings",
277+
"@abseil-cpp//absl/time",
278+
"@abseil-cpp//absl/types:optional",
279+
"@abseil-cpp//absl/types:span",
280+
],
281+
)
282+
283+
cc_test(
284+
name = "bitstream-writer_test",
285+
srcs = [
286+
"bitstream-writer_test.cc",
287+
],
288+
deps = [
289+
":arch-types",
290+
":arch-xc7-configuration-packet",
291+
":bit-ops",
292+
":bitstream-writer",
293+
":configuration-packet",
294+
"@abseil-cpp//absl/types:span",
295+
"@googletest//:gtest",
296+
"@googletest//:gtest_main",
297+
],
298+
)
299+
300+
cc_library(
301+
name = "bitstream",
302+
hdrs = [
303+
"bitstream.h",
304+
],
305+
deps = [
306+
":arch-types",
307+
":bitstream-writer",
308+
":configuration",
309+
":frames",
310+
"//fpga:database-parsers",
311+
"@abseil-cpp//absl/status",
312+
"@abseil-cpp//absl/status:statusor",
313+
"@abseil-cpp//absl/strings:string_view",
314+
],
315+
)

fpga/xilinx/arch-xc7-configuration-packet.h

-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ class ConfigurationPacket
7979
private:
8080
using BaseType =
8181
ConfigurationPacketBase<ConfigurationRegister, ConfigurationPacket>;
82-
using ParseResult = BaseType::ParseResult;
8382

8483
public:
8584
using BaseType::BaseType;

fpga/xilinx/arch-xc7-frame.cc

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ std::ostream &operator<<(std::ostream &o, BlockType value) {
1414
case BlockType::kBlockRam: o << "Block RAM"; break;
1515
case BlockType::kCFGCLB: o << "Config CLB"; break;
1616
case BlockType::kReserved: o << "Reserved"; break;
17+
case BlockType::kInvalid: o << "Invalid"; break;
1718
}
1819
return o;
1920
}

fpga/xilinx/arch-xc7-frame.h

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ enum class BlockType : unsigned int {
5252
kBlockRam = 0x1,
5353
kCFGCLB = 0x2,
5454
kReserved = 0x3,
55+
kInvalid = 0xFFFFFFFF,
5556
};
5657

5758
std::ostream &operator<<(std::ostream &o, BlockType value);

0 commit comments

Comments
 (0)