Skip to content

Commit 88f60fd

Browse files
committed
xilinx: added xilinx 7 series architecture definitions and configuration packet
1 parent 2f49a1c commit 88f60fd

13 files changed

+736
-16
lines changed

MODULE.bazel

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,7 @@ git_override(
1616
bazel_dep(name = "abseil-cpp", version = "20240722.0.bcr.2")
1717
bazel_dep(name = "googletest", version = "1.15.2")
1818
bazel_dep(name = "rapidjson", version = "1.1.0.bcr.20241007")
19-
20-
## C/C++ deps from local registry.
21-
bazel_dep(name = "prjxray", version = "0.0-583-t1e53270")
22-
git_override(
23-
module_name = "prjxray",
24-
commit = "3a95169e555de315c6b4cb71249107972d944303",
25-
patch_strip = 1,
26-
patches = ["//bazel:prjxray-add-module-bazel.patch"],
27-
remote = "https://github.com/f4pga/prjxray.git",
28-
)
19+
bazel_dep(name = "rules_license", version = "1.0.0")
2920

3021
# compilation DB; build_cleaner
3122
bazel_dep(name = "bant", version = "0.1.14", dev_dependency = True)

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ or install in system directory that requires root-access:
3030
sudo install -D --strip bazel-bin/fpga/fpga-as /usr/local/bin/fpga-as
3131
```
3232

33-
[fasm-spec]: https://fasm.readthedocs.io/en/stable/#
34-
[bazel]: https://bazel.build/
35-
[counter-example]: https://github.com/chipsalliance/f4pga-examples/blob/13f11197b33dae1cde3bf146f317d63f0134eacf/xc7/counter_test/counter.v
36-
3733
# How it works
3834

3935
## Frames generation
@@ -59,3 +55,7 @@ The next step is to locate the tile metadata in the FPGA fabric's `tilegrid.json
5955
* offset: `77`
6056

6157
Using this metadata, you can search the segbits database for the specific feature. By matching the tile_type and the FASM feature name, you can identify the correct configuration bits in the tile type segbits file (`segbits_clblm_r.db`). In this case, you would look for the entry corresponding to CLBLM_R.SLICEM_X0.ALUT.INIT and find the entry for address `[34]`. The value 34_06 then provides the coordinates for the word index and the specific bit index to be set.
58+
59+
[fasm-spec]: https://fasm.readthedocs.io/en/stable/#
60+
[bazel]: https://bazel.build/
61+
[counter-example]: https://github.com/chipsalliance/f4pga-examples/blob/13f11197b33dae1cde3bf146f317d63f0134eacf/xc7/counter_test/counter.v

fpga/assembler.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ int main(int argc, char *argv[]) {
430430
<< '\n';
431431
return EXIT_FAILURE;
432432
}
433-
434433
PrintFrames(frames, std::cout, false);
434+
// Write bitstream
435435
return EXIT_SUCCESS;
436436
}

fpga/database-parsers_test.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include "gtest/gtest.h"
1111

1212
namespace fpga {
13-
1413
template <typename Sink>
1514
void AbslStringify(Sink &sink, const TileFeature &e) {
1615
absl::Format(&sink, "(tile_feature=\"%s\", address=%d)", e.tile_feature,

fpga/xilinx/BUILD

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
2+
load("@rules_license//rules:license.bzl", "license")
3+
4+
package(
5+
default_applicable_licenses = [":license"],
6+
default_visibility = ["//:__subpackages__"],
7+
)
8+
9+
license(
10+
name = "license",
11+
package_name = "xilinx",
12+
license_kind = "@rules_license//licenses/spdx:ISC",
13+
license_text = "LICENSE",
14+
)
15+
16+
cc_library(
17+
name = "big-endian-span",
18+
hdrs = [
19+
"big-endian-span.h",
20+
],
21+
deps = [
22+
"@abseil-cpp//absl/types:span",
23+
],
24+
)
25+
26+
cc_test(
27+
name = "big-endian-span_test",
28+
srcs = [
29+
"big-endian-span_test.cc",
30+
],
31+
deps = [
32+
":big-endian-span",
33+
"@googletest//:gtest",
34+
"@googletest//:gtest_main",
35+
],
36+
)
37+
38+
cc_library(
39+
name = "bit-ops",
40+
hdrs = [
41+
"bit-ops.h",
42+
],
43+
)
44+
45+
cc_test(
46+
name = "bit-ops_test",
47+
srcs = [
48+
"bit-ops_test.cc",
49+
],
50+
deps = [
51+
":bit-ops",
52+
"@googletest//:gtest",
53+
"@googletest//:gtest_main",
54+
],
55+
)
56+
57+
cc_library(
58+
name = "architecture-xc7",
59+
srcs = [
60+
"architecture-xc7.cc",
61+
],
62+
hdrs = [
63+
"architecture-xc7.h",
64+
],
65+
deps = [
66+
":bit-ops",
67+
":configuration-packet",
68+
"@abseil-cpp//absl/types:span",
69+
],
70+
)
71+
72+
cc_library(
73+
name = "configuration-packet",
74+
hdrs = [
75+
"configuration-packet.h",
76+
],
77+
deps = [
78+
"@abseil-cpp//absl/types:optional",
79+
"@abseil-cpp//absl/types:span",
80+
],
81+
)

fpga/xilinx/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Xilinx Bitstream Generation
2+
3+
Most of this code originates from [prjxray][prjxray]. It was imported into this repository to simplify type interfacing and eliminate the dependency on yaml-cpp, which requires exceptions to be enabled.
4+
5+
[prjxray]: https://github.com/f4pga/prjxray/tree/faf9c774a340e39cf6802d009996ed6016e63521/lib

fpga/xilinx/architecture-xc7.cc

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#include "architecture-xc7.h"
2+
3+
#include <cstdint>
4+
#include <optional>
5+
#include <ostream>
6+
7+
#include "absl/types/span.h"
8+
#include "fpga/xilinx/bit-ops.h"
9+
#include "fpga/xilinx/configuration-packet.h"
10+
11+
namespace fpga {
12+
namespace xilinx {
13+
namespace xc7 {
14+
std::ostream &operator<<(std::ostream &o, const ConfigurationRegister &value) {
15+
switch (value) {
16+
case ConfigurationRegister::kCRC: return o << "CRC";
17+
case ConfigurationRegister::kFAR: return o << "Frame Address";
18+
case ConfigurationRegister::kFDRI: return o << "Frame Data Input";
19+
case ConfigurationRegister::kFDRO: return o << "Frame Data Output";
20+
case ConfigurationRegister::kCMD: return o << "Command";
21+
case ConfigurationRegister::kCTL0: return o << "Control 0";
22+
case ConfigurationRegister::kMASK: return o << "Mask for CTL0 and CTL1";
23+
case ConfigurationRegister::kSTAT: return o << "Status";
24+
case ConfigurationRegister::kLOUT: return o << "Legacy Output";
25+
case ConfigurationRegister::kCOR0: return o << "Configuration Option 0";
26+
case ConfigurationRegister::kMFWR: return o << "Multiple Frame Write";
27+
case ConfigurationRegister::kCBC: return o << "Initial CBC Value";
28+
case ConfigurationRegister::kIDCODE: return o << "Device ID";
29+
case ConfigurationRegister::kAXSS: return o << "User Access";
30+
case ConfigurationRegister::kCOR1: return o << "Configuration Option 1";
31+
case ConfigurationRegister::kWBSTAR: return o << "Warm Boot Start Address";
32+
case ConfigurationRegister::kTIMER: return o << "Watchdog Timer";
33+
case ConfigurationRegister::kBOOTSTS: return o << "Boot History Status";
34+
case ConfigurationRegister::kCTL1: return o << "Control 1";
35+
case ConfigurationRegister::kBSPI:
36+
return o << "BPI/SPI Configuration Options";
37+
default: return o << "Unknown";
38+
}
39+
}
40+
41+
ConfigurationPacket::ParseResult ConfigurationPacket::InitWithWordsImpl(
42+
absl::Span<uint32_t> words, const ConfigurationPacket *previous_packet) {
43+
using ConfigurationRegister = ConfigurationRegister;
44+
// Need at least one 32-bit word to have a valid packet header.
45+
if (words.empty() < 1) {
46+
return {words, {}};
47+
}
48+
const ConfigurationPacketType header_type =
49+
static_cast<ConfigurationPacketType>(bit_field_get(words[0], 31, 29));
50+
switch (header_type) {
51+
case ConfigurationPacketType::kNONE:
52+
// Type 0 is emitted at the end of a configuration row
53+
// when BITSTREAM.GENERAL.DEBUGBITSTREAM is set to YES.
54+
// These seem to be padding that are interepreted as
55+
// NOPs. Since Type 0 packets don't exist according to
56+
// UG470 and they seem to be zero-filled, just consume
57+
// the bytes without generating a packet.
58+
return {words.subspan(1),
59+
{{static_cast<uint32_t>(header_type),
60+
Opcode::kNOP,
61+
ConfigurationRegister::kCRC,
62+
{}}}};
63+
case ConfigurationPacketType::kTYPE1: {
64+
const Opcode opcode = static_cast<Opcode>(bit_field_get(words[0], 28, 27));
65+
const ConfigurationRegister address =
66+
static_cast<ConfigurationRegister>(bit_field_get(words[0], 26, 13));
67+
const uint32_t data_word_count = bit_field_get(words[0], 10, 0);
68+
69+
// If the full packet has not been received, return as
70+
// though no valid packet was found.
71+
if (data_word_count > words.size() - 1) {
72+
return {words, {}};
73+
}
74+
75+
return {words.subspan(data_word_count + 1),
76+
{{static_cast<uint32_t>(header_type), opcode, address,
77+
words.subspan(1, data_word_count)}}};
78+
}
79+
case ConfigurationPacketType::kTYPE2: {
80+
std::optional<ConfigurationPacket> packet;
81+
const Opcode opcode = static_cast<Opcode>(bit_field_get(words[0], 28, 27));
82+
const uint32_t data_word_count = bit_field_get(words[0], 26, 0);
83+
84+
// If the full packet has not been received, return as
85+
// though no valid packet was found.
86+
if (data_word_count > words.size() - 1) {
87+
return {words, {}};
88+
}
89+
90+
if (previous_packet) {
91+
packet = ConfigurationPacket(static_cast<uint32_t>(header_type), opcode,
92+
previous_packet->address(),
93+
words.subspan(1, data_word_count));
94+
}
95+
96+
return {words.subspan(data_word_count + 1), packet};
97+
}
98+
default: return {{}, {}};
99+
}
100+
}
101+
} // namespace xc7
102+
} // namespace xilinx
103+
} // namespace fpga

fpga/xilinx/architecture-xc7.h

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright (C) 2017-2020 The Project X-Ray Authors.
3+
*
4+
* Use of this source code is governed by a ISC-style
5+
* license that can be found in the LICENSE file or at
6+
* https://opensource.org/licenses/ISC
7+
*
8+
* SPDX-License-Identifier: ISC
9+
*/
10+
#ifndef FPGA_XILINX_ARCHITECTURE_H
11+
#define FPGA_XILINX_ARCHITECTURE_H
12+
13+
#include <cstdint>
14+
#include <memory>
15+
#include <ostream>
16+
#include <vector>
17+
18+
#include "absl/types/span.h"
19+
#include "fpga/xilinx/configuration-packet.h"
20+
21+
namespace fpga {
22+
namespace xilinx {
23+
namespace xc7 {
24+
// Series-7 configuration register addresses
25+
// according to UG470, pg. 109
26+
enum class ConfigurationRegister : unsigned int {
27+
kCRC = 0x00,
28+
kFAR = 0x01,
29+
kFDRI = 0x02,
30+
kFDRO = 0x03,
31+
kCMD = 0x04,
32+
kCTL0 = 0x05,
33+
kMASK = 0x06,
34+
kSTAT = 0x07,
35+
kLOUT = 0x08,
36+
kCOR0 = 0x09,
37+
kMFWR = 0x0a,
38+
kCBC = 0x0b,
39+
kIDCODE = 0x0c,
40+
kAXSS = 0x0d,
41+
kCOR1 = 0x0e,
42+
kWBSTAR = 0x10,
43+
kTIMER = 0x11,
44+
kUNKNOWN = 0x13,
45+
kBOOTSTS = 0x16,
46+
kCTL1 = 0x18,
47+
kBSPI = 0x1F,
48+
};
49+
50+
std::ostream &operator<<(std::ostream &o, const ConfigurationRegister &value);
51+
52+
enum class Architecture {
53+
kBase,
54+
kUltrascale,
55+
kUltrascalePlus,
56+
};
57+
58+
template <Architecture arch>
59+
struct frame_words_count;
60+
61+
template <>
62+
struct frame_words_count<Architecture::kBase> {
63+
static constexpr int value = 101;
64+
};
65+
66+
template <>
67+
struct frame_words_count<Architecture::kUltrascale> {
68+
static constexpr int value = 123;
69+
};
70+
71+
template <>
72+
struct frame_words_count<Architecture::kUltrascalePlus> {
73+
static constexpr int value = 93;
74+
};
75+
76+
template <Architecture arch>
77+
using frame_words_count_v = frame_words_count<arch>::value;
78+
79+
struct Part {};
80+
81+
class ConfigurationPacket
82+
: public ConfigurationPacketBase<ConfigurationRegister,
83+
ConfigurationPacket> {
84+
private:
85+
using BaseType =
86+
ConfigurationPacketBase<ConfigurationRegister, ConfigurationPacket>;
87+
88+
public:
89+
using BaseType::BaseType;
90+
91+
private:
92+
friend BaseType;
93+
static ParseResult InitWithWordsImpl(
94+
absl::Span<uint32_t> words,
95+
const ConfigurationPacket *previous_packet = nullptr);
96+
};
97+
98+
using ConfigurationPackage = std::vector<std::unique_ptr<ConfigurationPacket>>;
99+
} // namespace xc7
100+
} // namespace xilinx
101+
} // namespace fpga
102+
#endif // FPGA_XILINX_ARCHITECTURE_H

0 commit comments

Comments
 (0)