Support FF initialization

This commit is contained in:
Miodrag Milanovic 2024-12-07 14:58:36 +01:00
parent 0325f0091a
commit 5ce6ab64f4
5 changed files with 94 additions and 8 deletions

View File

@ -35,7 +35,7 @@ class Die
static constexpr int MAX_RAM = 32;
static constexpr int MAX_RAM_ROWS = 8;
static constexpr int MAX_RAM_COLS = 4;
static constexpr int LATCH_BLOCK_SIZE = 112;
static constexpr int LATCH_BLOCK_SIZE = 112 + 1; // Added one more byte for FF_INIT
static constexpr int RAM_BLOCK_SIZE = 27;
static constexpr int MEMORY_SIZE = 5120;
static constexpr int MAX_PLL = 4;
@ -43,6 +43,8 @@ class Die
static constexpr int CLKIN_CFG_SIZE = 4;
static constexpr int GLBOUT_CFG_SIZE = 8;
static constexpr int PLL_CONFIG_SIZE = PLL_CFG_SIZE * MAX_PLL * 2 + CLKIN_CFG_SIZE + GLBOUT_CFG_SIZE;
static constexpr int FF_INIT_RESET = 2;
static constexpr int FF_INIT_SET = 3;
public:
explicit Die();
@ -54,6 +56,7 @@ class Die
int get_max_ram_col() const { return MAX_RAM_COLS; }
bool is_latch_empty(int x, int y) const;
bool is_cpe_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;
@ -65,6 +68,7 @@ class Die
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; }
void write_ff_init(int x, int y, uint8_t 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)); }

View File

@ -69,6 +69,7 @@ class TileBitDatabase : public BaseBitDatabase
void add_sb_drive(int index, int start);
void add_cpe(int index, int start);
void add_ff_init(int index, int start);
void add_inmux(int index, int plane, int start);
void add_gpio(int start);

View File

