mirror of https://github.com/openXC7/prjxray.git
Apply clang-format to all C++ files
Signed-off-by: Rick Altherr <kc8apf@kc8apf.net>
This commit is contained in:
parent
c1676cb0f1
commit
50d2521b33
|
|
@ -44,28 +44,24 @@ TEST(BitFieldGetTest, SelectMidway) {
|
|||
|
||||
TEST(BitFieldSetTest, WriteOneBit) {
|
||||
uint32_t actual = prjxray::bit_field_set(
|
||||
static_cast<uint32_t>(0x0), 23, 23,
|
||||
static_cast<uint32_t>(0x1));
|
||||
static_cast<uint32_t>(0x0), 23, 23, static_cast<uint32_t>(0x1));
|
||||
EXPECT_EQ(actual, static_cast<uint32_t>(0x800000));
|
||||
}
|
||||
|
||||
TEST(BitFieldSetTest, WriteOneBitWithOutOfRangeValue) {
|
||||
uint32_t actual = prjxray::bit_field_set(
|
||||
static_cast<uint32_t>(0x0), 23, 23,
|
||||
static_cast<uint32_t>(0x3));
|
||||
static_cast<uint32_t>(0x0), 23, 23, static_cast<uint32_t>(0x3));
|
||||
EXPECT_EQ(actual, static_cast<uint32_t>(0x800000));
|
||||
}
|
||||
|
||||
TEST(BitFieldSetTest, WriteMultipleBits) {
|
||||
uint32_t actual = prjxray::bit_field_set(
|
||||
static_cast<uint32_t>(0x0), 18, 8,
|
||||
static_cast<uint32_t>(0x123));
|
||||
static_cast<uint32_t>(0x0), 18, 8, static_cast<uint32_t>(0x123));
|
||||
EXPECT_EQ(actual, static_cast<uint32_t>(0x12300));
|
||||
}
|
||||
|
||||
TEST(BitFieldSetTest, WriteMultipleBitsWithOutOfRangeValue) {
|
||||
uint32_t actual = prjxray::bit_field_set(
|
||||
static_cast<uint32_t>(0x0), 18, 8,
|
||||
static_cast<uint32_t>(0x1234));
|
||||
static_cast<uint32_t>(0x0), 18, 8, static_cast<uint32_t>(0x1234));
|
||||
EXPECT_EQ(actual, static_cast<uint32_t>(0x23400));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,20 +10,20 @@ namespace prjxray {
|
|||
|
||||
static constexpr const char kSegbitsGlobPattern[] = "segbits_*.db";
|
||||
|
||||
std::vector<std::unique_ptr<prjxray::SegbitsFileReader>> Database::segbits() const {
|
||||
std::vector<std::unique_ptr<prjxray::SegbitsFileReader>> Database::segbits()
|
||||
const {
|
||||
std::vector<std::unique_ptr<prjxray::SegbitsFileReader>> segbits;
|
||||
|
||||
glob_t segbits_glob_results;
|
||||
int ret = glob(absl::StrCat(db_path_, "/", kSegbitsGlobPattern).c_str(),
|
||||
GLOB_NOSORT | GLOB_TILDE,
|
||||
NULL, &segbits_glob_results);
|
||||
GLOB_NOSORT | GLOB_TILDE, NULL, &segbits_glob_results);
|
||||
if (ret < 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
for(size_t idx = 0; idx < segbits_glob_results.gl_pathc; idx++) {
|
||||
for (size_t idx = 0; idx < segbits_glob_results.gl_pathc; idx++) {
|
||||
auto this_segbit = SegbitsFileReader::InitWithFile(
|
||||
segbits_glob_results.gl_pathv[idx]);
|
||||
segbits_glob_results.gl_pathv[idx]);
|
||||
if (this_segbit) {
|
||||
segbits.emplace_back(std::move(this_segbit));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
|
||||
namespace prjxray {
|
||||
|
||||
template<typename WordType, typename ByteType>
|
||||
template <typename WordType, typename ByteType>
|
||||
class BigEndianSpan {
|
||||
public:
|
||||
public:
|
||||
constexpr static size_t kBytesPerElement = sizeof(WordType);
|
||||
|
||||
using byte_type = ByteType;
|
||||
|
|
@ -18,43 +18,45 @@ class BigEndianSpan {
|
|||
using size_type = std::size_t;
|
||||
|
||||
class value_type {
|
||||
public:
|
||||
public:
|
||||
operator WordType() const {
|
||||
WordType word = 0;
|
||||
for(size_t ii = 0; ii < kBytesPerElement; ++ii) {
|
||||
word |= (static_cast<WordType>(bytes_[ii]) << ((kBytesPerElement - 1 - ii) * 8));
|
||||
for (size_t ii = 0; ii < kBytesPerElement; ++ii) {
|
||||
word |= (static_cast<WordType>(bytes_[ii])
|
||||
<< ((kBytesPerElement - 1 - ii) * 8));
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
value_type& operator=(WordType word) {
|
||||
for (size_t ii = 0; ii < kBytesPerElement; ++ii) {
|
||||
bytes_[ii] = ((word >> ((kBytesPerElement - 1 - ii) * 8)) & 0xFF);
|
||||
bytes_[ii] =
|
||||
((word >>
|
||||
((kBytesPerElement - 1 - ii) * 8)) &
|
||||
0xFF);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
protected:
|
||||
friend class BigEndianSpan<WordType, ByteType>;
|
||||
|
||||
value_type(absl::Span<ByteType> bytes) : bytes_(bytes) {};
|
||||
value_type(absl::Span<ByteType> bytes) : bytes_(bytes){};
|
||||
|
||||
private:
|
||||
private:
|
||||
absl::Span<ByteType> bytes_;
|
||||
};
|
||||
|
||||
class iterator
|
||||
: public std::iterator<std::input_iterator_tag, value_type> {
|
||||
public:
|
||||
value_type operator*() const {
|
||||
return value_type(bytes_);
|
||||
}
|
||||
: public std::iterator<std::input_iterator_tag, value_type> {
|
||||
public:
|
||||
value_type operator*() const { return value_type(bytes_); }
|
||||
|
||||
bool operator==(const iterator &other) const {
|
||||
bool operator==(const iterator& other) const {
|
||||
return bytes_ == other.bytes_;
|
||||
}
|
||||
|
||||
bool operator!=(const iterator &other) const {
|
||||
bool operator!=(const iterator& other) const {
|
||||
return bytes_ != other.bytes_;
|
||||
}
|
||||
|
||||
|
|
@ -63,20 +65,19 @@ class BigEndianSpan {
|
|||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
protected:
|
||||
friend class BigEndianSpan<WordType, ByteType>;
|
||||
|
||||
iterator(absl::Span<ByteType> bytes) : bytes_(bytes) {};
|
||||
iterator(absl::Span<ByteType> bytes) : bytes_(bytes){};
|
||||
|
||||
private:
|
||||
private:
|
||||
absl::Span<ByteType> bytes_;
|
||||
};
|
||||
|
||||
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
|
||||
BigEndianSpan(absl::Span<ByteType> bytes) : bytes_(bytes) {};
|
||||
BigEndianSpan(absl::Span<ByteType> bytes) : bytes_(bytes){};
|
||||
|
||||
constexpr size_type size() const noexcept {
|
||||
return bytes_.size() / kBytesPerElement;
|
||||
|
|
@ -88,7 +89,7 @@ class BigEndianSpan {
|
|||
|
||||
value_type operator[](size_type pos) const {
|
||||
assert(pos >= 0 && pos < size());
|
||||
return value_type(bytes_.subspan((pos*kBytesPerElement)));
|
||||
return value_type(bytes_.subspan((pos * kBytesPerElement)));
|
||||
}
|
||||
|
||||
constexpr reference at(size_type pos) const {
|
||||
|
|
@ -98,16 +99,15 @@ class BigEndianSpan {
|
|||
iterator begin() const { return iterator(bytes_); }
|
||||
iterator end() const { return iterator({}); }
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
absl::Span<ByteType> bytes_;
|
||||
};
|
||||
|
||||
template<typename WordType, typename Container>
|
||||
template <typename WordType, typename Container>
|
||||
BigEndianSpan<WordType, typename Container::value_type> make_big_endian_span(
|
||||
Container &bytes) {
|
||||
Container& bytes) {
|
||||
return BigEndianSpan<WordType, typename Container::value_type>(
|
||||
absl::Span<typename Container::value_type>(bytes));
|
||||
absl::Span<typename Container::value_type>(bytes));
|
||||
}
|
||||
|
||||
} // namespace prjxray
|
||||
|
|
|
|||
|
|
@ -3,41 +3,44 @@
|
|||
|
||||
namespace prjxray {
|
||||
|
||||
template<typename UInt>
|
||||
template <typename UInt>
|
||||
constexpr UInt bit_mask(const int bit) {
|
||||
return (static_cast<UInt>(1) << bit);
|
||||
}
|
||||
|
||||
template<typename UInt>
|
||||
template <typename UInt>
|
||||
constexpr UInt bit_sizeof() {
|
||||
return sizeof(UInt) * 8;
|
||||
}
|
||||
|
||||
template<typename UInt>
|
||||
template <typename UInt>
|
||||
constexpr UInt bit_all_ones() {
|
||||
return ~static_cast<UInt>(0);
|
||||
}
|
||||
|
||||
template<typename UInt>
|
||||
template <typename UInt>
|
||||
constexpr UInt bit_mask_range(const int top_bit, const int bottom_bit) {
|
||||
return ((bit_all_ones<UInt>() >> (bit_sizeof<UInt>() - 1 - top_bit)) &
|
||||
(bit_all_ones<UInt>() - bit_mask<UInt>(bottom_bit) +
|
||||
static_cast<UInt>(1)));
|
||||
(bit_all_ones<UInt>() - bit_mask<UInt>(bottom_bit) +
|
||||
static_cast<UInt>(1)));
|
||||
}
|
||||
|
||||
|
||||
template<typename UInt>
|
||||
constexpr UInt bit_field_get(UInt value, const int top_bit, const int bottom_bit) {
|
||||
return (value & bit_mask_range<UInt>(top_bit, bottom_bit)) >> bottom_bit;
|
||||
template <typename UInt>
|
||||
constexpr UInt bit_field_get(UInt value,
|
||||
const int top_bit,
|
||||
const int bottom_bit) {
|
||||
return (value & bit_mask_range<UInt>(top_bit, bottom_bit)) >>
|
||||
bottom_bit;
|
||||
}
|
||||
|
||||
template<typename UInt, typename ValueType>
|
||||
template <typename UInt, typename ValueType>
|
||||
constexpr UInt bit_field_set(const UInt reg_value,
|
||||
const int top_bit, const int bottom_bit,
|
||||
const ValueType field_value) {
|
||||
const int top_bit,
|
||||
const int bottom_bit,
|
||||
const ValueType field_value) {
|
||||
return ((reg_value & ~bit_mask_range<UInt>(top_bit, bottom_bit)) |
|
||||
((static_cast<UInt>(field_value) << bottom_bit) &
|
||||
bit_mask_range<UInt>(top_bit, bottom_bit)));
|
||||
((static_cast<UInt>(field_value) << bottom_bit) &
|
||||
bit_mask_range<UInt>(top_bit, bottom_bit)));
|
||||
}
|
||||
|
||||
} // namespace prjxray
|
||||
|
|
|
|||
|
|
@ -10,16 +10,15 @@
|
|||
namespace prjxray {
|
||||
|
||||
class Database {
|
||||
public:
|
||||
Database(const std::string &path)
|
||||
: db_path_(path) {}
|
||||
public:
|
||||
Database(const std::string& path) : db_path_(path) {}
|
||||
|
||||
std::vector<std::unique_ptr<SegbitsFileReader>> segbits() const;
|
||||
|
||||
private:
|
||||
private:
|
||||
std::string db_path_;
|
||||
};
|
||||
|
||||
} // namespace prjxray
|
||||
|
||||
#endif // PRJXRAY_LIB_DATABASE_H
|
||||
#endif // PRJXRAY_LIB_DATABASE_H
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@
|
|||
namespace prjxray {
|
||||
|
||||
class MemoryMappedFile {
|
||||
public:
|
||||
public:
|
||||
~MemoryMappedFile();
|
||||
|
||||
static std::unique_ptr<MemoryMappedFile> InitWithFile(
|
||||
const std::string &path);
|
||||
const std::string& path);
|
||||
|
||||
void* const data() const { return data_; }
|
||||
const size_t size() const { return size_; }
|
||||
|
|
@ -22,14 +22,13 @@ class MemoryMappedFile {
|
|||
return {static_cast<uint8_t*>(data_), size_};
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryMappedFile(void *data, size_t size)
|
||||
: data_(data), size_(size) {};
|
||||
private:
|
||||
MemoryMappedFile(void* data, size_t size) : data_(data), size_(size){};
|
||||
|
||||
void *data_;
|
||||
void* data_;
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
} // namespace prjxray
|
||||
} // namespace prjxray
|
||||
|
||||
#endif // PRJXRAY_LIB_MEMORY_MAPPED_FILE
|
||||
|
|
|
|||
|
|
@ -10,39 +10,41 @@
|
|||
namespace prjxray {
|
||||
|
||||
class SegbitsFileReader {
|
||||
public:
|
||||
public:
|
||||
class value_type {
|
||||
public:
|
||||
public:
|
||||
absl::string_view tag() const { return tag_; }
|
||||
absl::string_view bit() const { return bit_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
friend SegbitsFileReader;
|
||||
|
||||
value_type(const absl::string_view &view);
|
||||
value_type(const absl::string_view& view);
|
||||
|
||||
absl::string_view tag_;
|
||||
absl::string_view bit_;
|
||||
};
|
||||
|
||||
class iterator
|
||||
: public std::iterator<std::input_iterator_tag, value_type> {
|
||||
public:
|
||||
: public std::iterator<std::input_iterator_tag, value_type> {
|
||||
public:
|
||||
iterator& operator++();
|
||||
|
||||
bool operator==(iterator other) const {
|
||||
return view_ == other.view_; }
|
||||
return view_ == other.view_;
|
||||
}
|
||||
bool operator!=(iterator other) const {
|
||||
return !(*this == other);}
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
const value_type& operator*() const { return value_; }
|
||||
const value_type* operator->() const { return &value_; }
|
||||
|
||||
protected:
|
||||
protected:
|
||||
explicit iterator(absl::string_view view)
|
||||
: view_(view), value_(view) {}
|
||||
: view_(view), value_(view) {}
|
||||
|
||||
private:
|
||||
private:
|
||||
friend SegbitsFileReader;
|
||||
|
||||
absl::string_view view_;
|
||||
|
|
@ -50,18 +52,18 @@ class SegbitsFileReader {
|
|||
};
|
||||
|
||||
static std::unique_ptr<SegbitsFileReader> InitWithFile(
|
||||
const std::string &path);
|
||||
const std::string& path);
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
|
||||
private:
|
||||
SegbitsFileReader(std::unique_ptr<MemoryMappedFile> &&mapped_file)
|
||||
: mapped_file_(std::move(mapped_file)) {};
|
||||
private:
|
||||
SegbitsFileReader(std::unique_ptr<MemoryMappedFile>&& mapped_file)
|
||||
: mapped_file_(std::move(mapped_file)){};
|
||||
|
||||
std::unique_ptr<MemoryMappedFile> mapped_file_;
|
||||
};
|
||||
|
||||
} // namespace prjxray
|
||||
} // namespace prjxray
|
||||
|
||||
#endif // PRJXRAY_LIB_SEGBITS_FILE_READER_H
|
||||
|
|
|
|||
|
|
@ -16,24 +16,24 @@ namespace xilinx {
|
|||
namespace xc7series {
|
||||
|
||||
class BitstreamReader {
|
||||
public:
|
||||
public:
|
||||
using value_type = ConfigurationPacket;
|
||||
|
||||
class iterator
|
||||
: public std::iterator<std::input_iterator_tag, value_type> {
|
||||
public:
|
||||
: public std::iterator<std::input_iterator_tag, value_type> {
|
||||
public:
|
||||
iterator& operator++();
|
||||
|
||||
bool operator==(const iterator &other) const;
|
||||
bool operator!=(const iterator &other) const;
|
||||
bool operator==(const iterator& other) const;
|
||||
bool operator!=(const iterator& other) const;
|
||||
|
||||
const value_type& operator*() const;
|
||||
const value_type* operator->() const;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
explicit iterator(absl::Span<uint32_t> words);
|
||||
|
||||
private:
|
||||
private:
|
||||
friend BitstreamReader;
|
||||
|
||||
ConfigurationPacket::ParseResult parse_result_;
|
||||
|
|
@ -42,31 +42,32 @@ class BitstreamReader {
|
|||
|
||||
// Construct a reader from a collection of 32-bit, big-endian words.
|
||||
// Assumes that any sync word has already been removed.
|
||||
BitstreamReader(std::vector<uint32_t> &&words);
|
||||
BitstreamReader(std::vector<uint32_t>&& words);
|
||||
|
||||
// Construct a `BitstreamReader` from a Container of bytes.
|
||||
// Any bytes preceding an initial sync word are ignored.
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
static absl::optional<BitstreamReader> InitWithBytes(T bitstream);
|
||||
|
||||
const std::vector<uint32_t> &words() { return words_; };
|
||||
const std::vector<uint32_t>& words() { return words_; };
|
||||
|
||||
// Returns an iterator that yields `ConfigurationPackets`
|
||||
// as read from the bitstream.
|
||||
iterator begin();
|
||||
iterator end();
|
||||
private:
|
||||
|
||||
private:
|
||||
static std::array<uint8_t, 4> kSyncWord;
|
||||
|
||||
std::vector<uint32_t> words_;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
absl::optional<BitstreamReader> BitstreamReader::InitWithBytes(T bitstream) {
|
||||
// If this is really a Xilinx 7-Series bitstream, there will be a sync
|
||||
// word somewhere toward the beginning.
|
||||
auto sync_pos = std::search(bitstream.begin(), bitstream.end(),
|
||||
kSyncWord.begin(), kSyncWord.end());
|
||||
kSyncWord.begin(), kSyncWord.end());
|
||||
if (sync_pos == bitstream.end()) {
|
||||
return absl::optional<BitstreamReader>();
|
||||
}
|
||||
|
|
@ -74,13 +75,13 @@ absl::optional<BitstreamReader> BitstreamReader::InitWithBytes(T bitstream) {
|
|||
|
||||
// Wrap the provided container in a span that strips off the preamble.
|
||||
absl::Span<typename T::value_type> bitstream_span(bitstream);
|
||||
auto config_packets = bitstream_span.subspan(
|
||||
sync_pos - bitstream.begin());
|
||||
auto config_packets =
|
||||
bitstream_span.subspan(sync_pos - bitstream.begin());
|
||||
|
||||
// Convert the bytes into 32-bit, big-endian words.
|
||||
auto big_endian_reader = make_big_endian_span<uint32_t>(config_packets);
|
||||
std::vector<uint32_t> words{big_endian_reader.begin(),
|
||||
big_endian_reader.end()};
|
||||
big_endian_reader.end()};
|
||||
|
||||
return BitstreamReader(std::move(words));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,18 +16,18 @@ enum class BlockType : unsigned int {
|
|||
/* reserved = 0x3, */
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, BlockType value);
|
||||
std::ostream& operator<<(std::ostream& o, BlockType value);
|
||||
|
||||
} // namespace xc7series
|
||||
} // namespace xilinx
|
||||
} // namespace prjxray
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
template <>
|
||||
struct convert<prjxray::xilinx::xc7series::BlockType> {
|
||||
static Node encode(const prjxray::xilinx::xc7series::BlockType &rhs);
|
||||
static Node encode(const prjxray::xilinx::xc7series::BlockType& rhs);
|
||||
static bool decode(const Node& node,
|
||||
prjxray::xilinx::xc7series::BlockType &lhs);
|
||||
prjxray::xilinx::xc7series::BlockType& lhs);
|
||||
};
|
||||
} // namespace YAML
|
||||
|
||||
|
|
|
|||
|
|
@ -14,30 +14,31 @@ namespace xilinx {
|
|||
namespace xc7series {
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
using FrameMap = std::map<FrameAddress,
|
||||
absl::Span<uint32_t>>;
|
||||
public:
|
||||
using FrameMap = std::map<FrameAddress, absl::Span<uint32_t>>;
|
||||
|
||||
template<typename Collection>
|
||||
template <typename Collection>
|
||||
static absl::optional<Configuration> InitWithPackets(
|
||||
const Part& part, Collection &packets);
|
||||
const Part& part,
|
||||
Collection& packets);
|
||||
|
||||
Configuration(const Part& part, const FrameMap &frames)
|
||||
: part_(part), frames_(std::move(frames)) {}
|
||||
Configuration(const Part& part, const FrameMap& frames)
|
||||
: part_(part), frames_(std::move(frames)) {}
|
||||
|
||||
const Part& part() const { return part_; }
|
||||
const FrameMap& frames() const { return frames_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
static constexpr int kWordsPerFrame = 101;
|
||||
|
||||
Part part_;
|
||||
FrameMap frames_;
|
||||
};
|
||||
|
||||
template<typename Collection>
|
||||
template <typename Collection>
|
||||
absl::optional<Configuration> Configuration::InitWithPackets(
|
||||
const Part& part, Collection &packets) {
|
||||
const Part& part,
|
||||
Collection& packets) {
|
||||
// Registers that can be directly written to.
|
||||
uint32_t command_register = 0;
|
||||
uint32_t frame_address_register = 0;
|
||||
|
|
@ -55,95 +56,106 @@ absl::optional<Configuration> Configuration::InitWithPackets(
|
|||
}
|
||||
|
||||
switch (packet.address()) {
|
||||
case ConfigurationRegister::MASK:
|
||||
if (packet.data().size() < 1) continue;
|
||||
mask_register = packet.data()[0];
|
||||
break;
|
||||
case ConfigurationRegister::CTL1:
|
||||
if (packet.data().size() < 1) continue;
|
||||
ctl1_register = packet.data()[0] & mask_register;
|
||||
break;
|
||||
case ConfigurationRegister::CMD:
|
||||
if (packet.data().size() < 1) continue;
|
||||
command_register = packet.data()[0];
|
||||
// Writes to CMD trigger an immediate action. In the case of
|
||||
// WCFG, that is just setting a flag for the next FDIR.
|
||||
if (command_register == 0x1) {
|
||||
start_new_write = true;
|
||||
}
|
||||
break;
|
||||
case ConfigurationRegister::IDCODE:
|
||||
// This really should be a one-word write.
|
||||
if (packet.data().size() < 1) continue;
|
||||
|
||||
// If the IDCODE doesn't match our expected part,
|
||||
// consider the bitstream invalid.
|
||||
if (packet.data()[0] != part.idcode()) {
|
||||
return {};
|
||||
}
|
||||
break;
|
||||
case ConfigurationRegister::FAR:
|
||||
// This really should be a one-word write.
|
||||
if (packet.data().size() < 1) continue;
|
||||
frame_address_register = packet.data()[0];
|
||||
|
||||
// Per UG470, the command present in the CMD register
|
||||
// is executed each time the FAR register is laoded
|
||||
// with a new value. As we only care about WCFG
|
||||
// commands, just check that here. CTRL1 is completely
|
||||
// undocumented but looking at generated bitstreams, bit 21
|
||||
// is used when per-frame CRC is enabled. Setting this
|
||||
// bit seems to inhibit the re-execution of CMD during a
|
||||
// FAR write. In practice, this is used so FAR writes
|
||||
// can be added in the bitstream to show progress
|
||||
// markers without impacting the actual write
|
||||
// operation.
|
||||
if (bit_field_get(ctl1_register, 21, 21) == 0 &&
|
||||
command_register == 0x1) {
|
||||
start_new_write = true;
|
||||
}
|
||||
break;
|
||||
case ConfigurationRegister::FDRI: {
|
||||
if (start_new_write) {
|
||||
current_frame_address = frame_address_register;
|
||||
start_new_write = false;
|
||||
}
|
||||
|
||||
// 7-series frames are 101-words long. Writes to this
|
||||
// register can be multiples of that to do
|
||||
// auto-incrementing block writes.
|
||||
for (size_t ii = 0;
|
||||
ii < packet.data().size();
|
||||
ii += kWordsPerFrame) {
|
||||
frames[current_frame_address] =
|
||||
packet.data().subspan(
|
||||
ii, kWordsPerFrame);
|
||||
|
||||
auto next_address = part.GetNextFrameAddress(
|
||||
current_frame_address);
|
||||
if (!next_address) break;
|
||||
|
||||
// Bitstreams appear to have 2 frames of
|
||||
// padding between rows.
|
||||
if (next_address->row_address() !=
|
||||
current_frame_address.row_address()) {
|
||||
ii += 2 * kWordsPerFrame;
|
||||
case ConfigurationRegister::MASK:
|
||||
if (packet.data().size() < 1)
|
||||
continue;
|
||||
mask_register = packet.data()[0];
|
||||
break;
|
||||
case ConfigurationRegister::CTL1:
|
||||
if (packet.data().size() < 1)
|
||||
continue;
|
||||
ctl1_register =
|
||||
packet.data()[0] & mask_register;
|
||||
break;
|
||||
case ConfigurationRegister::CMD:
|
||||
if (packet.data().size() < 1)
|
||||
continue;
|
||||
command_register = packet.data()[0];
|
||||
// Writes to CMD trigger an immediate action. In
|
||||
// the case of WCFG, that is just setting a flag
|
||||
// for the next FDIR.
|
||||
if (command_register == 0x1) {
|
||||
start_new_write = true;
|
||||
}
|
||||
current_frame_address = *next_address;
|
||||
break;
|
||||
case ConfigurationRegister::IDCODE:
|
||||
// This really should be a one-word write.
|
||||
if (packet.data().size() < 1)
|
||||
continue;
|
||||
|
||||
// If the IDCODE doesn't match our expected
|
||||
// part, consider the bitstream invalid.
|
||||
if (packet.data()[0] != part.idcode()) {
|
||||
return {};
|
||||
}
|
||||
break;
|
||||
case ConfigurationRegister::FAR:
|
||||
// This really should be a one-word write.
|
||||
if (packet.data().size() < 1)
|
||||
continue;
|
||||
frame_address_register = packet.data()[0];
|
||||
|
||||
// Per UG470, the command present in the CMD
|
||||
// register is executed each time the FAR
|
||||
// register is laoded with a new value. As we
|
||||
// only care about WCFG commands, just check
|
||||
// that here. CTRL1 is completely undocumented
|
||||
// but looking at generated bitstreams, bit 21
|
||||
// is used when per-frame CRC is enabled.
|
||||
// Setting this bit seems to inhibit the
|
||||
// re-execution of CMD during a FAR write. In
|
||||
// practice, this is used so FAR writes can be
|
||||
// added in the bitstream to show progress
|
||||
// markers without impacting the actual write
|
||||
// operation.
|
||||
if (bit_field_get(ctl1_register, 21, 21) == 0 &&
|
||||
command_register == 0x1) {
|
||||
start_new_write = true;
|
||||
}
|
||||
break;
|
||||
case ConfigurationRegister::FDRI: {
|
||||
if (start_new_write) {
|
||||
current_frame_address =
|
||||
frame_address_register;
|
||||
start_new_write = false;
|
||||
}
|
||||
|
||||
// 7-series frames are 101-words long. Writes
|
||||
// to this register can be multiples of that to
|
||||
// do auto-incrementing block writes.
|
||||
for (size_t ii = 0; ii < packet.data().size();
|
||||
ii += kWordsPerFrame) {
|
||||
frames[current_frame_address] =
|
||||
packet.data().subspan(
|
||||
ii, kWordsPerFrame);
|
||||
|
||||
auto next_address =
|
||||
part.GetNextFrameAddress(
|
||||
current_frame_address);
|
||||
if (!next_address)
|
||||
break;
|
||||
|
||||
// Bitstreams appear to have 2 frames of
|
||||
// padding between rows.
|
||||
if (next_address->row_address() !=
|
||||
current_frame_address
|
||||
.row_address()) {
|
||||
ii += 2 * kWordsPerFrame;
|
||||
}
|
||||
current_frame_address = *next_address;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Configuration(part, frames);
|
||||
}
|
||||
|
||||
|
||||
} // namespace xc7series
|
||||
} // namespace xilinx
|
||||
} // namespace prjxray
|
||||
|
||||
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_CONFIGURATION_H_
|
||||
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_CONFIGURATION_H_
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ namespace xilinx {
|
|||
namespace xc7series {
|
||||
|
||||
class ConfigurationFrameRange {
|
||||
public:
|
||||
public:
|
||||
ConfigurationFrameRange() : begin_(0), end_(0) {}
|
||||
|
||||
ConfigurationFrameRange(FrameAddress begin, FrameAddress end)
|
||||
: begin_(begin), end_(end) {};
|
||||
: begin_(begin), end_(end){};
|
||||
|
||||
FrameAddress begin() const { return begin_; }
|
||||
FrameAddress end() const { return end_; }
|
||||
|
|
@ -25,7 +25,7 @@ class ConfigurationFrameRange {
|
|||
|
||||
bool Contains(FrameAddress address) const;
|
||||
|
||||
private:
|
||||
private:
|
||||
FrameAddress begin_;
|
||||
FrameAddress end_;
|
||||
};
|
||||
|
|
@ -35,13 +35,13 @@ class ConfigurationFrameRange {
|
|||
} // namespace prjxray
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
template <>
|
||||
struct convert<prjxray::xilinx::xc7series::ConfigurationFrameRange> {
|
||||
static Node encode(
|
||||
const prjxray::xilinx::xc7series::ConfigurationFrameRange &rhs);
|
||||
const prjxray::xilinx::xc7series::ConfigurationFrameRange& rhs);
|
||||
static bool decode(
|
||||
const Node& node,
|
||||
prjxray::xilinx::xc7series::ConfigurationFrameRange &lhs);
|
||||
const Node& node,
|
||||
prjxray::xilinx::xc7series::ConfigurationFrameRange& lhs);
|
||||
};
|
||||
} // namespace YAML
|
||||
} // namespace YAML
|
||||
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_CONFIGURATION_FRAME_RANGE_H_
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ namespace xilinx {
|
|||
namespace xc7series {
|
||||
|
||||
class ConfigurationPacket {
|
||||
public:
|
||||
public:
|
||||
typedef std::pair<absl::Span<uint32_t>,
|
||||
absl::optional<ConfigurationPacket>>
|
||||
ParseResult;
|
||||
absl::optional<ConfigurationPacket>>
|
||||
ParseResult;
|
||||
|
||||
enum Opcode {
|
||||
NOP = 0,
|
||||
|
|
@ -24,11 +24,14 @@ class ConfigurationPacket {
|
|||
/* reserved = 3 */
|
||||
};
|
||||
|
||||
ConfigurationPacket(unsigned int header_type, Opcode opcode,
|
||||
ConfigurationRegister address,
|
||||
const absl::Span<uint32_t> &data)
|
||||
: header_type_(header_type), opcode_(opcode),
|
||||
address_(address), data_(std::move(data)) {}
|
||||
ConfigurationPacket(unsigned int header_type,
|
||||
Opcode opcode,
|
||||
ConfigurationRegister address,
|
||||
const absl::Span<uint32_t>& data)
|
||||
: header_type_(header_type),
|
||||
opcode_(opcode),
|
||||
address_(address),
|
||||
data_(std::move(data)) {}
|
||||
|
||||
// Attempt to read a configuration packet from a sequence of
|
||||
// 32-bit, big-endian words. If successful, returns the packet read and
|
||||
|
|
@ -38,22 +41,22 @@ class ConfigurationPacket {
|
|||
// packet is produced. If no valid header is found, an empty span is
|
||||
// returned.
|
||||
static ParseResult InitWithWords(
|
||||
absl::Span<uint32_t> words,
|
||||
const ConfigurationPacket *previous_packet = nullptr);
|
||||
absl::Span<uint32_t> words,
|
||||
const ConfigurationPacket* previous_packet = nullptr);
|
||||
|
||||
unsigned int header_type() const { return header_type_; }
|
||||
const Opcode opcode() const { return opcode_; }
|
||||
const ConfigurationRegister address() const { return address_; }
|
||||
const absl::Span<uint32_t> &data() const { return data_; }
|
||||
const absl::Span<uint32_t>& data() const { return data_; }
|
||||
|
||||
private:
|
||||
private:
|
||||
unsigned int header_type_;
|
||||
Opcode opcode_;
|
||||
ConfigurationRegister address_;
|
||||
absl::Span<uint32_t> data_;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const ConfigurationPacket &packet);
|
||||
std::ostream& operator<<(std::ostream& o, const ConfigurationPacket& packet);
|
||||
|
||||
} // namespace xc7series
|
||||
} // namespace xilinx
|
||||
|
|
|
|||
|
|
@ -8,29 +8,29 @@ namespace xilinx {
|
|||
namespace xc7series {
|
||||
|
||||
enum class ConfigurationRegister : unsigned int {
|
||||
CRC = 0x00,
|
||||
FAR = 0x01,
|
||||
FDRI = 0x02,
|
||||
FDRO = 0x03,
|
||||
CMD = 0x04,
|
||||
CTL0 = 0x05,
|
||||
MASK = 0x06,
|
||||
STAT = 0x07,
|
||||
LOUT = 0x08,
|
||||
COR0 = 0x09,
|
||||
MFWR = 0x0a,
|
||||
CBC = 0x0b,
|
||||
IDCODE = 0x0c,
|
||||
AXSS = 0x0d,
|
||||
COR1 = 0x0e,
|
||||
WBSTAR = 0x10,
|
||||
TIMER = 0x11,
|
||||
CRC = 0x00,
|
||||
FAR = 0x01,
|
||||
FDRI = 0x02,
|
||||
FDRO = 0x03,
|
||||
CMD = 0x04,
|
||||
CTL0 = 0x05,
|
||||
MASK = 0x06,
|
||||
STAT = 0x07,
|
||||
LOUT = 0x08,
|
||||
COR0 = 0x09,
|
||||
MFWR = 0x0a,
|
||||
CBC = 0x0b,
|
||||
IDCODE = 0x0c,
|
||||
AXSS = 0x0d,
|
||||
COR1 = 0x0e,
|
||||
WBSTAR = 0x10,
|
||||
TIMER = 0x11,
|
||||
BOOTSTS = 0x16,
|
||||
CTL1 = 0x18,
|
||||
BSPI = 0x1F,
|
||||
CTL1 = 0x18,
|
||||
BSPI = 0x1F,
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream &o, const ConfigurationRegister &value);
|
||||
std::ostream& operator<<(std::ostream& o, const ConfigurationRegister& value);
|
||||
|
||||
} // namespace xc7series
|
||||
} // namespace xilinx
|
||||
|
|
|
|||
|
|
@ -12,14 +12,16 @@ namespace xilinx {
|
|||
namespace xc7series {
|
||||
|
||||
class FrameAddress {
|
||||
public:
|
||||
public:
|
||||
FrameAddress() : address_(0) {}
|
||||
|
||||
FrameAddress(uint32_t address)
|
||||
: address_(address) {};
|
||||
FrameAddress(uint32_t address) : address_(address){};
|
||||
|
||||
FrameAddress(BlockType block_type, bool is_bottom_half_rows,
|
||||
uint8_t row, uint16_t column, uint8_t minor);
|
||||
FrameAddress(BlockType block_type,
|
||||
bool is_bottom_half_rows,
|
||||
uint8_t row,
|
||||
uint16_t column,
|
||||
uint8_t minor);
|
||||
|
||||
operator uint32_t() const { return address_; }
|
||||
|
||||
|
|
@ -29,22 +31,22 @@ class FrameAddress {
|
|||
uint16_t column_address() const;
|
||||
uint8_t minor_address() const;
|
||||
|
||||
private:
|
||||
private:
|
||||
uint32_t address_;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, const FrameAddress& addr);
|
||||
std::ostream& operator<<(std::ostream& o, const FrameAddress& addr);
|
||||
|
||||
} // namespace xc7series
|
||||
} // namespace xilinx
|
||||
} // namespace prjxray
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
template <>
|
||||
struct convert<prjxray::xilinx::xc7series::FrameAddress> {
|
||||
static Node encode(const prjxray::xilinx::xc7series::FrameAddress &rhs);
|
||||
static Node encode(const prjxray::xilinx::xc7series::FrameAddress& rhs);
|
||||
static bool decode(const Node& node,
|
||||
prjxray::xilinx::xc7series::FrameAddress &lhs);
|
||||
prjxray::xilinx::xc7series::FrameAddress& lhs);
|
||||
};
|
||||
} // namespace YAML
|
||||
} // namespace YAML
|
||||
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_FRAME_ADDRESS_H_
|
||||
|
|
|
|||
|
|
@ -4,38 +4,40 @@
|
|||
#include <vector>
|
||||
|
||||
#include <absl/types/optional.h>
|
||||
#include <prjxray/xilinx/xc7series/frame_address.h>
|
||||
#include <prjxray/xilinx/xc7series/configuration_frame_range.h>
|
||||
#include <prjxray/xilinx/xc7series/frame_address.h>
|
||||
|
||||
namespace prjxray {
|
||||
namespace xilinx {
|
||||
namespace xc7series {
|
||||
|
||||
class Part {
|
||||
public:
|
||||
static absl::optional<Part> FromFile(const std::string &path);
|
||||
public:
|
||||
static absl::optional<Part> FromFile(const std::string& path);
|
||||
|
||||
// Constructs an invalid part with a zero IDCODE. Required for YAML
|
||||
// conversion but shouldn't be used otherwise.
|
||||
Part() : idcode_(0), frame_ranges_() {}
|
||||
|
||||
Part(uint32_t idcode,
|
||||
const std::vector<ConfigurationFrameRange> &ranges)
|
||||
: idcode_(idcode), frame_ranges_(std::move(ranges)) {}
|
||||
const std::vector<ConfigurationFrameRange>& ranges)
|
||||
: idcode_(idcode), frame_ranges_(std::move(ranges)) {}
|
||||
|
||||
uint32_t idcode() const { return idcode_; }
|
||||
|
||||
const std::vector<ConfigurationFrameRange>&
|
||||
configuration_frame_ranges() const { return frame_ranges_; }
|
||||
const std::vector<ConfigurationFrameRange>& configuration_frame_ranges()
|
||||
const {
|
||||
return frame_ranges_;
|
||||
}
|
||||
|
||||
absl::optional<FrameAddress>
|
||||
GetNextFrameAddress(FrameAddress address) const;
|
||||
absl::optional<FrameAddress> GetNextFrameAddress(
|
||||
FrameAddress address) const;
|
||||
|
||||
private:
|
||||
uint32_t idcode_;
|
||||
private:
|
||||
uint32_t idcode_;
|
||||
|
||||
// Ranges are expected to be non-overlapping.
|
||||
std::vector<ConfigurationFrameRange> frame_ranges_;
|
||||
// Ranges are expected to be non-overlapping.
|
||||
std::vector<ConfigurationFrameRange> frame_ranges_;
|
||||
};
|
||||
|
||||
} // namespace xc7series
|
||||
|
|
@ -43,12 +45,12 @@ class Part {
|
|||
} // namespace prjxray
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
template <>
|
||||
struct convert<prjxray::xilinx::xc7series::Part> {
|
||||
static Node encode(const prjxray::xilinx::xc7series::Part &rhs);
|
||||
static Node encode(const prjxray::xilinx::xc7series::Part& rhs);
|
||||
static bool decode(const Node& node,
|
||||
prjxray::xilinx::xc7series::Part &lhs);
|
||||
prjxray::xilinx::xc7series::Part& lhs);
|
||||
};
|
||||
} // namespace YAML
|
||||
} // namespace YAML
|
||||
|
||||
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_PART_H_
|
||||
#endif // PRJXRAY_LIB_XILINX_XC7SERIES_PART_H_
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@
|
|||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace prjxray {
|
||||
|
||||
std::unique_ptr<MemoryMappedFile> MemoryMappedFile::InitWithFile(
|
||||
const std::string &path) {
|
||||
|
||||
const std::string& path) {
|
||||
int fd = open(path.c_str(), O_RDONLY, 0);
|
||||
if (fd == -1) return nullptr;
|
||||
if (fd == -1)
|
||||
return nullptr;
|
||||
|
||||
struct stat statbuf;
|
||||
if (fstat(fd, &statbuf) < 0) {
|
||||
|
|
@ -26,25 +26,26 @@ std::unique_ptr<MemoryMappedFile> MemoryMappedFile::InitWithFile(
|
|||
if (statbuf.st_size == 0) {
|
||||
close(fd);
|
||||
return std::unique_ptr<MemoryMappedFile>(
|
||||
new MemoryMappedFile(nullptr, 0));
|
||||
new MemoryMappedFile(nullptr, 0));
|
||||
}
|
||||
|
||||
void *file_map = mmap(NULL, statbuf.st_size, PROT_READ,
|
||||
MAP_PRIVATE | MAP_POPULATE, fd, 0);
|
||||
void* file_map = mmap(NULL, statbuf.st_size, PROT_READ,
|
||||
MAP_PRIVATE | MAP_POPULATE, fd, 0);
|
||||
|
||||
// If mmap() succeeded, the fd is no longer needed as the mapping will
|
||||
// keep the file open. If mmap() failed, the fd needs to be closed
|
||||
// anyway.
|
||||
close(fd);
|
||||
|
||||
if (file_map == MAP_FAILED) return nullptr;
|
||||
if (file_map == MAP_FAILED)
|
||||
return nullptr;
|
||||
|
||||
return std::unique_ptr<MemoryMappedFile>(
|
||||
new MemoryMappedFile(file_map, statbuf.st_size));
|
||||
new MemoryMappedFile(file_map, statbuf.st_size));
|
||||
}
|
||||
|
||||
MemoryMappedFile::~MemoryMappedFile() {
|
||||
munmap(data_, size_);
|
||||
}
|
||||
|
||||
} // namepsace prjxray
|
||||
} // namespace prjxray
|
||||
|
|
|
|||
|
|
@ -3,26 +3,26 @@
|
|||
namespace prjxray {
|
||||
|
||||
std::unique_ptr<SegbitsFileReader> SegbitsFileReader::InitWithFile(
|
||||
const std::string &path) {
|
||||
|
||||
const std::string& path) {
|
||||
auto mapped_file = MemoryMappedFile::InitWithFile(path);
|
||||
if (!mapped_file) return nullptr;
|
||||
if (!mapped_file)
|
||||
return nullptr;
|
||||
|
||||
return std::unique_ptr<SegbitsFileReader>(
|
||||
new SegbitsFileReader(std::move(mapped_file)));
|
||||
new SegbitsFileReader(std::move(mapped_file)));
|
||||
}
|
||||
|
||||
SegbitsFileReader::iterator SegbitsFileReader::begin() {
|
||||
return iterator(absl::string_view(
|
||||
static_cast<const char*>(mapped_file_->data()),
|
||||
mapped_file_->size()));
|
||||
return iterator(
|
||||
absl::string_view(static_cast<const char*>(mapped_file_->data()),
|
||||
mapped_file_->size()));
|
||||
}
|
||||
|
||||
SegbitsFileReader::iterator SegbitsFileReader::end() {
|
||||
return iterator(absl::string_view());
|
||||
}
|
||||
|
||||
SegbitsFileReader::value_type::value_type(const absl::string_view &view) {
|
||||
SegbitsFileReader::value_type::value_type(const absl::string_view& view) {
|
||||
size_t separator_start = view.find_first_of(" \t");
|
||||
if (separator_start == absl::string_view::npos) {
|
||||
tag_ = view;
|
||||
|
|
@ -55,5 +55,4 @@ SegbitsFileReader::iterator& SegbitsFileReader::iterator::operator++() {
|
|||
return *this;
|
||||
}
|
||||
|
||||
|
||||
} // namespace prjxray
|
||||
|
|
|
|||
|
|
@ -6,12 +6,13 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(SegbitsFileReaderTest, NonExistantFileReturnsNull) {
|
||||
EXPECT_FALSE(prjxray::SegbitsFileReader::InitWithFile("does_not_exist"));
|
||||
EXPECT_FALSE(
|
||||
prjxray::SegbitsFileReader::InitWithFile("does_not_exist"));
|
||||
}
|
||||
|
||||
TEST(SegbitsFileReaderTest, ZeroLengthFileYieldsNoItems) {
|
||||
auto segbits_reader =
|
||||
prjxray::SegbitsFileReader::InitWithFile("empty_file");
|
||||
prjxray::SegbitsFileReader::InitWithFile("empty_file");
|
||||
ASSERT_TRUE(segbits_reader);
|
||||
|
||||
EXPECT_EQ(segbits_reader->begin(), segbits_reader->end());
|
||||
|
|
@ -19,7 +20,7 @@ TEST(SegbitsFileReaderTest, ZeroLengthFileYieldsNoItems) {
|
|||
|
||||
TEST(SegbitsFileReaderTest, FileWithOneEntry) {
|
||||
auto segbits_reader =
|
||||
prjxray::SegbitsFileReader::InitWithFile("one_entry.segbits");
|
||||
prjxray::SegbitsFileReader::InitWithFile("one_entry.segbits");
|
||||
ASSERT_TRUE(segbits_reader);
|
||||
|
||||
auto begin_iter = segbits_reader->begin();
|
||||
|
|
@ -31,7 +32,7 @@ TEST(SegbitsFileReaderTest, FileWithOneEntry) {
|
|||
|
||||
TEST(SegbitsFileReaderTest, FileWithOneEntryWithEmptyTag) {
|
||||
auto segbits_reader = prjxray::SegbitsFileReader::InitWithFile(
|
||||
"one_entry_empty_tag.segbits");
|
||||
"one_entry_empty_tag.segbits");
|
||||
ASSERT_TRUE(segbits_reader);
|
||||
|
||||
auto begin_iter = segbits_reader->begin();
|
||||
|
|
@ -43,7 +44,7 @@ TEST(SegbitsFileReaderTest, FileWithOneEntryWithEmptyTag) {
|
|||
|
||||
TEST(SegbitsFileReaderTest, FileWithOneEntryMissingBit) {
|
||||
auto segbits_reader = prjxray::SegbitsFileReader::InitWithFile(
|
||||
"one_entry_missing_bit.segbits");
|
||||
"one_entry_missing_bit.segbits");
|
||||
ASSERT_TRUE(segbits_reader);
|
||||
|
||||
auto begin_iter = segbits_reader->begin();
|
||||
|
|
@ -55,7 +56,7 @@ TEST(SegbitsFileReaderTest, FileWithOneEntryMissingBit) {
|
|||
|
||||
TEST(SegbitsFileReaderTest, FileWithOneEntryWithExtraWhitespace) {
|
||||
auto segbits_reader = prjxray::SegbitsFileReader::InitWithFile(
|
||||
"one_entry_extra_whitespace.segbits");
|
||||
"one_entry_extra_whitespace.segbits");
|
||||
ASSERT_TRUE(segbits_reader);
|
||||
|
||||
auto begin_iter = segbits_reader->begin();
|
||||
|
|
@ -66,8 +67,8 @@ TEST(SegbitsFileReaderTest, FileWithOneEntryWithExtraWhitespace) {
|
|||
}
|
||||
|
||||
TEST(SegbitsFileReaderTest, FileWithTwoEntries) {
|
||||
auto segbits_reader = prjxray::SegbitsFileReader::InitWithFile(
|
||||
"two_entries.segbits");
|
||||
auto segbits_reader =
|
||||
prjxray::SegbitsFileReader::InitWithFile("two_entries.segbits");
|
||||
ASSERT_TRUE(segbits_reader);
|
||||
|
||||
auto iter = segbits_reader->begin();
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ namespace xc7series {
|
|||
|
||||
std::array<uint8_t, 4> BitstreamReader::kSyncWord{0xAA, 0x99, 0x55, 0x66};
|
||||
|
||||
BitstreamReader::BitstreamReader(std::vector<uint32_t> &&words)
|
||||
: words_(std::move(words)) {}
|
||||
BitstreamReader::BitstreamReader(std::vector<uint32_t>&& words)
|
||||
: words_(std::move(words)) {}
|
||||
|
||||
BitstreamReader::iterator BitstreamReader::begin() {
|
||||
return iterator(absl::MakeSpan(words_));
|
||||
|
|
@ -23,14 +23,12 @@ BitstreamReader::iterator::iterator(absl::Span<uint32_t> words) {
|
|||
++(*this);
|
||||
}
|
||||
|
||||
BitstreamReader::iterator&
|
||||
BitstreamReader::iterator::operator++() {
|
||||
BitstreamReader::iterator& BitstreamReader::iterator::operator++() {
|
||||
do {
|
||||
auto new_result = ConfigurationPacket::InitWithWords(
|
||||
parse_result_.first,
|
||||
parse_result_.second.has_value() ?
|
||||
parse_result_.second.operator->() :
|
||||
nullptr);
|
||||
parse_result_.first, parse_result_.second.has_value()
|
||||
? parse_result_.second.operator->()
|
||||
: nullptr);
|
||||
|
||||
// If the a valid header is being found but there are
|
||||
// insufficient words to yield a packet, consider it the end.
|
||||
|
|
@ -41,8 +39,7 @@ BitstreamReader::iterator::operator++() {
|
|||
|
||||
words_ = parse_result_.first;
|
||||
parse_result_ = new_result;
|
||||
} while (!parse_result_.first.empty() &&
|
||||
!parse_result_.second);
|
||||
} while (!parse_result_.first.empty() && !parse_result_.second);
|
||||
|
||||
if (!parse_result_.second) {
|
||||
words_ = absl::Span<uint32_t>();
|
||||
|
|
@ -51,21 +48,21 @@ BitstreamReader::iterator::operator++() {
|
|||
return *this;
|
||||
}
|
||||
|
||||
bool BitstreamReader::iterator::operator==(const iterator &other) const {
|
||||
bool BitstreamReader::iterator::operator==(const iterator& other) const {
|
||||
return words_ == other.words_;
|
||||
}
|
||||
|
||||
bool BitstreamReader::iterator::operator!=(const iterator &other) const {
|
||||
bool BitstreamReader::iterator::operator!=(const iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
const BitstreamReader::value_type&
|
||||
BitstreamReader::iterator::operator*() const {
|
||||
const BitstreamReader::value_type& BitstreamReader::iterator::operator*()
|
||||
const {
|
||||
return *(parse_result_.second);
|
||||
}
|
||||
|
||||
const BitstreamReader::value_type*
|
||||
BitstreamReader::iterator::operator->() const {
|
||||
const BitstreamReader::value_type* BitstreamReader::iterator::operator->()
|
||||
const {
|
||||
return parse_result_.second.operator->();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,30 +19,23 @@ TEST(BitstreamReaderTest, InitWithOnlySyncReturnsObject) {
|
|||
EXPECT_TRUE(reader);
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest,
|
||||
InitWithSyncAfterNonWordSizedPaddingReturnsObject) {
|
||||
std::vector<uint8_t> bitstream{
|
||||
0xFF, 0xFE,
|
||||
0xAA, 0x99, 0x55, 0x66
|
||||
};
|
||||
TEST(BitstreamReaderTest, InitWithSyncAfterNonWordSizedPaddingReturnsObject) {
|
||||
std::vector<uint8_t> bitstream{0xFF, 0xFE, 0xAA, 0x99, 0x55, 0x66};
|
||||
auto reader = xc7series::BitstreamReader::InitWithBytes(bitstream);
|
||||
EXPECT_TRUE(reader);
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest,
|
||||
InitWithSyncAfterWordSizedPaddingReturnsObject) {
|
||||
std::vector<uint8_t> bitstream{
|
||||
0xFF, 0xFE, 0xFD, 0xFC,
|
||||
0xAA, 0x99, 0x55, 0x66
|
||||
};
|
||||
TEST(BitstreamReaderTest, InitWithSyncAfterWordSizedPaddingReturnsObject) {
|
||||
std::vector<uint8_t> bitstream{0xFF, 0xFE, 0xFD, 0xFC,
|
||||
0xAA, 0x99, 0x55, 0x66};
|
||||
auto reader = xc7series::BitstreamReader::InitWithBytes(bitstream);
|
||||
EXPECT_TRUE(reader);
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest, ParsesType1Packet) {
|
||||
std::vector<uint8_t> bitstream{
|
||||
0xAA, 0x99, 0x55, 0x66, // sync
|
||||
0x20, 0x00, 0x00, 0x00, // NOP
|
||||
0xAA, 0x99, 0x55, 0x66, // sync
|
||||
0x20, 0x00, 0x00, 0x00, // NOP
|
||||
};
|
||||
auto reader = xc7series::BitstreamReader::InitWithBytes(bitstream);
|
||||
ASSERT_TRUE(reader);
|
||||
|
|
@ -50,34 +43,31 @@ TEST(BitstreamReaderTest, ParsesType1Packet) {
|
|||
|
||||
auto first_packet = reader->begin();
|
||||
EXPECT_EQ(first_packet->opcode(),
|
||||
xc7series::ConfigurationPacket::Opcode::NOP);
|
||||
xc7series::ConfigurationPacket::Opcode::NOP);
|
||||
|
||||
EXPECT_EQ(++first_packet, reader->end());
|
||||
}
|
||||
|
||||
TEST(BitstreamReaderTest, ParseType2PacketWithoutType1Fails) {
|
||||
std::vector<uint8_t> bitstream{
|
||||
0xAA, 0x99, 0x55, 0x66, // sync
|
||||
0x40, 0x00, 0x00, 0x00, // Type 2 NOP
|
||||
0xAA, 0x99, 0x55, 0x66, // sync
|
||||
0x40, 0x00, 0x00, 0x00, // Type 2 NOP
|
||||
};
|
||||
auto reader = xc7series::BitstreamReader::InitWithBytes(bitstream);
|
||||
ASSERT_TRUE(reader);
|
||||
EXPECT_EQ(reader->begin(), reader->end());
|
||||
}
|
||||
|
||||
|
||||
TEST(BitstreamReaderTest, ParsesType2AfterType1Packet) {
|
||||
std::vector<uint8_t> bitstream{
|
||||
0xAA, 0x99, 0x55, 0x66, // sync
|
||||
0x28, 0x00, 0x60, 0x00, // Type 1 Read zero bytes from 6
|
||||
0x48, 0x00, 0x00, 0x04, // Type 2 write of 4 words
|
||||
0x1, 0x2, 0x3, 0x4,
|
||||
0x5, 0x6, 0x7, 0x8,
|
||||
0x9, 0xA, 0xB, 0xC,
|
||||
0xD, 0xE, 0xF, 0x10,
|
||||
0xAA, 0x99, 0x55, 0x66, // sync
|
||||
0x28, 0x00, 0x60, 0x00, // Type 1 Read zero bytes from 6
|
||||
0x48, 0x00, 0x00, 0x04, // Type 2 write of 4 words
|
||||
0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
|
||||
0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10,
|
||||
};
|
||||
std::vector<uint32_t> data_words{
|
||||
0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10};
|
||||
std::vector<uint32_t> data_words{0x01020304, 0x05060708, 0x090A0B0C,
|
||||
0x0D0E0F10};
|
||||
|
||||
auto reader = xc7series::BitstreamReader::InitWithBytes(bitstream);
|
||||
ASSERT_TRUE(reader);
|
||||
|
|
@ -85,17 +75,17 @@ TEST(BitstreamReaderTest, ParsesType2AfterType1Packet) {
|
|||
|
||||
auto first_packet = reader->begin();
|
||||
EXPECT_EQ(first_packet->opcode(),
|
||||
xc7series::ConfigurationPacket::Opcode::Read);
|
||||
xc7series::ConfigurationPacket::Opcode::Read);
|
||||
EXPECT_EQ(first_packet->address(),
|
||||
xc7series::ConfigurationRegister::FDRO);
|
||||
xc7series::ConfigurationRegister::FDRO);
|
||||
EXPECT_EQ(first_packet->data(), absl::Span<uint32_t>());
|
||||
|
||||
auto second_packet = ++first_packet;
|
||||
ASSERT_NE(second_packet, reader->end());
|
||||
EXPECT_EQ(second_packet->opcode(),
|
||||
xc7series::ConfigurationPacket::Opcode::Read);
|
||||
xc7series::ConfigurationPacket::Opcode::Read);
|
||||
EXPECT_EQ(second_packet->address(),
|
||||
xc7series::ConfigurationRegister::FDRO);
|
||||
xc7series::ConfigurationRegister::FDRO);
|
||||
EXPECT_EQ(first_packet->data(), absl::Span<uint32_t>(data_words));
|
||||
|
||||
EXPECT_EQ(++first_packet, reader->end());
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@ namespace prjxray {
|
|||
namespace xilinx {
|
||||
namespace xc7series {
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, BlockType value) {
|
||||
std::ostream& operator<<(std::ostream& o, BlockType value) {
|
||||
switch (value) {
|
||||
case BlockType::CLB_IO_CLK:
|
||||
o << "CLB/IO/CLK";
|
||||
break;
|
||||
case BlockType::BLOCK_RAM:
|
||||
o << "Block RAM";
|
||||
break;
|
||||
case BlockType::CFG_CLB:
|
||||
o << "Config CLB";
|
||||
break;
|
||||
case BlockType::CLB_IO_CLK:
|
||||
o << "CLB/IO/CLK";
|
||||
break;
|
||||
case BlockType::BLOCK_RAM:
|
||||
o << "Block RAM";
|
||||
break;
|
||||
case BlockType::CFG_CLB:
|
||||
o << "Config CLB";
|
||||
break;
|
||||
}
|
||||
|
||||
return o;
|
||||
|
|
@ -27,7 +27,7 @@ std::ostream &operator<<(std::ostream &o, BlockType value) {
|
|||
namespace YAML {
|
||||
|
||||
Node convert<prjxray::xilinx::xc7series::BlockType>::encode(
|
||||
const prjxray::xilinx::xc7series::BlockType &rhs) {
|
||||
const prjxray::xilinx::xc7series::BlockType& rhs) {
|
||||
switch (rhs) {
|
||||
case prjxray::xilinx::xc7series::BlockType::CLB_IO_CLK:
|
||||
return Node("CLB_IO_CLK");
|
||||
|
|
@ -41,7 +41,8 @@ Node convert<prjxray::xilinx::xc7series::BlockType>::encode(
|
|||
}
|
||||
|
||||
bool YAML::convert<prjxray::xilinx::xc7series::BlockType>::decode(
|
||||
const Node &node, prjxray::xilinx::xc7series::BlockType &lhs) {
|
||||
const Node& node,
|
||||
prjxray::xilinx::xc7series::BlockType& lhs) {
|
||||
auto type_str = node.as<std::string>();
|
||||
|
||||
if (type_str == "CLB_IO_CLK") {
|
||||
|
|
@ -58,4 +59,4 @@ bool YAML::convert<prjxray::xilinx::xc7series::BlockType>::decode(
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace YAML;
|
||||
} // namespace YAML
|
||||
|
|
|
|||
|
|
@ -22,9 +22,9 @@ TEST(BlockTypeTest, YamlDecode) {
|
|||
node.push_back("CLB_IO_CLK");
|
||||
|
||||
EXPECT_EQ(node[0].as<xc7series::BlockType>(),
|
||||
xc7series::BlockType::CFG_CLB);
|
||||
xc7series::BlockType::CFG_CLB);
|
||||
EXPECT_EQ(node[1].as<xc7series::BlockType>(),
|
||||
xc7series::BlockType::BLOCK_RAM);
|
||||
xc7series::BlockType::BLOCK_RAM);
|
||||
EXPECT_EQ(node[2].as<xc7series::BlockType>(),
|
||||
xc7series::BlockType::CLB_IO_CLK);
|
||||
xc7series::BlockType::CLB_IO_CLK);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace xc7series = prjxray::xilinx::xc7series;
|
|||
namespace YAML {
|
||||
|
||||
Node convert<xc7series::ConfigurationFrameRange>::encode(
|
||||
const xc7series::ConfigurationFrameRange &rhs) {
|
||||
const xc7series::ConfigurationFrameRange& rhs) {
|
||||
Node node;
|
||||
node.SetTag("xilinx/xc7series/configuration_frame_range");
|
||||
node["begin"] = rhs.begin();
|
||||
|
|
@ -26,16 +26,16 @@ Node convert<xc7series::ConfigurationFrameRange>::encode(
|
|||
}
|
||||
|
||||
bool convert<xc7series::ConfigurationFrameRange>::decode(
|
||||
const Node &node,
|
||||
xc7series::ConfigurationFrameRange &lhs) {
|
||||
const Node& node,
|
||||
xc7series::ConfigurationFrameRange& lhs) {
|
||||
if (node.Tag() != "xilinx/xc7series/configuration_frame_range" ||
|
||||
!node["begin"] ||
|
||||
!node["end"]) return false;
|
||||
!node["begin"] || !node["end"])
|
||||
return false;
|
||||
|
||||
lhs = xc7series::ConfigurationFrameRange(
|
||||
node["begin"].as<xc7series::FrameAddress>(),
|
||||
node["end"].as<xc7series::FrameAddress>());
|
||||
node["begin"].as<xc7series::FrameAddress>(),
|
||||
node["end"].as<xc7series::FrameAddress>());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace YAML;
|
||||
} // namespace YAML
|
||||
|
|
|
|||
|
|
@ -11,65 +11,68 @@ namespace xc7series {
|
|||
|
||||
std::pair<absl::Span<uint32_t>, absl::optional<ConfigurationPacket>>
|
||||
ConfigurationPacket::InitWithWords(absl::Span<uint32_t> words,
|
||||
const ConfigurationPacket *previous_packet) {
|
||||
const ConfigurationPacket* previous_packet) {
|
||||
// Need at least one 32-bit word to have a valid packet header.
|
||||
if (words.size() < 1) return {words, {}};
|
||||
if (words.size() < 1)
|
||||
return {words, {}};
|
||||
|
||||
uint32_t header_type = bit_field_get(words[0], 31, 29);
|
||||
switch (header_type) {
|
||||
case 0x0:
|
||||
// Type 0 is emitted at the end of a configuration row when
|
||||
// BITSTREAM.GENERAL.DEBUGBITSTREAM is set to YES. These seem
|
||||
// to be padding that are interepreted as NOPs. Since Type 0
|
||||
// packets don't exist according to UG470 and they seem to be
|
||||
// zero-filled, just consume the bytes without generating a
|
||||
// packet.
|
||||
return {words.subspan(1), {}};
|
||||
case 0x1: {
|
||||
Opcode opcode = static_cast<Opcode>(
|
||||
bit_field_get(words[0], 28, 27));
|
||||
ConfigurationRegister address =
|
||||
static_cast<ConfigurationRegister>(
|
||||
bit_field_get(words[0], 26, 13));
|
||||
uint32_t data_word_count = bit_field_get(words[0], 10, 0);
|
||||
case 0x0:
|
||||
// Type 0 is emitted at the end of a configuration row
|
||||
// when BITSTREAM.GENERAL.DEBUGBITSTREAM is set to YES.
|
||||
// These seem to be padding that are interepreted as
|
||||
// NOPs. Since Type 0 packets don't exist according to
|
||||
// UG470 and they seem to be zero-filled, just consume
|
||||
// the bytes without generating a packet.
|
||||
return {words.subspan(1), {}};
|
||||
case 0x1: {
|
||||
Opcode opcode = static_cast<Opcode>(
|
||||
bit_field_get(words[0], 28, 27));
|
||||
ConfigurationRegister address =
|
||||
static_cast<ConfigurationRegister>(
|
||||
bit_field_get(words[0], 26, 13));
|
||||
uint32_t data_word_count =
|
||||
bit_field_get(words[0], 10, 0);
|
||||
|
||||
// If the full packet has not been received, return as though
|
||||
// no valid packet was found.
|
||||
if (data_word_count > words.size() - 1) {
|
||||
return {words, {}};
|
||||
// If the full packet has not been received, return as
|
||||
// though no valid packet was found.
|
||||
if (data_word_count > words.size() - 1) {
|
||||
return {words, {}};
|
||||
}
|
||||
|
||||
return {words.subspan(data_word_count + 1),
|
||||
{{header_type, opcode, address,
|
||||
words.subspan(1, data_word_count)}}};
|
||||
}
|
||||
case 0x2: {
|
||||
absl::optional<ConfigurationPacket> packet;
|
||||
Opcode opcode = static_cast<Opcode>(
|
||||
bit_field_get(words[0], 28, 27));
|
||||
uint32_t data_word_count =
|
||||
bit_field_get(words[0], 26, 0);
|
||||
|
||||
return {words.subspan(data_word_count+1),
|
||||
{{header_type, opcode, address,
|
||||
words.subspan(1, data_word_count)}}};
|
||||
}
|
||||
case 0x2: {
|
||||
absl::optional<ConfigurationPacket> packet;
|
||||
Opcode opcode = static_cast<Opcode>(
|
||||
bit_field_get(words[0], 28, 27));
|
||||
uint32_t data_word_count = bit_field_get(words[0], 26, 0);
|
||||
// If the full packet has not been received, return as
|
||||
// though no valid packet was found.
|
||||
if (data_word_count > words.size() - 1) {
|
||||
return {words, {}};
|
||||
}
|
||||
|
||||
// If the full packet has not been received, return as though
|
||||
// no valid packet was found.
|
||||
if (data_word_count > words.size() - 1) {
|
||||
return {words, {}};
|
||||
if (previous_packet) {
|
||||
packet = ConfigurationPacket(
|
||||
header_type, opcode,
|
||||
previous_packet->address(),
|
||||
words.subspan(1, data_word_count));
|
||||
}
|
||||
|
||||
return {words.subspan(data_word_count + 1), packet};
|
||||
}
|
||||
|
||||
if (previous_packet) {
|
||||
packet = ConfigurationPacket(
|
||||
header_type, opcode,
|
||||
previous_packet->address(),
|
||||
words.subspan(1, data_word_count));
|
||||
}
|
||||
|
||||
return {words.subspan(data_word_count + 1), packet};
|
||||
}
|
||||
default:
|
||||
return {{}, {}};
|
||||
default:
|
||||
return {{}, {}};
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const ConfigurationPacket &packet) {
|
||||
std::ostream& operator<<(std::ostream& o, const ConfigurationPacket& packet) {
|
||||
switch (packet.opcode()) {
|
||||
case ConfigurationPacket::Opcode::NOP:
|
||||
o << "[NOP]" << std::endl;
|
||||
|
|
@ -101,7 +104,7 @@ std::ostream& operator<<(std::ostream& o, const ConfigurationPacket &packet) {
|
|||
o << std::setw(8) << std::hex;
|
||||
o << packet.data()[ii] << " ";
|
||||
|
||||
if ((ii+1) % 4 == 0) {
|
||||
if ((ii + 1) % 4 == 0) {
|
||||
o << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,26 +10,26 @@ namespace xc7series = prjxray::xilinx::xc7series;
|
|||
|
||||
constexpr uint32_t kType1NOP = prjxray::bit_field_set<uint32_t>(0, 31, 29, 0x1);
|
||||
|
||||
constexpr uint32_t MakeType1(const int opcode, const int address,
|
||||
const int word_count) {
|
||||
constexpr uint32_t MakeType1(const int opcode,
|
||||
const int address,
|
||||
const int word_count) {
|
||||
return prjxray::bit_field_set<uint32_t>(
|
||||
prjxray::bit_field_set<uint32_t>(
|
||||
prjxray::bit_field_set<uint32_t>(
|
||||
prjxray::bit_field_set<uint32_t>(0x0, 31, 29, 0x1),
|
||||
28, 27, opcode),
|
||||
26, 13, address),
|
||||
10, 0, word_count);
|
||||
prjxray::bit_field_set<uint32_t>(
|
||||
prjxray::bit_field_set<uint32_t>(
|
||||
prjxray::bit_field_set<uint32_t>(0x0, 31, 29, 0x1), 28, 27,
|
||||
opcode),
|
||||
26, 13, address),
|
||||
10, 0, word_count);
|
||||
}
|
||||
|
||||
constexpr uint32_t MakeType2(const int opcode, const int word_count) {
|
||||
return prjxray::bit_field_set<uint32_t>(
|
||||
prjxray::bit_field_set<uint32_t>(
|
||||
prjxray::bit_field_set<uint32_t>(0x0, 31, 29, 0x2),
|
||||
28, 27, opcode),
|
||||
26, 0, word_count);
|
||||
prjxray::bit_field_set<uint32_t>(
|
||||
prjxray::bit_field_set<uint32_t>(0x0, 31, 29, 0x2), 28, 27,
|
||||
opcode),
|
||||
26, 0, word_count);
|
||||
}
|
||||
|
||||
|
||||
TEST(ConfigPacket, InitWithZeroBytes) {
|
||||
auto packet = xc7series::ConfigurationPacket::InitWithWords({});
|
||||
|
||||
|
|
@ -44,9 +44,9 @@ TEST(ConfigPacket, InitWithType1Nop) {
|
|||
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
|
||||
ASSERT_TRUE(packet.second);
|
||||
EXPECT_EQ(packet.second->opcode(),
|
||||
xc7series::ConfigurationPacket::Opcode::NOP);
|
||||
xc7series::ConfigurationPacket::Opcode::NOP);
|
||||
EXPECT_EQ(packet.second->address(),
|
||||
xc7series::ConfigurationRegister::CRC);
|
||||
xc7series::ConfigurationRegister::CRC);
|
||||
EXPECT_EQ(packet.second->data(), absl::Span<uint32_t>());
|
||||
}
|
||||
|
||||
|
|
@ -57,9 +57,9 @@ TEST(ConfigPacket, InitWithType1Read) {
|
|||
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
|
||||
ASSERT_TRUE(packet.second);
|
||||
EXPECT_EQ(packet.second->opcode(),
|
||||
xc7series::ConfigurationPacket::Opcode::Read);
|
||||
xc7series::ConfigurationPacket::Opcode::Read);
|
||||
EXPECT_EQ(packet.second->address(),
|
||||
xc7series::ConfigurationRegister::FDRI);
|
||||
xc7series::ConfigurationRegister::FDRI);
|
||||
EXPECT_EQ(packet.second->data(), word_span.subspan(1));
|
||||
}
|
||||
|
||||
|
|
@ -70,9 +70,9 @@ TEST(ConfigPacket, InitWithType1Write) {
|
|||
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
|
||||
ASSERT_TRUE(packet.second);
|
||||
EXPECT_EQ(packet.second->opcode(),
|
||||
xc7series::ConfigurationPacket::Opcode::Write);
|
||||
xc7series::ConfigurationPacket::Opcode::Write);
|
||||
EXPECT_EQ(packet.second->address(),
|
||||
xc7series::ConfigurationRegister::FDRO);
|
||||
xc7series::ConfigurationRegister::FDRO);
|
||||
EXPECT_EQ(packet.second->data(), word_span.subspan(1));
|
||||
}
|
||||
|
||||
|
|
@ -86,20 +86,19 @@ TEST(ConfigPacket, InitWithType2WithoutPreviousPacketFails) {
|
|||
|
||||
TEST(ConfigPacket, InitWithType2WithPreviousPacket) {
|
||||
xc7series::ConfigurationPacket previous_packet(
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Read,
|
||||
xc7series::ConfigurationRegister::MFWR,
|
||||
absl::Span<uint32_t>());
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Read,
|
||||
xc7series::ConfigurationRegister::MFWR, absl::Span<uint32_t>());
|
||||
std::vector<uint32_t> words{
|
||||
MakeType2(0x01, 12), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
MakeType2(0x01, 12), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
absl::Span<uint32_t> word_span(words);
|
||||
auto packet = xc7series::ConfigurationPacket::InitWithWords(
|
||||
word_span, &previous_packet);
|
||||
word_span, &previous_packet);
|
||||
EXPECT_EQ(packet.first, absl::Span<uint32_t>());
|
||||
ASSERT_TRUE(packet.second);
|
||||
EXPECT_EQ(packet.second->opcode(),
|
||||
xc7series::ConfigurationPacket::Opcode::Read);
|
||||
xc7series::ConfigurationPacket::Opcode::Read);
|
||||
EXPECT_EQ(packet.second->address(),
|
||||
xc7series::ConfigurationRegister::MFWR);
|
||||
xc7series::ConfigurationRegister::MFWR);
|
||||
EXPECT_EQ(packet.second->data(), word_span.subspan(1));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace prjxray {
|
|||
namespace xilinx {
|
||||
namespace xc7series {
|
||||
|
||||
std::ostream& operator<<(std::ostream &o, const ConfigurationRegister &value) {
|
||||
std::ostream& operator<<(std::ostream& o, const ConfigurationRegister& value) {
|
||||
switch (value) {
|
||||
case ConfigurationRegister::CRC:
|
||||
return o << "CRC";
|
||||
|
|
@ -51,7 +51,6 @@ std::ostream& operator<<(std::ostream &o, const ConfigurationRegister &value) {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace xc7series
|
||||
} // namespace xilinx
|
||||
} // namespace prjxray
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace xc7series = prjxray::xilinx::xc7series;
|
|||
TEST(ConfigurationTest, ConstructFromPacketsWithSingleFrame) {
|
||||
std::vector<xc7series::ConfigurationFrameRange> test_part_ranges;
|
||||
test_part_ranges.push_back(
|
||||
xc7series::ConfigurationFrameRange(0x4567, 0x4568));
|
||||
xc7series::ConfigurationFrameRange(0x4567, 0x4568));
|
||||
|
||||
xc7series::Part test_part(0x1234, test_part_ranges);
|
||||
|
||||
|
|
@ -25,33 +25,34 @@ TEST(ConfigurationTest, ConstructFromPacketsWithSingleFrame) {
|
|||
std::vector<uint32_t> frame(101, 0xAA);
|
||||
|
||||
std::vector<xc7series::ConfigurationPacket> packets{
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::IDCODE,
|
||||
absl::MakeSpan(idcode),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::FAR,
|
||||
absl::MakeSpan(frame_address),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::CMD,
|
||||
absl::MakeSpan(cmd),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::FDRI,
|
||||
absl::MakeSpan(frame),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::IDCODE,
|
||||
absl::MakeSpan(idcode),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::FAR,
|
||||
absl::MakeSpan(frame_address),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::CMD,
|
||||
absl::MakeSpan(cmd),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::FDRI,
|
||||
absl::MakeSpan(frame),
|
||||
},
|
||||
};
|
||||
|
||||
auto test_config = xc7series::Configuration::InitWithPackets(test_part, packets);
|
||||
auto test_config =
|
||||
xc7series::Configuration::InitWithPackets(test_part, packets);
|
||||
ASSERT_TRUE(test_config);
|
||||
|
||||
EXPECT_EQ(test_config->part().idcode(), static_cast<uint32_t>(0x1234));
|
||||
|
|
@ -62,9 +63,9 @@ TEST(ConfigurationTest, ConstructFromPacketsWithSingleFrame) {
|
|||
TEST(ConfigurationTest, ConstructFromPacketsWithAutoincrement) {
|
||||
std::vector<xc7series::ConfigurationFrameRange> test_part_ranges;
|
||||
test_part_ranges.push_back(
|
||||
xc7series::ConfigurationFrameRange(0x4560, 0x4570));
|
||||
xc7series::ConfigurationFrameRange(0x4560, 0x4570));
|
||||
test_part_ranges.push_back(
|
||||
xc7series::ConfigurationFrameRange(0x4580, 0x4590));
|
||||
xc7series::ConfigurationFrameRange(0x4580, 0x4590));
|
||||
|
||||
xc7series::Part test_part(0x1234, test_part_ranges);
|
||||
|
||||
|
|
@ -75,88 +76,99 @@ TEST(ConfigurationTest, ConstructFromPacketsWithAutoincrement) {
|
|||
std::fill_n(frame.begin() + 101, 101, 0xBB);
|
||||
|
||||
std::vector<xc7series::ConfigurationPacket> packets{
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::IDCODE,
|
||||
absl::MakeSpan(idcode),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::FAR,
|
||||
absl::MakeSpan(frame_address),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::CMD,
|
||||
absl::MakeSpan(cmd),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::FDRI,
|
||||
absl::MakeSpan(frame),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::IDCODE,
|
||||
absl::MakeSpan(idcode),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::FAR,
|
||||
absl::MakeSpan(frame_address),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::CMD,
|
||||
absl::MakeSpan(cmd),
|
||||
},
|
||||
{
|
||||
static_cast<unsigned int>(0x1),
|
||||
xc7series::ConfigurationPacket::Opcode::Write,
|
||||
xc7series::ConfigurationRegister::FDRI,
|
||||
absl::MakeSpan(frame),
|
||||
},
|
||||
};
|
||||
|
||||
auto test_config = xc7series::Configuration::InitWithPackets(test_part, packets);
|
||||
auto test_config =
|
||||
xc7series::Configuration::InitWithPackets(test_part, packets);
|
||||
ASSERT_TRUE(test_config);
|
||||
|
||||
absl::Span<uint32_t> frame_span(frame);
|
||||
EXPECT_EQ(test_config->part().idcode(), static_cast<uint32_t>(0x1234));
|
||||
EXPECT_EQ(test_config->frames().size(), static_cast<size_t>(2));
|
||||
EXPECT_EQ(test_config->frames().at(0x456F), std::vector<uint32_t>(101, 0xAA));
|
||||
EXPECT_EQ(test_config->frames().at(0x4580), std::vector<uint32_t>(101, 0xBB));
|
||||
EXPECT_EQ(test_config->frames().at(0x456F),
|
||||
std::vector<uint32_t>(101, 0xAA));
|
||||
EXPECT_EQ(test_config->frames().at(0x4580),
|
||||
std::vector<uint32_t>(101, 0xBB));
|
||||
}
|
||||
|
||||
TEST(ConfigurationTest, DebugAndPerFrameCrcBitstreamsProduceEqualConfigurations) {
|
||||
TEST(ConfigurationTest,
|
||||
DebugAndPerFrameCrcBitstreamsProduceEqualConfigurations) {
|
||||
auto part = xc7series::Part::FromFile("configuration_test.yaml");
|
||||
ASSERT_TRUE(part);
|
||||
|
||||
auto debug_bitstream = prjxray::MemoryMappedFile::InitWithFile(
|
||||
"configuration_test.debug.bit");
|
||||
"configuration_test.debug.bit");
|
||||
ASSERT_TRUE(debug_bitstream);
|
||||
|
||||
auto debug_reader = xc7series::BitstreamReader::InitWithBytes(
|
||||
debug_bitstream->as_bytes());
|
||||
debug_bitstream->as_bytes());
|
||||
ASSERT_TRUE(debug_reader);
|
||||
|
||||
auto debug_configuration = xc7series::Configuration::InitWithPackets(
|
||||
*part, *debug_reader);
|
||||
auto debug_configuration =
|
||||
xc7series::Configuration::InitWithPackets(*part, *debug_reader);
|
||||
ASSERT_TRUE(debug_configuration);
|
||||
|
||||
auto perframecrc_bitstream = prjxray::MemoryMappedFile::InitWithFile(
|
||||
"configuration_test.perframecrc.bit");
|
||||
"configuration_test.perframecrc.bit");
|
||||
ASSERT_TRUE(perframecrc_bitstream);
|
||||
|
||||
auto perframecrc_reader = xc7series::BitstreamReader::InitWithBytes(
|
||||
perframecrc_bitstream->as_bytes());
|
||||
perframecrc_bitstream->as_bytes());
|
||||
ASSERT_TRUE(perframecrc_reader);
|
||||
|
||||
auto perframecrc_configuration = xc7series::Configuration::InitWithPackets(
|
||||
*part, *perframecrc_reader);
|
||||
auto perframecrc_configuration =
|
||||
xc7series::Configuration::InitWithPackets(*part,
|
||||
*perframecrc_reader);
|
||||
ASSERT_TRUE(perframecrc_configuration);
|
||||
|
||||
for (auto debug_frame : debug_configuration->frames()) {
|
||||
auto perframecrc_frame = perframecrc_configuration->frames().find(debug_frame.first);
|
||||
if (perframecrc_frame == perframecrc_configuration->frames().end()) {
|
||||
ADD_FAILURE() << debug_frame.first << ": missing in perframecrc bitstream";
|
||||
auto perframecrc_frame =
|
||||
perframecrc_configuration->frames().find(debug_frame.first);
|
||||
if (perframecrc_frame ==
|
||||
perframecrc_configuration->frames().end()) {
|
||||
ADD_FAILURE() << debug_frame.first
|
||||
<< ": missing in perframecrc bitstream";
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int ii = 0; ii < 101; ++ii) {
|
||||
EXPECT_EQ(perframecrc_frame->second[ii], debug_frame.second[ii])
|
||||
<< debug_frame.first << ": word " << ii;
|
||||
EXPECT_EQ(perframecrc_frame->second[ii],
|
||||
debug_frame.second[ii])
|
||||
<< debug_frame.first << ": word " << ii;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto perframecrc_frame : perframecrc_configuration->frames()) {
|
||||
auto debug_frame = debug_configuration->frames().find(perframecrc_frame.first);
|
||||
auto debug_frame =
|
||||
debug_configuration->frames().find(perframecrc_frame.first);
|
||||
if (debug_frame == debug_configuration->frames().end()) {
|
||||
ADD_FAILURE() << perframecrc_frame.first
|
||||
<< ": unexpectedly present in perframecrc bitstream";
|
||||
<< ": unexpectedly present in "
|
||||
"perframecrc bitstream";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -166,47 +178,52 @@ TEST(ConfigurationTest, DebugAndNormalBitstreamsProduceEqualConfigurations) {
|
|||
ASSERT_TRUE(part);
|
||||
|
||||
auto debug_bitstream = prjxray::MemoryMappedFile::InitWithFile(
|
||||
"configuration_test.debug.bit");
|
||||
"configuration_test.debug.bit");
|
||||
ASSERT_TRUE(debug_bitstream);
|
||||
|
||||
auto debug_reader = xc7series::BitstreamReader::InitWithBytes(
|
||||
debug_bitstream->as_bytes());
|
||||
debug_bitstream->as_bytes());
|
||||
ASSERT_TRUE(debug_reader);
|
||||
|
||||
auto debug_configuration = xc7series::Configuration::InitWithPackets(
|
||||
*part, *debug_reader);
|
||||
auto debug_configuration =
|
||||
xc7series::Configuration::InitWithPackets(*part, *debug_reader);
|
||||
ASSERT_TRUE(debug_configuration);
|
||||
|
||||
auto normal_bitstream = prjxray::MemoryMappedFile::InitWithFile(
|
||||
"configuration_test.bit");
|
||||
auto normal_bitstream =
|
||||
prjxray::MemoryMappedFile::InitWithFile("configuration_test.bit");
|
||||
ASSERT_TRUE(normal_bitstream);
|
||||
|
||||
auto normal_reader = xc7series::BitstreamReader::InitWithBytes(
|
||||
normal_bitstream->as_bytes());
|
||||
normal_bitstream->as_bytes());
|
||||
ASSERT_TRUE(normal_reader);
|
||||
|
||||
auto normal_configuration = xc7series::Configuration::InitWithPackets(
|
||||
*part, *normal_reader);
|
||||
auto normal_configuration =
|
||||
xc7series::Configuration::InitWithPackets(*part, *normal_reader);
|
||||
ASSERT_TRUE(normal_configuration);
|
||||
|
||||
for (auto debug_frame : debug_configuration->frames()) {
|
||||
auto normal_frame = normal_configuration->frames().find(debug_frame.first);
|
||||
auto normal_frame =
|
||||
normal_configuration->frames().find(debug_frame.first);
|
||||
if (normal_frame == normal_configuration->frames().end()) {
|
||||
ADD_FAILURE() << debug_frame.first << ": missing in normal bitstream";
|
||||
ADD_FAILURE() << debug_frame.first
|
||||
<< ": missing in normal bitstream";
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int ii = 0; ii < 101; ++ii) {
|
||||
EXPECT_EQ(normal_frame->second[ii], debug_frame.second[ii])
|
||||
<< debug_frame.first << ": word " << ii;
|
||||
EXPECT_EQ(normal_frame->second[ii],
|
||||
debug_frame.second[ii])
|
||||
<< debug_frame.first << ": word " << ii;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto normal_frame : normal_configuration->frames()) {
|
||||
auto debug_frame = debug_configuration->frames().find(normal_frame.first);
|
||||
auto debug_frame =
|
||||
debug_configuration->frames().find(normal_frame.first);
|
||||
if (debug_frame == debug_configuration->frames().end()) {
|
||||
ADD_FAILURE() << normal_frame.first
|
||||
<< ": unexpectedly present in normal bitstream";
|
||||
ADD_FAILURE()
|
||||
<< normal_frame.first
|
||||
<< ": unexpectedly present in normal bitstream";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,11 @@ namespace prjxray {
|
|||
namespace xilinx {
|
||||
namespace xc7series {
|
||||
|
||||
FrameAddress::FrameAddress(BlockType block_type, bool is_bottom_half_rows,
|
||||
uint8_t row, uint16_t column, uint8_t minor) {
|
||||
FrameAddress::FrameAddress(BlockType block_type,
|
||||
bool is_bottom_half_rows,
|
||||
uint8_t row,
|
||||
uint16_t column,
|
||||
uint8_t minor) {
|
||||
address_ = bit_field_set(0, 25, 23, block_type);
|
||||
address_ = bit_field_set(address_, 22, 22, is_bottom_half_rows);
|
||||
address_ = bit_field_set(address_, 21, 17, row);
|
||||
|
|
@ -37,23 +40,16 @@ uint8_t FrameAddress::minor_address() const {
|
|||
return bit_field_get(address_, 6, 0);
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &o, const FrameAddress& addr) {
|
||||
o << "["
|
||||
<< std::hex << std::showbase << std::setw(10)
|
||||
<< static_cast<uint32_t>(addr)
|
||||
<< "] "
|
||||
<< (addr.is_bottom_half_rows() ? "BOTTOM" : "TOP")
|
||||
<< " Row="
|
||||
<< std::setw(2) << std::dec
|
||||
std::ostream& operator<<(std::ostream& o, const FrameAddress& addr) {
|
||||
o << "[" << std::hex << std::showbase << std::setw(10)
|
||||
<< static_cast<uint32_t>(addr) << "] "
|
||||
<< (addr.is_bottom_half_rows() ? "BOTTOM" : "TOP")
|
||||
<< " Row=" << std::setw(2) << std::dec
|
||||
<< static_cast<unsigned int>(addr.row_address())
|
||||
<< " Column="
|
||||
<< std::setw(2) << std::dec
|
||||
<< addr.column_address()
|
||||
<< " Minor="
|
||||
<< std::setw(2) << std::dec
|
||||
<< " Column=" << std::setw(2) << std::dec << addr.column_address()
|
||||
<< " Minor=" << std::setw(2) << std::dec
|
||||
<< static_cast<unsigned int>(addr.minor_address())
|
||||
<< " Type="
|
||||
<< addr.block_type();
|
||||
<< " Type=" << addr.block_type();
|
||||
return o;
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +62,7 @@ namespace YAML {
|
|||
namespace xc7series = prjxray::xilinx::xc7series;
|
||||
|
||||
Node convert<xc7series::FrameAddress>::encode(
|
||||
const xc7series::FrameAddress &rhs) {
|
||||
const xc7series::FrameAddress& rhs) {
|
||||
Node node;
|
||||
node.SetTag("xilinx/xc7series/frame_address");
|
||||
node["block_type"] = rhs.block_type();
|
||||
|
|
@ -77,15 +73,13 @@ Node convert<xc7series::FrameAddress>::encode(
|
|||
return node;
|
||||
}
|
||||
|
||||
bool convert<xc7series::FrameAddress>::decode(
|
||||
const Node &node, xc7series::FrameAddress &lhs) {
|
||||
bool convert<xc7series::FrameAddress>::decode(const Node& node,
|
||||
xc7series::FrameAddress& lhs) {
|
||||
if (!(node.Tag() == "xilinx/xc7series/frame_address" ||
|
||||
node.Tag() == "xilinx/xc7series/configuration_frame_address") ||
|
||||
!node["block_type"] ||
|
||||
!node["row_half"] ||
|
||||
!node["row"] ||
|
||||
!node["column"] ||
|
||||
!node["minor"]) return false;
|
||||
!node["block_type"] || !node["row_half"] || !node["row"] ||
|
||||
!node["column"] || !node["minor"])
|
||||
return false;
|
||||
|
||||
bool row_half;
|
||||
if (node["row_half"].as<std::string>() == "top") {
|
||||
|
|
@ -97,12 +91,10 @@ bool convert<xc7series::FrameAddress>::decode(
|
|||
}
|
||||
|
||||
lhs = prjxray::xilinx::xc7series::FrameAddress(
|
||||
node["block_type"].as<xc7series::BlockType>(),
|
||||
row_half,
|
||||
node["row"].as<unsigned int>(),
|
||||
node["column"].as<unsigned int>(),
|
||||
node["minor"].as<unsigned int>());
|
||||
node["block_type"].as<xc7series::BlockType>(), row_half,
|
||||
node["row"].as<unsigned int>(), node["column"].as<unsigned int>(),
|
||||
node["minor"].as<unsigned int>());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace YAML;
|
||||
} // namespace YAML
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
namespace xc7series = prjxray::xilinx::xc7series;
|
||||
|
||||
TEST(FrameAddressTest, YamlEncode) {
|
||||
xc7series::FrameAddress address(xc7series::BlockType::BLOCK_RAM,
|
||||
false, 10, 0, 5);
|
||||
xc7series::FrameAddress address(xc7series::BlockType::BLOCK_RAM, false,
|
||||
10, 0, 5);
|
||||
|
||||
YAML::Node node(address);
|
||||
|
||||
|
|
@ -27,8 +27,7 @@ TEST(FrameAddressTest, YamlDecode) {
|
|||
node["column"] = "5";
|
||||
node["minor"] = "11";
|
||||
|
||||
xc7series::FrameAddress address =
|
||||
node.as<xc7series::FrameAddress>();
|
||||
xc7series::FrameAddress address = node.as<xc7series::FrameAddress>();
|
||||
EXPECT_EQ(address.block_type(), xc7series::BlockType::BLOCK_RAM);
|
||||
EXPECT_TRUE(address.is_bottom_half_rows());
|
||||
EXPECT_EQ(address.row_address(), 0);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace prjxray {
|
|||
namespace xilinx {
|
||||
namespace xc7series {
|
||||
|
||||
absl::optional<Part> Part::FromFile(const std::string &path) {
|
||||
absl::optional<Part> Part::FromFile(const std::string& path) {
|
||||
try {
|
||||
YAML::Node yaml = YAML::LoadFile(path);
|
||||
return yaml.as<Part>();
|
||||
|
|
@ -16,8 +16,8 @@ absl::optional<Part> Part::FromFile(const std::string &path) {
|
|||
}
|
||||
}
|
||||
|
||||
absl::optional<FrameAddress>
|
||||
Part::GetNextFrameAddress(FrameAddress address) const {
|
||||
absl::optional<FrameAddress> Part::GetNextFrameAddress(
|
||||
FrameAddress address) const {
|
||||
// Start with the next linear address.
|
||||
FrameAddress target_address(address + 1);
|
||||
|
||||
|
|
@ -27,8 +27,7 @@ Part::GetNextFrameAddress(FrameAddress address) const {
|
|||
// address.
|
||||
absl::optional<FrameAddress> closest_address;
|
||||
int32_t closest_distance;
|
||||
for (auto iter = frame_ranges_.begin();
|
||||
iter != frame_ranges_.end();
|
||||
for (auto iter = frame_ranges_.begin(); iter != frame_ranges_.end();
|
||||
++iter) {
|
||||
if (iter->Contains(target_address)) {
|
||||
return target_address;
|
||||
|
|
@ -36,8 +35,7 @@ Part::GetNextFrameAddress(FrameAddress address) const {
|
|||
|
||||
int32_t distance = iter->begin() - target_address;
|
||||
if (distance > 0 &&
|
||||
(!closest_address ||
|
||||
distance < closest_distance)) {
|
||||
(!closest_address || distance < closest_distance)) {
|
||||
closest_address = iter->begin();
|
||||
closest_distance = distance;
|
||||
}
|
||||
|
|
@ -54,7 +52,7 @@ namespace xc7series = prjxray::xilinx::xc7series;
|
|||
|
||||
namespace YAML {
|
||||
|
||||
Node convert<xc7series::Part>::encode(const xc7series::Part &rhs) {
|
||||
Node convert<xc7series::Part>::encode(const xc7series::Part& rhs) {
|
||||
Node node;
|
||||
node.SetTag("xilinx/xc7series/part");
|
||||
|
||||
|
|
@ -66,17 +64,16 @@ Node convert<xc7series::Part>::encode(const xc7series::Part &rhs) {
|
|||
return node;
|
||||
}
|
||||
|
||||
bool convert<xc7series::Part>::decode(const Node &node, xc7series::Part &lhs) {
|
||||
if (node.Tag() != "xilinx/xc7series/part" ||
|
||||
!node["idcode"] ||
|
||||
!node["configuration_ranges"]) return false;
|
||||
bool convert<xc7series::Part>::decode(const Node& node, xc7series::Part& lhs) {
|
||||
if (node.Tag() != "xilinx/xc7series/part" || !node["idcode"] ||
|
||||
!node["configuration_ranges"])
|
||||
return false;
|
||||
|
||||
lhs = xc7series::Part(
|
||||
node["idcode"].as<uint32_t>(),
|
||||
node["configuration_ranges"].as<
|
||||
std::vector<xc7series::ConfigurationFrameRange>>());
|
||||
node["idcode"].as<uint32_t>(),
|
||||
node["configuration_ranges"]
|
||||
.as<std::vector<xc7series::ConfigurationFrameRange>>());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace YAML;
|
||||
|
||||
} // namespace YAML
|
||||
|
|
|
|||
182
tools/bitread.cc
182
tools/bitread.cc
|
|
@ -1,10 +1,10 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <absl/strings/numbers.h>
|
||||
|
|
@ -19,20 +19,27 @@
|
|||
|
||||
DEFINE_bool(c, false, "output '*' for repeating patterns");
|
||||
DEFINE_bool(C, false, "do not ignore the checksum in each frame");
|
||||
DEFINE_int32(f, -1, "only dump the specified frame (might be used more than once)");
|
||||
DEFINE_string(F, "", "<first_frame_address>:<last_frame_address> only dump frame in the specified range");
|
||||
DEFINE_int32(f,
|
||||
-1,
|
||||
"only dump the specified frame (might be used more than once)");
|
||||
DEFINE_string(F,
|
||||
"",
|
||||
"<first_frame_address>:<last_frame_address> only dump frame in "
|
||||
"the specified range");
|
||||
DEFINE_string(o, "", "write machine-readable output file with config frames");
|
||||
DEFINE_bool(p, false, "output a binary netpgm image");
|
||||
DEFINE_bool(x, false, "use format 'bit_%%08x_%%03d_%%02d_t%%d_h%%d_r%%d_c%%d_m%%d'\n"
|
||||
"The fields have the following meaning:\n"
|
||||
" - complete 32 bit hex frame id\n"
|
||||
" - word index with that frame (decimal)\n"
|
||||
" - bit index with that word (decimal)\n"
|
||||
" - decoded frame type from frame id\n"
|
||||
" - decoded top/botttom from frame id (top=0)\n"
|
||||
" - decoded row address from frame id\n"
|
||||
" - decoded column address from frame id\n"
|
||||
" - decoded minor address from frame id\n");
|
||||
DEFINE_bool(x,
|
||||
false,
|
||||
"use format 'bit_%%08x_%%03d_%%02d_t%%d_h%%d_r%%d_c%%d_m%%d'\n"
|
||||
"The fields have the following meaning:\n"
|
||||
" - complete 32 bit hex frame id\n"
|
||||
" - word index with that frame (decimal)\n"
|
||||
" - bit index with that word (decimal)\n"
|
||||
" - decoded frame type from frame id\n"
|
||||
" - decoded top/botttom from frame id (top=0)\n"
|
||||
" - decoded row address from frame id\n"
|
||||
" - decoded column address from frame id\n"
|
||||
" - decoded minor address from frame id\n");
|
||||
DEFINE_bool(y, false, "use format 'bit_%%08x_%%03d_%%02d'");
|
||||
DEFINE_bool(z, false, "skip zero frames (frames with all bits cleared) in o");
|
||||
DEFINE_string(part_file, "", "YAML file describing a Xilinx 7-Series part");
|
||||
|
|
@ -44,9 +51,9 @@ uint32_t frame_range_begin = 0, frame_range_end = 0;
|
|||
|
||||
std::vector<uint32_t> zero_frame(101);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int main(int argc, char** argv) {
|
||||
gflags::SetUsageMessage(
|
||||
absl::StrCat("Usage: ", argv[0], " [options] [bitfile]"));
|
||||
absl::StrCat("Usage: ", argv[0], " [options] [bitfile]"));
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
auto part = xc7series::Part::FromFile(FLAGS_part_file);
|
||||
|
|
@ -60,7 +67,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
if (!FLAGS_F.empty()) {
|
||||
std::pair<std::string, std::string> p = absl::StrSplit(FLAGS_F, ":");
|
||||
std::pair<std::string, std::string> p =
|
||||
absl::StrSplit(FLAGS_F, ":");
|
||||
frame_range_begin = strtol(p.first.c_str(), nullptr, 0);
|
||||
frame_range_end = strtol(p.second.c_str(), nullptr, 0) + 1;
|
||||
}
|
||||
|
|
@ -68,59 +76,61 @@ int main(int argc, char **argv) {
|
|||
absl::optional<xc7series::BitstreamReader> reader;
|
||||
if (argc == 2) {
|
||||
auto in_file_name = argv[1];
|
||||
auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
|
||||
auto in_file =
|
||||
prjxray::MemoryMappedFile::InitWithFile(in_file_name);
|
||||
if (!in_file) {
|
||||
std::cerr << "Can't open input file '" << in_file_name
|
||||
<< "' for reading!" << std::endl;
|
||||
<< "' for reading!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Bitstream size: " << in_file->size() << " bytes"
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
reader = xc7series::BitstreamReader::InitWithBytes(
|
||||
in_file->as_bytes());
|
||||
in_file->as_bytes());
|
||||
} else {
|
||||
std::vector<uint8_t> bitdata;
|
||||
while (1) {
|
||||
int c = getchar();
|
||||
if (c == EOF) break;
|
||||
if (c == EOF)
|
||||
break;
|
||||
bitdata.push_back(c);
|
||||
}
|
||||
|
||||
std::cout << "Bitstream size: " << bitdata.size() << " bytes"
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
|
||||
reader = xc7series::BitstreamReader::InitWithBytes(bitdata);
|
||||
}
|
||||
|
||||
if (!reader) {
|
||||
std::cerr << "Bitstream does not appear to be a Xilinx "
|
||||
<< "7-series bitstream!" << std::endl;
|
||||
<< "7-series bitstream!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Config size: " << reader->words().size()
|
||||
<< " words" << std::endl;
|
||||
std::cout << "Config size: " << reader->words().size() << " words"
|
||||
<< std::endl;
|
||||
|
||||
auto config = xc7series::Configuration::InitWithPackets(*part, *reader);
|
||||
if (!config) {
|
||||
std::cerr << "Bitstream does not appear to be for this part"
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Number of configuration frames: "
|
||||
<< config->frames().size() << std::endl;
|
||||
<< config->frames().size() << std::endl;
|
||||
|
||||
FILE *f = stdout;
|
||||
FILE* f = stdout;
|
||||
|
||||
if (!FLAGS_o.empty())
|
||||
{
|
||||
if (!FLAGS_o.empty()) {
|
||||
f = fopen(FLAGS_o.c_str(), "w");
|
||||
|
||||
if (f == nullptr) {
|
||||
printf("Can't open output file '%s' for writing!\n", FLAGS_o.c_str());
|
||||
printf("Can't open output file '%s' for writing!\n",
|
||||
FLAGS_o.c_str());
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -130,8 +140,7 @@ int main(int argc, char **argv) {
|
|||
std::vector<std::vector<bool>> pgmdata;
|
||||
std::vector<int> pgmsep;
|
||||
|
||||
for (auto &it : config->frames())
|
||||
{
|
||||
for (auto& it : config->frames()) {
|
||||
if (FLAGS_z && it.second == zero_frame)
|
||||
continue;
|
||||
|
||||
|
|
@ -139,67 +148,95 @@ int main(int argc, char **argv) {
|
|||
continue;
|
||||
|
||||
if (frame_range_begin != frame_range_end &&
|
||||
(it.first < frame_range_begin || frame_range_end <= it.first))
|
||||
(it.first < frame_range_begin ||
|
||||
frame_range_end <= it.first))
|
||||
continue;
|
||||
|
||||
if (FLAGS_o.empty())
|
||||
printf("Frame 0x%08x (Type=%d Top=%d Row=%d Column=%d Minor=%d):\n",
|
||||
static_cast<uint32_t>(it.first), static_cast<unsigned int>(it.first.block_type()),
|
||||
it.first.is_bottom_half_rows() ? 1 : 0,
|
||||
it.first.row_address(), it.first.column_address(), it.first.minor_address());
|
||||
printf(
|
||||
"Frame 0x%08x (Type=%d Top=%d Row=%d Column=%d "
|
||||
"Minor=%d):\n",
|
||||
static_cast<uint32_t>(it.first),
|
||||
static_cast<unsigned int>(it.first.block_type()),
|
||||
it.first.is_bottom_half_rows() ? 1 : 0,
|
||||
it.first.row_address(), it.first.column_address(),
|
||||
it.first.minor_address());
|
||||
|
||||
if (FLAGS_p)
|
||||
{
|
||||
if (FLAGS_p) {
|
||||
if (it.first.minor_address() == 0 && !pgmdata.empty())
|
||||
pgmsep.push_back(pgmdata.size());
|
||||
|
||||
pgmdata.push_back(std::vector<bool>());
|
||||
|
||||
for (int i = 0; i < 101; i++)
|
||||
for (int k = 0; k < 32; k++)
|
||||
pgmdata.back().push_back((it.second.at(i) & (1 << k)) != 0);
|
||||
}
|
||||
else
|
||||
if (FLAGS_x || FLAGS_y)
|
||||
{
|
||||
for (int k = 0; k < 32; k++)
|
||||
pgmdata.back().push_back(
|
||||
(it.second.at(i) & (1 << k)) != 0);
|
||||
} else if (FLAGS_x || FLAGS_y) {
|
||||
for (int i = 0; i < 101; i++)
|
||||
for (int k = 0; k < 32; k++)
|
||||
if ((i != 50 || k > 12 || FLAGS_C) && ((it.second.at(i) & (1 << k)) != 0)) {
|
||||
if (FLAGS_x)
|
||||
fprintf(f, "bit_%08x_%03d_%02d_t%d_h%d_r%d_c%d_m%d\n",
|
||||
static_cast<uint32_t>(it.first),
|
||||
i, k,
|
||||
static_cast<unsigned int>(it.first.block_type()),
|
||||
it.first.is_bottom_half_rows() ? 1 : 0,
|
||||
it.first.row_address(), it.first.column_address(), it.first.minor_address());
|
||||
else
|
||||
fprintf(f, "bit_%08x_%03d_%02d\n", static_cast<uint32_t>(it.first), i, k);
|
||||
}
|
||||
for (int k = 0; k < 32; k++)
|
||||
if ((i != 50 || k > 12 || FLAGS_C) &&
|
||||
((it.second.at(i) & (1 << k)) !=
|
||||
0)) {
|
||||
if (FLAGS_x)
|
||||
fprintf(
|
||||
f,
|
||||
"bit_%08x_%03d_%"
|
||||
"02d_t%d_h%d_r%d_c%"
|
||||
"d_m%d\n",
|
||||
static_cast<
|
||||
uint32_t>(
|
||||
it.first),
|
||||
i, k,
|
||||
static_cast<
|
||||
unsigned int>(
|
||||
it.first
|
||||
.block_type()),
|
||||
it.first.is_bottom_half_rows()
|
||||
? 1
|
||||
: 0,
|
||||
it.first
|
||||
.row_address(),
|
||||
it.first
|
||||
.column_address(),
|
||||
it.first
|
||||
.minor_address());
|
||||
else
|
||||
fprintf(f,
|
||||
"bit_%08x_%03d_"
|
||||
"%02d\n",
|
||||
static_cast<
|
||||
uint32_t>(
|
||||
it.first),
|
||||
i, k);
|
||||
}
|
||||
if (FLAGS_o.empty())
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (!FLAGS_o.empty())
|
||||
fprintf(f, ".frame 0x%08x\n", static_cast<uint32_t>(it.first));
|
||||
fprintf(f, ".frame 0x%08x\n",
|
||||
static_cast<uint32_t>(it.first));
|
||||
|
||||
for (int i = 0; i < 101; i++)
|
||||
fprintf(f, "%08x%s", it.second.at(i) & ((i != 50 || FLAGS_C) ? 0xffffffff : 0xffffe000), (i % 6) == 5 ? "\n" : " ");
|
||||
fprintf(f, "%08x%s",
|
||||
it.second.at(i) &
|
||||
((i != 50 || FLAGS_C) ? 0xffffffff
|
||||
: 0xffffe000),
|
||||
(i % 6) == 5 ? "\n" : " ");
|
||||
fprintf(f, "\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (FLAGS_p)
|
||||
{
|
||||
if (FLAGS_p) {
|
||||
int width = pgmdata.size() + pgmsep.size();
|
||||
int height = 101*32+100;
|
||||
int height = 101 * 32 + 100;
|
||||
fprintf(f, "P5 %d %d 15\n", width, height);
|
||||
|
||||
for (int y = 0, bit = 101*32-1; y < height; y++, bit--)
|
||||
{
|
||||
for (int x = 0, frame = 0, sep = 0; x < width; x++, frame++)
|
||||
{
|
||||
if (sep < int(pgmsep.size()) && frame == pgmsep.at(sep)) {
|
||||
for (int y = 0, bit = 101 * 32 - 1; y < height; y++, bit--) {
|
||||
for (int x = 0, frame = 0, sep = 0; x < width;
|
||||
x++, frame++) {
|
||||
if (sep < int(pgmsep.size()) &&
|
||||
frame == pgmsep.at(sep)) {
|
||||
fputc(8, f);
|
||||
x++, sep++;
|
||||
}
|
||||
|
|
@ -221,4 +258,3 @@ int main(int argc, char **argv) {
|
|||
printf("DONE\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,15 +11,14 @@ namespace xc7series = prjxray::xilinx::xc7series;
|
|||
|
||||
struct Action {
|
||||
std::string name;
|
||||
std::function<int(int, char*[])> handler;
|
||||
std::function<int(int, char* [])> handler;
|
||||
};
|
||||
|
||||
int ListConfigPackets(int argc, char *argv[]) {
|
||||
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 <bit_file>"
|
||||
<< std::endl;
|
||||
<< "list_config_packets <bit_file>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -27,15 +26,14 @@ int ListConfigPackets(int argc, char *argv[]) {
|
|||
auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
|
||||
if (!in_file) {
|
||||
std::cerr << "Unable to open bit file: " << in_file_name
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto reader = xc7series::BitstreamReader::InitWithBytes(
|
||||
in_file->as_bytes());
|
||||
auto reader =
|
||||
xc7series::BitstreamReader::InitWithBytes(in_file->as_bytes());
|
||||
if (!reader) {
|
||||
std::cerr << "Input doesn't look like a bitstream"
|
||||
<< std::endl;
|
||||
std::cerr << "Input doesn't look like a bitstream" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -46,12 +44,12 @@ int ListConfigPackets(int argc, char *argv[]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int DumpDebugbitstreamFrameAddresses(int argc, char *argv[]) {
|
||||
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 <bit_file>"
|
||||
<< std::endl;
|
||||
<< "dump_debugbitstream_frame_addresses <bit_file>"
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -59,17 +57,15 @@ int DumpDebugbitstreamFrameAddresses(int argc, char *argv[]) {
|
|||
auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
|
||||
if (!in_file) {
|
||||
std::cerr << "Unable to open bit file: " << in_file_name
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto in_bytes = absl::Span<uint8_t>(
|
||||
static_cast<uint8_t*>(in_file->data()),
|
||||
in_file->size());
|
||||
static_cast<uint8_t*>(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;
|
||||
std::cerr << "Input doesn't look like a bitstream" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -84,7 +80,7 @@ int DumpDebugbitstreamFrameAddresses(int argc, char *argv[]) {
|
|||
|
||||
if (packet.data().size() != 1) {
|
||||
std::cerr << "Write to FAR with word_count != 1"
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -94,20 +90,19 @@ int DumpDebugbitstreamFrameAddresses(int argc, char *argv[]) {
|
|||
|
||||
if (!found_one_lout) {
|
||||
std::cerr << "No LOUT writes found. Was "
|
||||
<< "BITSTREAM.GENERAL.DEBUGBITSTREAM set to YES?"
|
||||
<< std::endl;
|
||||
<< "BITSTREAM.GENERAL.DEBUGBITSTREAM set to YES?"
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetDeviceId(int argc, char *argv[]) {
|
||||
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 <bit_file>"
|
||||
<< std::endl;
|
||||
std::cerr << "Usage: " << argv[0] << "get_device_id <bit_file>"
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -115,68 +110,65 @@ int GetDeviceId(int argc, char *argv[]) {
|
|||
auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
|
||||
if (!in_file) {
|
||||
std::cerr << "Unable to open bit file: " << in_file_name
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto in_bytes = absl::Span<uint8_t>(
|
||||
static_cast<uint8_t*>(in_file->data()),
|
||||
in_file->size());
|
||||
static_cast<uint8_t*>(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;
|
||||
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);
|
||||
});
|
||||
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;
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "0x" << std::hex << idcode_packet->data()[0]
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
Action actions[] = {
|
||||
{ "list_config_packets", ListConfigPackets },
|
||||
{ "dump_debugbitstream_frame_addresses",
|
||||
DumpDebugbitstreamFrameAddresses },
|
||||
{ "get_device_id", GetDeviceId },
|
||||
{"list_config_packets", ListConfigPackets},
|
||||
{"dump_debugbitstream_frame_addresses",
|
||||
DumpDebugbitstreamFrameAddresses},
|
||||
{"get_device_id", GetDeviceId},
|
||||
};
|
||||
|
||||
gflags::SetUsageMessage(
|
||||
absl::StrCat("Usage: ", argv[0], " [options] [bitfile]"));
|
||||
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]
|
||||
<< "<command> <command_options>" << std::endl;
|
||||
<< "<command> <command_options>" << 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; });
|
||||
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;
|
||||
std::cerr << "Unknown action: " << requested_action_str
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
namespace xc7series = prjxray::xilinx::xc7series;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
std::istream * input_stream = &std::cin;
|
||||
int main(int argc, char* argv[]) {
|
||||
std::istream* input_stream = &std::cin;
|
||||
if (argc > 1) {
|
||||
auto file_stream = std::ifstream(argv[1]);
|
||||
if (file_stream) {
|
||||
|
|
@ -16,27 +16,19 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
for (uint32_t frame_address_raw;
|
||||
(*input_stream) >> std::setbase(0) >> frame_address_raw;
|
||||
) {
|
||||
(*input_stream) >> std::setbase(0) >> frame_address_raw;) {
|
||||
xc7series::FrameAddress frame_address(frame_address_raw);
|
||||
std::cout << "["
|
||||
<< std::hex << std::showbase << std::setw(10)
|
||||
<< frame_address_raw
|
||||
<< "] "
|
||||
<< (frame_address.is_bottom_half_rows() ?
|
||||
"BOTTOM" : "TOP")
|
||||
<< " Row="
|
||||
<< std::setw(2) << std::dec
|
||||
<< static_cast<unsigned int>(frame_address.row_address())
|
||||
<< " Column="
|
||||
<< std::setw(2) << std::dec
|
||||
<< frame_address.column_address()
|
||||
<< " Minor="
|
||||
<< std::setw(2) << std::dec
|
||||
<< static_cast<unsigned int>(frame_address.minor_address())
|
||||
<< " Type="
|
||||
<< frame_address.block_type()
|
||||
<< std::endl;
|
||||
std::cout
|
||||
<< "[" << std::hex << std::showbase << std::setw(10)
|
||||
<< frame_address_raw << "] "
|
||||
<< (frame_address.is_bottom_half_rows() ? "BOTTOM" : "TOP")
|
||||
<< " Row=" << std::setw(2) << std::dec
|
||||
<< static_cast<unsigned int>(frame_address.row_address())
|
||||
<< " Column=" << std::setw(2) << std::dec
|
||||
<< frame_address.column_address()
|
||||
<< " Minor=" << std::setw(2) << std::dec
|
||||
<< static_cast<unsigned int>(frame_address.minor_address())
|
||||
<< " Type=" << frame_address.block_type() << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -13,12 +13,11 @@
|
|||
|
||||
namespace xc7series = prjxray::xilinx::xc7series;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "ERROR: no input specified" << std::endl;
|
||||
std::cerr << "Usage: " << basename(argv[0])
|
||||
<< " <bit_file>"
|
||||
<< std::endl;
|
||||
std::cerr << "Usage: " << basename(argv[0]) << " <bit_file>"
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -26,15 +25,14 @@ int main(int argc, char *argv[]) {
|
|||
auto in_file = prjxray::MemoryMappedFile::InitWithFile(in_file_name);
|
||||
if (!in_file) {
|
||||
std::cerr << "Unable to open bit file: " << in_file_name
|
||||
<< std::endl;
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto reader = xc7series::BitstreamReader::InitWithBytes(
|
||||
in_file->as_bytes());
|
||||
auto reader =
|
||||
xc7series::BitstreamReader::InitWithBytes(in_file->as_bytes());
|
||||
if (!reader) {
|
||||
std::cerr << "Input doesn't look like a bitstream"
|
||||
<< std::endl;
|
||||
std::cerr << "Input doesn't look like a bitstream" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +41,7 @@ int main(int argc, char *argv[]) {
|
|||
absl::optional<uint32_t> idcode;
|
||||
for (auto packet : *reader) {
|
||||
if (packet.opcode() !=
|
||||
xc7series::ConfigurationPacket::Opcode::Write) {
|
||||
xc7series::ConfigurationPacket::Opcode::Write) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -51,13 +49,13 @@ int main(int argc, char *argv[]) {
|
|||
xc7series::ConfigurationRegister::FDRI) {
|
||||
found_fdri_write = true;
|
||||
} else if ((packet.address() ==
|
||||
xc7series::ConfigurationRegister::IDCODE) &&
|
||||
packet.data().size() == 1) {
|
||||
xc7series::ConfigurationRegister::IDCODE) &&
|
||||
packet.data().size() == 1) {
|
||||
idcode = packet.data()[0];
|
||||
} else if (found_fdri_write &&
|
||||
(packet.address() ==
|
||||
xc7series::ConfigurationRegister::LOUT) &&
|
||||
packet.data().size() == 1) {
|
||||
(packet.address() ==
|
||||
xc7series::ConfigurationRegister::LOUT) &&
|
||||
packet.data().size() == 1) {
|
||||
frame_addresses.push_back(packet.data()[0]);
|
||||
}
|
||||
}
|
||||
|
|
@ -69,8 +67,8 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
if (frame_addresses.empty()) {
|
||||
std::cerr << "No LOUT writes found. Was "
|
||||
<< "BITSTREAM.GENERAL.DEBUGBITSTREAM set to YES?"
|
||||
<< std::endl;
|
||||
<< "BITSTREAM.GENERAL.DEBUGBITSTREAM set to YES?"
|
||||
<< std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -80,17 +78,15 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
std::vector<xc7series::ConfigurationFrameRange> ranges;
|
||||
for (auto start_of_range = frame_addresses.begin();
|
||||
start_of_range != frame_addresses.end();
|
||||
) {
|
||||
start_of_range != frame_addresses.end();) {
|
||||
auto end_of_range = start_of_range;
|
||||
while (end_of_range + 1 != frame_addresses.end() &&
|
||||
*(end_of_range + 1) == *end_of_range + 1) {
|
||||
++end_of_range;
|
||||
}
|
||||
|
||||
ranges.push_back(
|
||||
xc7series::ConfigurationFrameRange(*start_of_range,
|
||||
*end_of_range+1));
|
||||
ranges.push_back(xc7series::ConfigurationFrameRange(
|
||||
*start_of_range, *end_of_range + 1));
|
||||
|
||||
start_of_range = ++end_of_range;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,23 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <numeric>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <absl/strings/str_cat.h>
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
DEFINE_int32(c, 4, "threshold under which candidates are output. set to -1 to output all.");
|
||||
DEFINE_int32(
|
||||
c,
|
||||
4,
|
||||
"threshold under which candidates are output. set to -1 to output all.");
|
||||
DEFINE_bool(i, false, "add inverted tags");
|
||||
DEFINE_int32(m, 0, "min number of set/cleared samples each");
|
||||
DEFINE_int32(M, 0, "min number of set/cleared samples total");
|
||||
|
|
@ -22,9 +25,9 @@ DEFINE_string(o, "", "set output file");
|
|||
DEFINE_string(k, "", "set output mask file");
|
||||
|
||||
using std::map;
|
||||
using std::string;
|
||||
using std::tuple;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
int num_bits = 0, num_tags = 0;
|
||||
map<string, int> bit_ids, tag_ids;
|
||||
|
|
@ -76,51 +79,40 @@ struct bool_vec
|
|||
}
|
||||
};
|
||||
#else
|
||||
struct bool_vec
|
||||
{
|
||||
struct bool_vec {
|
||||
vector<uint64_t> data;
|
||||
|
||||
bool_vec(int n = 0, bool initval = false) :
|
||||
data((n+63)/64, initval ? ~uint64_t(0) : uint64_t(0))
|
||||
{
|
||||
for (int i = data.size()*64-1; i >= n; i--)
|
||||
bool_vec(int n = 0, bool initval = false)
|
||||
: data((n + 63) / 64, initval ? ~uint64_t(0) : uint64_t(0)) {
|
||||
for (int i = data.size() * 64 - 1; i >= n; i--)
|
||||
data[n / 64] &= ~(uint64_t(1) << (n % 64));
|
||||
}
|
||||
|
||||
void set(int n)
|
||||
{
|
||||
if (int(data.size()*64) <= n)
|
||||
data.resize((n+64) / 64);
|
||||
void set(int n) {
|
||||
if (int(data.size() * 64) <= n)
|
||||
data.resize((n + 64) / 64);
|
||||
data[n / 64] |= uint64_t(1) << (n % 64);
|
||||
}
|
||||
|
||||
bool get(int n)
|
||||
{
|
||||
return (data[n / 64] >> (n % 64)) & 1;
|
||||
}
|
||||
bool get(int n) { return (data[n / 64] >> (n % 64)) & 1; }
|
||||
|
||||
void resize(int n)
|
||||
{
|
||||
data.resize((n+63) / 64);
|
||||
}
|
||||
void resize(int n) { data.resize((n + 63) / 64); }
|
||||
|
||||
int count()
|
||||
{
|
||||
int count() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 64*int(data.size()); i++)
|
||||
if (get(i)) sum++;
|
||||
for (int i = 0; i < 64 * int(data.size()); i++)
|
||||
if (get(i))
|
||||
sum++;
|
||||
return sum;
|
||||
}
|
||||
|
||||
void apply_and(const bool_vec &other)
|
||||
{
|
||||
void apply_and(const bool_vec& other) {
|
||||
assert(data.size() == other.data.size());
|
||||
for (int i = 0; i < int(data.size()); i++)
|
||||
data[i] &= other.data[i];
|
||||
}
|
||||
|
||||
void apply_andc(const bool_vec &other)
|
||||
{
|
||||
void apply_andc(const bool_vec& other) {
|
||||
assert(data.size() == other.data.size());
|
||||
for (int i = 0; i < int(data.size()); i++)
|
||||
data[i] &= ~other.data[i];
|
||||
|
|
@ -134,19 +126,22 @@ map<string, segdata_t> segdata;
|
|||
|
||||
map<string, int> segnamecnt;
|
||||
|
||||
static inline bool_vec &segdata_bits(segdata_t &sd) { return std::get<0>(sd); }
|
||||
static inline bool_vec &segdata_tags1(segdata_t &sd) { return std::get<1>(sd); }
|
||||
static inline bool_vec &segdata_tags0(segdata_t &sd) { return std::get<2>(sd); }
|
||||
static inline bool_vec& segdata_bits(segdata_t& sd) {
|
||||
return std::get<0>(sd);
|
||||
}
|
||||
static inline bool_vec& segdata_tags1(segdata_t& sd) {
|
||||
return std::get<1>(sd);
|
||||
}
|
||||
static inline bool_vec& segdata_tags0(segdata_t& sd) {
|
||||
return std::get<2>(sd);
|
||||
}
|
||||
|
||||
void read_input(std::istream &f, std::string filename)
|
||||
{
|
||||
void read_input(std::istream& f, std::string filename) {
|
||||
string token;
|
||||
segdata_t *segptr = nullptr;
|
||||
segdata_t* segptr = nullptr;
|
||||
|
||||
while (f >> token)
|
||||
{
|
||||
if (token == "seg")
|
||||
{
|
||||
while (f >> token) {
|
||||
if (token == "seg") {
|
||||
f >> token;
|
||||
token = filename + ":" + token;
|
||||
while (segdata.count(token)) {
|
||||
|
|
@ -162,8 +157,7 @@ void read_input(std::istream &f, std::string filename)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (token == "bit")
|
||||
{
|
||||
if (token == "bit") {
|
||||
assert(segptr != nullptr);
|
||||
|
||||
f >> token;
|
||||
|
|
@ -173,14 +167,13 @@ void read_input(std::istream &f, std::string filename)
|
|||
}
|
||||
|
||||
int bit_idx = bit_ids.at(token);
|
||||
auto &bits = segdata_bits(*segptr);
|
||||
auto& bits = segdata_bits(*segptr);
|
||||
|
||||
bits.set(bit_idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token == "tag")
|
||||
{
|
||||
if (token == "tag") {
|
||||
assert(segptr != nullptr);
|
||||
|
||||
f >> token;
|
||||
|
|
@ -194,13 +187,15 @@ void read_input(std::istream &f, std::string filename)
|
|||
f >> token;
|
||||
assert(token == "0" || token == "1");
|
||||
|
||||
auto &tags = token == "1" ? segdata_tags1(*segptr) : segdata_tags0(*segptr);
|
||||
auto& tags = token == "1" ? segdata_tags1(*segptr)
|
||||
: segdata_tags0(*segptr);
|
||||
|
||||
tags.set(tag_idx);
|
||||
|
||||
if (FLAGS_i)
|
||||
{
|
||||
auto &inv_tags = token == "1" ? segdata_tags0(*segptr) : segdata_tags1(*segptr);
|
||||
if (FLAGS_i) {
|
||||
auto& inv_tags = token == "1"
|
||||
? segdata_tags0(*segptr)
|
||||
: segdata_tags1(*segptr);
|
||||
|
||||
token = tag_ids_r.at(tag_idx) + "__INV";
|
||||
|
||||
|
|
@ -223,17 +218,16 @@ void read_input(std::istream &f, std::string filename)
|
|||
// printf("Number of bits: %d\n", num_bits);
|
||||
// printf("Number of tags: %d\n", num_tags);
|
||||
|
||||
for (auto &segdat : segdata) {
|
||||
for (auto& segdat : segdata) {
|
||||
segdata_bits(segdat.second).resize(num_bits);
|
||||
segdata_tags1(segdat.second).resize(num_tags);
|
||||
segdata_tags0(segdat.second).resize(num_tags);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int main(int argc, char** argv) {
|
||||
gflags::SetUsageMessage(
|
||||
absl::StrCat("Usage: ", argv[0], " [options] file.."));
|
||||
absl::StrCat("Usage: ", argv[0], " [options] file.."));
|
||||
gflags::ParseCommandLineFlags(&argc, &argv, true);
|
||||
|
||||
if (argc > 1) {
|
||||
|
|
@ -253,7 +247,7 @@ int main(int argc, char **argv)
|
|||
printf("#of bits: %d\n", num_bits);
|
||||
printf("#of tags: %d\n", num_tags);
|
||||
|
||||
FILE *f = stdout;
|
||||
FILE* f = stdout;
|
||||
|
||||
if (!FLAGS_o.empty()) {
|
||||
f = fopen(FLAGS_o.c_str(), "w");
|
||||
|
|
@ -269,14 +263,12 @@ int main(int argc, char **argv)
|
|||
|
||||
std::vector<std::string> out_lines;
|
||||
|
||||
for (int tag_idx = 0; tag_idx < num_tags; tag_idx++)
|
||||
{
|
||||
for (int tag_idx = 0; tag_idx < num_tags; tag_idx++) {
|
||||
bool_vec mask(num_bits, true);
|
||||
int count1 = 0, count0 = 0;
|
||||
|
||||
for (auto &segdat : segdata)
|
||||
{
|
||||
auto &sd = segdat.second;
|
||||
for (auto& segdat : segdata) {
|
||||
auto& sd = segdat.second;
|
||||
bool tag1 = segdata_tags1(sd).get(tag_idx);
|
||||
bool tag0 = segdata_tags0(sd).get(tag_idx);
|
||||
|
||||
|
|
@ -331,25 +323,28 @@ int main(int argc, char **argv)
|
|||
int num_candidates = mask.count();
|
||||
|
||||
if (count0) {
|
||||
min_candidates = std::min(min_candidates, num_candidates);
|
||||
max_candidates = std::max(max_candidates, num_candidates);
|
||||
min_candidates =
|
||||
std::min(min_candidates, num_candidates);
|
||||
max_candidates =
|
||||
std::max(max_candidates, num_candidates);
|
||||
avg_candidates += num_candidates;
|
||||
cnt_candidates += 1;
|
||||
}
|
||||
|
||||
if (FLAGS_c < 0 ||
|
||||
(0 < num_candidates &&
|
||||
num_candidates <= FLAGS_c)) {
|
||||
(0 < num_candidates && num_candidates <= FLAGS_c)) {
|
||||
std::vector<std::string> out_tags;
|
||||
for (int bit_idx = 0; bit_idx < num_bits; bit_idx++)
|
||||
if (mask.get(bit_idx))
|
||||
out_tags.push_back(bit_ids_r.at(bit_idx));
|
||||
out_tags.push_back(
|
||||
bit_ids_r.at(bit_idx));
|
||||
std::sort(out_tags.begin(), out_tags.end());
|
||||
for (auto &tag : out_tags)
|
||||
for (auto& tag : out_tags)
|
||||
out_line += " " + tag;
|
||||
} else {
|
||||
char buffer[64];
|
||||
snprintf(buffer, 64, " <%d candidates>", num_candidates);
|
||||
snprintf(buffer, 64, " <%d candidates>",
|
||||
num_candidates);
|
||||
out_line += buffer;
|
||||
}
|
||||
|
||||
|
|
@ -358,7 +353,7 @@ int main(int argc, char **argv)
|
|||
|
||||
std::sort(out_lines.begin(), out_lines.end());
|
||||
|
||||
for (auto &line : out_lines)
|
||||
for (auto& line : out_lines)
|
||||
fprintf(f, "%s\n", line.c_str());
|
||||
|
||||
if (cnt_candidates)
|
||||
|
|
@ -383,4 +378,3 @@ int main(int argc, char **argv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue