From 246ddc9c11926a3e618b94d26e8256fc131c8860 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 6 Dec 2024 11:36:39 +0100 Subject: [PATCH] Pack/unpack PLL related configuration --- libgm/include/ChipConfig.hpp | 1 + libgm/include/Die.hpp | 6 ++++++ libgm/include/TileBitDatabase.hpp | 6 ++++++ libgm/src/Bitstream.cpp | 36 ++++++++++++++++++++++++++++--- libgm/src/ChipConfig.cpp | 20 +++++++++++++++++ libgm/src/Die.cpp | 27 +++++++++++++++++++++++ libgm/src/TileBitDatabase.cpp | 19 ++++++++++++++++ 7 files changed, 112 insertions(+), 3 deletions(-) diff --git a/libgm/include/ChipConfig.hpp b/libgm/include/ChipConfig.hpp index 8284bfc..8ababc0 100644 --- a/libgm/include/ChipConfig.hpp +++ b/libgm/include/ChipConfig.hpp @@ -53,6 +53,7 @@ class ChipConfig string chip_package; std::map tiles; std::map brams; + std::map plls; // Block RAM initialisation std::map> bram_data; diff --git a/libgm/include/Die.hpp b/libgm/include/Die.hpp index b20f55a..c751638 100644 --- a/libgm/include/Die.hpp +++ b/libgm/include/Die.hpp @@ -38,6 +38,7 @@ class Die static constexpr int LATCH_BLOCK_SIZE = 112; static constexpr int RAM_BLOCK_SIZE = 27; static constexpr int MEMORY_SIZE = 5120; + static constexpr int PLL_CONFIG_SIZE = 12 * 8 + 4 + 8; public: explicit Die(); @@ -51,19 +52,24 @@ class Die bool is_latch_empty(int x, int y) const; bool is_ram_empty(int x, int y) const; bool is_ram_data_empty(int x, int y) const; + bool is_pll_cfg_empty(int index) const; void write_latch(int x, int y, const std::vector &data); void write_ram(int x, int y, const std::vector &data); void write_ram_data(int x, int y, const std::vector &data, uint16_t addr); + void write_pll_select(uint8_t select, const std::vector &data); + void write_pll(const std::vector &data) { pll_cfg = data; } const std::vector get_latch_config(int x, int y) const { return latch.at(std::make_pair(x, y)); } const std::vector get_ram_config(int x, int y) const { return ram.at(std::make_pair(x, y)); } const std::vector get_ram_data(int x, int y) const { return ram_data.at(std::make_pair(x, y)); } + const std::vector get_pll_config() const { return pll_cfg; } private: std::map, std::vector> latch; // Config latches std::map, std::vector> ram; // Config RAM std::map, std::vector> ram_data; // RAM data content FRAM + std::vector pll_cfg; // Config for all PLLs, CLKIN and GLBOUT }; } // namespace GateMate diff --git a/libgm/include/TileBitDatabase.hpp b/libgm/include/TileBitDatabase.hpp index 13f0850..648273b 100644 --- a/libgm/include/TileBitDatabase.hpp +++ b/libgm/include/TileBitDatabase.hpp @@ -86,6 +86,12 @@ class RamBitDatabase : public BaseBitDatabase RamBitDatabase(); }; +class PLLBitDatabase : public BaseBitDatabase +{ + public: + PLLBitDatabase(); +}; + class DatabaseConflictError : public runtime_error { public: diff --git a/libgm/src/Bitstream.cpp b/libgm/src/Bitstream.cpp index b2e7602..0fb660b 100644 --- a/libgm/src/Bitstream.cpp +++ b/libgm/src/Bitstream.cpp @@ -315,7 +315,7 @@ class BitstreamReadWriter insert_crc16(); } - void write_cmd_pll() + void write_cmd_pll_empty() { write_header(CMD_PLL, 12); for (int i = 0; i < 12; i++) @@ -323,6 +323,17 @@ class BitstreamReadWriter insert_crc16(); write_nops(6); } + + void write_cmd_pll(int index, std::vector data) + { + write_header(CMD_PLL, 24); + for (int i = 0; i < 12; i++) + write_byte(data[i + index * 12]); + for (int i = 12 * 8; i < 12 * 8 + 12; i++) + write_byte(data[i]); + insert_crc16(); + write_nops(6); + } }; void check_crc(BitstreamReadWriter &rd) @@ -371,6 +382,7 @@ Chip Bitstream::deserialise_chip() BitstreamReadWriter rd(data); bool is_block_ram = false; uint8_t x_pos = 0, y_pos = 0; + uint8_t pll_select = 0x0f; uint16_t aclcu = 0; while (!rd.is_end()) { rd.crc16.reset_crc16(); @@ -423,7 +435,7 @@ Chip Bitstream::deserialise_chip() // Check header CRC check_crc(rd); // Read data block - rd.get_byte(); + pll_select = rd.get_byte(); // Check data CRC check_crc(rd); break; @@ -438,6 +450,7 @@ Chip Bitstream::deserialise_chip() // Read data block rd.get_vector(block, length); + die.write_pll_select(pll_select, block); // Check data CRC check_crc(rd); @@ -576,8 +589,25 @@ Bitstream Bitstream::serialise_chip(const Chip &chip) { BitstreamReadWriter wr; wr.write_cmd_path(0x10); - wr.write_cmd_pll(); auto &die = chip.get_die(0); + std::vector pll_data = die.get_pll_config(); + bool pll_written = false; + for (int i = 0; i < 4; i++) { + bool cfg_a = !die.is_pll_cfg_empty(i * 2 + 0); + bool cfg_b = !die.is_pll_cfg_empty(i * 2 + 1); + if (cfg_a || cfg_b) { + wr.write_cmd_spll(1 << i); + wr.write_cmd_pll(i * 2, pll_data); + if (cfg_b) { + wr.write_cmd_spll(1 << i | 1 << (i + 4)); + wr.write_cmd_pll(i * 2, pll_data); + } + pll_written = true; + } + } + if (!pll_written) + wr.write_cmd_pll_empty(); + for (int iteration = 0; iteration < 2; iteration++) { for (int y = 0; y < Die::MAX_ROWS; y++) { for (int x = 0; x < Die::MAX_COLS; x++) { diff --git a/libgm/src/ChipConfig.cpp b/libgm/src/ChipConfig.cpp index c0caddc..a02d3db 100644 --- a/libgm/src/ChipConfig.cpp +++ b/libgm/src/ChipConfig.cpp @@ -31,6 +31,13 @@ std::string ChipConfig::to_string() const { std::stringstream ss; ss << ".device " << chip_name << endl << endl; + for (const auto &pll : plls) { + if (!pll.second.empty()) { + ss << ".pll " << pll.first << " " << endl; + ss << pll.second; + ss << endl; + } + } for (const auto &tile : tiles) { if (!tile.second.empty()) { ss << ".tile " << tile.first.die << " " << tile.first.x << " " << tile.first.y << endl; @@ -72,6 +79,12 @@ ChipConfig ChipConfig::from_string(const std::string &config) ss >> verb; if (verb == ".device") { ss >> cc.chip_name; + } else if (verb == ".pll") { + int die; + ss >> die; + TileConfig tc; + ss >> tc; + cc.plls.emplace(die, tc); } else if (verb == ".tile") { CfgLoc loc; ss >> loc.die; @@ -138,6 +151,11 @@ Chip ChipConfig::to_chip() const die.write_ram_data(x, y, bram_data.at(loc), 0); } } + PLLBitDatabase plldb; + if (plls.count(d)) { + const TileConfig &cfg = plls.at(d); + die.write_pll(plldb.config_to_data(cfg)); + } } return chip; @@ -173,6 +191,8 @@ ChipConfig ChipConfig::from_chip(const Chip &chip) } } } + PLLBitDatabase pll_db; + cc.plls.emplace(d, pll_db.data_to_config(die.get_pll_config())); } return cc; } diff --git a/libgm/src/Die.cpp b/libgm/src/Die.cpp index 5f0b165..2761072 100644 --- a/libgm/src/Die.cpp +++ b/libgm/src/Die.cpp @@ -37,6 +37,7 @@ Die::Die() ram_data[std::make_pair(x, y)] = std::vector(); } } + pll_cfg = std::vector(PLL_CONFIG_SIZE, 0x00); } bool Die::is_latch_empty(int x, int y) const { return latch.at(std::make_pair(x, y)).empty(); } @@ -45,6 +46,15 @@ bool Die::is_ram_empty(int x, int y) const { return ram.at(std::make_pair(x, y)) bool Die::is_ram_data_empty(int x, int y) const { return ram_data.at(std::make_pair(x, y)).empty(); } +bool Die::is_pll_cfg_empty(int index) const +{ + int pos = index * 12; + for (int i = 0; i < 12; i++) + if (pll_cfg[i + pos] != 0x00) + return false; + return true; +} + void Die::write_latch(int x, int y, const std::vector &data) { int pos = 0; @@ -72,4 +82,21 @@ void Die::write_ram_data(int x, int y, const std::vector &data, uint16_ block[pos++] = d; } +void Die::write_pll_select(uint8_t select, const std::vector &data) +{ + for (int i = 0; i < 4; i++) { + if (select & (1 << i)) { + int pos = i * 2 * 12; + if (select & (1 << (i + 4))) { + pos += 12; + } + for (size_t j = 0; j < 12; j++) + pll_cfg[pos++] = data[j]; + } + } + int pos = 8 * 12; // start after PLL data; + for (size_t j = 12; j < data.size(); j++) + pll_cfg[pos++] = data[j]; +} + } // namespace GateMate diff --git a/libgm/src/TileBitDatabase.cpp b/libgm/src/TileBitDatabase.cpp index d5f8e22..5bf8678 100644 --- a/libgm/src/TileBitDatabase.cpp +++ b/libgm/src/TileBitDatabase.cpp @@ -249,6 +249,25 @@ RamBitDatabase::RamBitDatabase() : BaseBitDatabase(Die::RAM_BLOCK_SIZE * 8) add_unknowns(); } +PLLBitDatabase::PLLBitDatabase() : BaseBitDatabase(Die::PLL_CONFIG_SIZE * 8) +{ + int pos = 0; + for (int i = 0; i < 4; i++) { + add_word_settings(stringf("PLL%d.CFG_A", i), pos, 96); + pos += 96; + add_word_settings(stringf("PLL%d.CFG_B", i), pos, 96); + pos += 96; + } + add_word_settings("CLKIN.PLL0", pos + 0, 8); + add_word_settings("CLKIN.PLL1", pos + 8, 8); + add_word_settings("CLKIN.PLL2", pos + 16, 8); + add_word_settings("CLKIN.PLL3", pos + 24, 8); + add_word_settings("GLBOUT.PLL0", pos + 32, 16); + add_word_settings("GLBOUT.PLL1", pos + 48, 16); + add_word_settings("GLBOUT.PLL2", pos + 64, 16); + add_word_settings("GLBOUT.PLL3", pos + 80, 16); +} + vector WordSettingBits::get_value(const vector &tile) const { std::vector val;