@ -385,6 +385,7 @@ Chip Bitstream::deserialise_chip()
uint8_t x_pos = 0, y_pos = 0;
uint8_t pll_select = 0x0f;
uint16_t aclcu = 0;
std::map<std::pair<int, int>, int> tile_iteration;
while (!rd.is_end()) {
rd.crc16.reset_crc16();
uint8_t cmd = rd.get_command_opcode();
@ -412,8 +413,34 @@ Chip Bitstream::deserialise_chip()
if (is_block_ram)
die.write_ram(x_pos, y_pos, block);
else
else {
int iteration = -1;
if (tile_iteration.count(std::make_pair(x_pos, y_pos)))
iteration = tile_iteration[std::make_pair(x_pos, y_pos)];
tile_iteration[std::make_pair(x_pos, y_pos)] = ++iteration;
// Detection of FF initialization is possible on
// last iteration
if (iteration == 2) {
std::vector<uint8_t> data = die.get_latch_config(x_pos, y_pos);
// Make sure we have CPE data
// even if uninitialized
block.resize(40, 0x00);
uint8_t val = 0x00;
for (int i = 0; i < 4; i++) {
uint8_t v = block[i * 10 + 8] ^ data[i * 10 + 8];
if (v == 0x30)
val |= Die::FF_INIT_RESET << (i * 2);
else if (v == 0xc0)
val |= Die::FF_INIT_SET << (i * 2);
else
BITSTREAM_FATAL(stringf("Unknown CPE state %d on pos %d,%d\n", v, x_pos, y_pos),
rd.get_offset());
}
die.write_ff_init(x_pos, y_pos, val);
}
die.write_latch(x_pos, y_pos, block);
}
break;
case CMD_PATH:
BITSTREAM_DEBUG("CMD_PATH");
@ -614,20 +641,52 @@ Bitstream Bitstream::serialise_chip(const Chip &chip)
if (!pll_written)
wr.write_cmd_pll_empty();
for (int iteration = 0; iteration < 2; iteration++) {
for (int iteration = 0; iteration < 3; iteration++) {
for (int y = 0; y < Die::MAX_ROWS; y++) {
for (int x = 0; x < Die::MAX_COLS; x++) {
// Empty configuration is skipped
if (die.is_latch_empty(x, y))
continue;
// Only tiles with CPE can have multiple iterations
if (iteration != 0 && is_edge_location(x, y))
continue;
wr.write_cmd_lxlys(x, y);
std::vector<uint8_t> data = die.get_latch_config(x, y);
if (iteration == 0 && !is_edge_location(x, y)) {
std::fill(data.begin(), data.begin() + 40, 0);
// If CPE empty skip other iterations
if (iteration != 0 && die.is_cpe_empty(x, y))
continue;
std::vector<uint8_t> data = std::vector<uint8_t>(die.get_latch_config(x, y));
uint8_t ff_init = data.back();
data.pop_back();
if (!is_edge_location(x, y)) {
if (iteration == 0) {
// First iteration does not setup CPE at all
std::fill(data.begin(), data.begin() + 40, 0);
}
// 2nd iteration with no changes if no FF initialization
if (iteration == 1 && ff_init) {
// Only CPE data is exported
data.resize(40);
// Set initial FFs states
for (int i = 0; i < 4; i++) {
uint8_t ff = (ff_init >> (i * 2)) & 0x03;
if (ff == Die::FF_INIT_RESET)
data[i * 10 + 8] &= 0x30 ^ 0xff;
else if (ff == Die::FF_INIT_SET)
data[i * 10 + 8] &= 0xc0 ^ 0xff;
}
}
// 3rd iteration only if there was FF initialization
if (iteration == 2) {
if (!ff_init)
continue;
// Only CPE data is exported
data.resize(40);
}
}
// minimize output
auto rit = std::find_if(data.rbegin(), data.rend(), [](uint8_t val) { return val != 0; });
data.erase(rit.base(), end(data));
wr.write_cmd_lxlys(x, y);
wr.write_header(CMD_DLCU, data.size());
wr.write_bytes(data);
wr.insert_crc16();

View File

@ -33,7 +33,7 @@ Die::Die()
for (int y = 0; y < MAX_RAM_ROWS; y++) {
for (int x = 0; x < MAX_RAM_COLS; x++) {
ram[std::make_pair(x, y)] = std::vector<u_int8_t>();
ram[std::make_pair(x, y)].reserve(LATCH_BLOCK_SIZE);
ram[std::make_pair(x, y)].reserve(RAM_BLOCK_SIZE);
ram_data[std::make_pair(x, y)] = std::vector<u_int8_t>();
}
}
@ -42,6 +42,15 @@ Die::Die()
bool Die::is_latch_empty(int x, int y) const { return latch.at(std::make_pair(x, y)).empty(); }
bool Die::is_cpe_empty(int x, int y) const
{
auto &block = latch.at(std::make_pair(x, y));
for (int i = 0; i < 40; i++)
if (block[i] != 0x00)
return false;
return true;
}
bool Die::is_ram_empty(int x, int y) const { return ram.at(std::make_pair(x, y)).empty(); }
bool Die::is_ram_data_empty(int x, int y) const { return ram_data.at(std::make_pair(x, y)).empty(); }
@ -82,6 +91,13 @@ void Die::write_latch(int x, int y, const std::vector<uint8_t> &data)
block[pos++] = d;
}
void Die::write_ff_init(int x, int y, uint8_t data)
{
auto &block = latch.at(std::make_pair(x, y));
block.resize(LATCH_BLOCK_SIZE, 0x00);
block[LATCH_BLOCK_SIZE - 1] = data;
}
void Die::write_ram(int x, int y, const std::vector<uint8_t> &data)
{
int pos = 0;

View File

@ -124,6 +124,11 @@ void TileBitDatabase::add_sb_drive(int index, int start)
void TileBitDatabase::add_cpe(int index, int start) { add_word_settings(stringf("CPE_%d", index), start, 80); }
void TileBitDatabase::add_ff_init(int index, int start)
{
add_word_settings(stringf("CPE_%d.FF_INIT", index), start, 2);
}
void TileBitDatabase::add_inmux(int index, int plane, int start)
{
add_word_settings(stringf("INMUX_%d_%02d", index, plane), start, 4);
@ -172,6 +177,7 @@ TileBitDatabase::TileBitDatabase(const int x, const int y) : BaseBitDatabase(Die
is_core = true;
for (int i = 0; i < 4; i++) {
add_cpe(i + 1, 10 * i * 8);
add_ff_init(i + 1, (Die::LATCH_BLOCK_SIZE - 1) * 8 + i * 2);
}
int pos = 40;
for (int i = 0; i < 4; i++) {