Pack/unpack PLL related configuration

This commit is contained in:
Miodrag Milanovic 2024-12-06 11:36:39 +01:00
parent 97cb94755f
commit 246ddc9c11
7 changed files with 112 additions and 3 deletions

View File

@ -53,6 +53,7 @@ class ChipConfig
string chip_package;
std::map<CfgLoc, TileConfig> tiles;
std::map<CfgLoc, TileConfig> brams;
std::map<int, TileConfig> plls;
// Block RAM initialisation
std::map<CfgLoc, std::vector<uint8_t>> bram_data;

View File

@ -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<uint8_t> &data);
void write_ram(int x, int y, const std::vector<uint8_t> &data);
void write_ram_data(int x, int y, const std::vector<uint8_t> &data, uint16_t addr);
void write_pll_select(uint8_t select, const std::vector<uint8_t> &data);
void write_pll(const std::vector<uint8_t> &data) { pll_cfg = data; }
const std::vector<uint8_t> get_latch_config(int x, int y) const { return latch.at(std::make_pair(x, y)); }
const std::vector<uint8_t> get_ram_config(int x, int y) const { return ram.at(std::make_pair(x, y)); }
const std::vector<uint8_t> get_ram_data(int x, int y) const { return ram_data.at(std::make_pair(x, y)); }
const std::vector<uint8_t> get_pll_config() const { return pll_cfg; }
private:
std::map<std::pair<int, int>, std::vector<uint8_t>> latch; // Config latches
std::map<std::pair<int, int>, std::vector<uint8_t>> ram; // Config RAM
std::map<std::pair<int, int>, std::vector<uint8_t>> ram_data; // RAM data content FRAM
std::vector<uint8_t> pll_cfg; // Config for all PLLs, CLKIN and GLBOUT
};
} // namespace GateMate

View File

@ -86,6 +86,12 @@ class RamBitDatabase : public BaseBitDatabase
RamBitDatabase();
};
class PLLBitDatabase : public BaseBitDatabase
{
public:
PLLBitDatabase();
};
class DatabaseConflictError : public runtime_error
{
public:

View File

@ -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<uint8_t> 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<uint8_t> 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++) {

View File

@ -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;
}

View File

@ -37,6 +37,7 @@ Die::Die()
ram_data[std::make_pair(x, y)] = std::vector<u_int8_t>();
}
}
pll_cfg = std::vector<u_int8_t>(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<uint8_t> &data)
{
int pos = 0;
@ -72,4 +82,21 @@ void Die::write_ram_data(int x, int y, const std::vector<uint8_t> &data, uint16_
block[pos++] = d;
}
void Die::write_pll_select(uint8_t select, const std::vector<uint8_t> &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

View File

@ -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<bool> WordSettingBits::get_value(const vector<bool> &tile) const
{
std::vector<bool> val;