Merge pull request #12 from pu-cc/bootaddr

Secondary bitstream and scrubber features
This commit is contained in:
Miodrag Milanović 2025-10-21 08:01:01 +02:00 committed by GitHub
commit 1ab0612d22
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 287 additions and 25 deletions

View File

@ -91,7 +91,7 @@ each bit of one byte payload is used to set one of 4 columns.
CMD_CFGRST
-----------
Resets all configuration latches to value of a byte from payload.
Resets all configuration latches to value of a byte from payload, except active SPI controller and configuration PLL.
CMD_ACLCU
----------
@ -304,29 +304,161 @@ CMD_CHG_STATUS
- 6..7
- Unused
* - 4
-
- PLL0 Control Register
- 0
- PLL0 PLL_RST_N
* -
- 1
- PLL0 PLL_EN
* -
- 2
- PLL0 PLL_AUTN
* -
- 3
- PLL0 SET_SEL
* -
- 4
- PLL0 USR_SET
* -
- 5
- PLL0 USR_CLK_REF
* -
- 6
- PLL0 CLK_OUT_EN
* -
- 7
- PLL0 LOCK_REQ
* - 5
-
- PLL0 Startup Register
- 0..2
- PLL0 AUTN_CT_I[2:0], should be 001
* -
- 3
- PLL0 CLK180_DOUB
* -
- 4
- PLL0 CLK270_DOUB
* -
- 5..6
- Unused
* -
- 7
- PLL0 USR_CLK_OUT
* - 6
-
- PLL1 Control Register
- 0
- PLL1 PLL_RST_N
* -
- 1
- PLL1 PLL_EN
* -
- 2
- Unused
* -
- 3
- PLL1 SET_SEL
* -
- 4
- PLL1 USR_SET
* -
- 5
- PLL1 USR_CLK_REF
* -
- 6
- PLL1 CLK_OUT_EN
* -
- 7
- PLL1 LOCK_REQ
* - 7
-
- PLL1 Startup Register
- 0..2
- Unused
* -
- 3
- PLL1 CLK180_DOUB
* -
- 4
- PLL1 CLK270_DOUB
* -
- 5..6
- Unused
* -
- 7
- PLL1 USR_CLK_OUT
* - 8
-
- PLL2 Control Register
* - 9
-
- PLL2 Startup Register
- 0
- PLL2 PLL_RST_N
* -
- 1
- PLL2 PLL_EN
* -
- 2
- Unused
* -
- 3
- PLL2 SET_SEL
* -
- 4
- PLL2 USR_SET
* -
- 5
- PLL2 USR_CLK_REF
* -
- 6
- PLL2 CLK_OUT_EN
* -
- 9
- PLL2 LOCK_REQ
* - 7
- 0..2
- Unused
* -
- 3
- PLL2 CLK180_DOUB
* -
- 4
- PLL2 CLK270_DOUB
* -
- 5..6
- Unused
* -
- 7
- PLL2 USR_CLK_OUT
* - 10
-
- PLL3 Control Register
- 0
- PLL3 PLL_RST_N
* -
- 1
- PLL3 PLL_EN
* -
- 2
- Unused
* -
- 3
- PLL3 SET_SEL
* -
- 4
- PLL3 USR_SET
* -
- 5
- PLL3 USR_CLK_REF
* -
- 6
- PLL3 CLK_OUT_EN
* -
- 9
- PLL3 LOCK_REQ
* - 11
-
- PLL3 Startup Register
- 0..2
- Unused
* -
- 3
- PLL3 CLK180_DOUB
* -
- 4
- PLL3 CLK270_DOUB
* -
- 5..6
- Unused
* -
- 7
- PLL3 USR_CLK_OUT
.. warning::
This command have data after payload, and it consists of 9 bytes ``0x00 0x00 0x00 0x00 0x33 0x00 0x00 0x00 0x00`` and
@ -358,6 +490,26 @@ CMD_SERDES
CMD_JUMP
--------
Jump to address in SPI flash.
.. list-table::
:widths: 10 40
:header-rows: 1
* - Byte
- Description
* - 0
- addr[7:0]
* - 1
- addr[15:8]
* - 2
- addr[23:16]
* - 3
- addr[31:24]
.. warning::
This command requires data after payload, and it consists of 2 NOP bytes ``0x00 0x00``.
CMD_CFGMODE
------------

View File

@ -30,7 +30,7 @@ namespace GateMate {
static constexpr const uint8_t CMD_PLL = 0xc1;
static constexpr const uint8_t CMD_CFGMODE = 0xc2;
static constexpr const uint8_t CMD_CFGRST = 0xc3; //
static constexpr const uint8_t CMD_CFGRST = 0xc3;
static constexpr const uint8_t CMD_FLASH = 0xc5;
static constexpr const uint8_t CMD_DLXP = 0xc6; //
static constexpr const uint8_t CMD_DLYP = 0xc7; //
@ -43,7 +43,7 @@ static constexpr const uint8_t CMD_FRAM = 0xd2;
static constexpr const uint8_t CMD_SERDES = 0xd7; //
static constexpr const uint8_t CMD_D2D = 0xd8; //
static constexpr const uint8_t CMD_PATH = 0xd9;
static constexpr const uint8_t CMD_JUMP = 0xda; //
static constexpr const uint8_t CMD_JUMP = 0xda;
static constexpr const uint8_t CMD_CHG_STATUS = 0xdb;
static constexpr const uint8_t CMD_WAIT_PLL = 0xdc; //
static constexpr const uint8_t CMD_SPLL = 0xdd;
@ -58,6 +58,22 @@ static constexpr const uint8_t CFG_CPE_RESET = 0x10;
static constexpr const uint8_t CFG_FILL_RAM = 0x20;
static constexpr const uint8_t CFG_SERDES = 0x40;
// PLL register A
static constexpr const uint8_t CFG_PLL_RST_N = 0x01;
static constexpr const uint8_t CFG_PLL_EN = 0x02;
static constexpr const uint8_t CFG_PLL_AUTN = 0x04; // only available for PLL0
static constexpr const uint8_t CFG_SET_SEL = 0x08;
static constexpr const uint8_t CFG_USR_SET = 0x10;
static constexpr const uint8_t CFG_USR_CLK_REF = 0x20;
static constexpr const uint8_t CFG_CLK_OUT_EN = 0x40;
static constexpr const uint8_t CFG_LOCK_REQ = 0x80;
// PLL register B
static constexpr const uint8_t CFG_AUTN_CT_I = 0x01; // only available for PLL0
static constexpr const uint8_t CFG_CLK180_DOUB = 0x08;
static constexpr const uint8_t CFG_CLK270_DOUB = 0x10;
static constexpr const uint8_t CFG_USR_CLK_OUT = 0x80;
static const std::vector<std::pair<std::string, uint8_t>> crc_modes = {
{"check", 0x00}, // Check CRC
{"ignore", 0x01}, // Ignore added CRC
@ -266,6 +282,17 @@ class BitstreamReadWriter
write_nops(4);
}
void write_cmd_jump(uint32_t addr)
{
write_header(CMD_JUMP, 4);
write_byte(uint8_t(addr & 0xFF));
write_byte(uint8_t((addr >> 8UL) & 0xFF));
write_byte(uint8_t((addr >> 16UL) & 0xFF));
write_byte(uint8_t((addr >> 24UL) & 0xFF));
insert_crc16();
write_nops(2);
}
void write_cmd_cfgmode(uint8_t crcmode, std::vector<uint8_t> spimode)
{
write_header(CMD_CFGMODE, spimode.size() > 0 ? 6 : 2);
@ -365,11 +392,11 @@ class BitstreamReadWriter
write_nops(4);
}
void write_cmd_chg_status(uint8_t cfg, std::vector<uint8_t> data)
void write_cmd_chg_status(uint8_t cfg, uint8_t next_mode, std::vector<uint8_t> data)
{
write_header(CMD_CHG_STATUS, 12);
write_byte(cfg);
write_byte(0x00);
write_byte(next_mode);
for (int i = 2; i < 12; i++)
write_byte(data[Die::STATUS_CFG_START + i]);
insert_crc16();
@ -442,6 +469,8 @@ int Bitstream::determine_size(int *max_die_x, int *max_die_y)
case CMD_ACLCU:
case CMD_RXRYS:
case CMD_D2D:
case CMD_CFGRST:
case CMD_JUMP:
// Check header CRC
check_crc(rd);
// Read data block
@ -460,6 +489,8 @@ int Bitstream::determine_size(int *max_die_x, int *max_die_y)
rd.skip_bytes(6);
if (cmd == CMD_CHG_STATUS)
rd.skip_bytes(9);
if (cmd == CMD_JUMP)
rd.skip_bytes(2);
break;
case CMD_PATH:
// Check header CRC
@ -783,6 +814,36 @@ Chip Bitstream::deserialise_chip()
check_crc(rd);
break;
case CMD_CFGRST:
BITSTREAM_DEBUG("CMD_CFGRST");
if (length > 1)
BITSTREAM_FATAL("CFGRST data longer than expected", rd.get_offset());
// Check header CRC
check_crc(rd);
// Read data block
rd.get_vector(block, length);
// Check data CRC
check_crc(rd);
break;
case CMD_JUMP:
BITSTREAM_DEBUG("CMD_JUMP");
if (length > 4)
BITSTREAM_FATAL("JUMP addr longer than expected", rd.get_offset());
// Check header CRC
check_crc(rd);
// Read data block
rd.get_vector(block, length);
// Check data CRC
check_crc(rd);
// Skip bytes
rd.skip_bytes(2);
break;
default:
BITSTREAM_FATAL("Unhandled command 0x" << std::hex << std::setw(2) << std::setfill('0') << int(cmd),
rd.get_offset());
@ -836,6 +897,10 @@ Bitstream Bitstream::serialise_chip(const Chip &chip, const std::map<std::string
}
wr.write_cmd_path(0x10);
if (options.count("reset") && !options.count("background")) {
wr.write_cmd_cfgrst(0x00);
}
bool change_crc = false;
auto crcmode = crc_modes.begin();
if (options.count("crcmode")) {
@ -936,6 +1001,7 @@ Bitstream Bitstream::serialise_chip(const Chip &chip, const std::map<std::string
}
// Write latch configuration
int scrubaddr = 0;
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++) {
@ -948,6 +1014,8 @@ Bitstream Bitstream::serialise_chip(const Chip &chip, const std::map<std::string
// If CPE empty skip other iterations
if (iteration != 0 && die.is_cpe_empty(x, y))
continue;
if (iteration == 1 && scrubaddr == 0)
scrubaddr = wr.data.size();
std::vector<uint8_t> data = std::vector<uint8_t>(die.get_latch_config(x, y));
uint8_t ff_init = data.back();
data.pop_back();
@ -993,15 +1061,31 @@ Bitstream Bitstream::serialise_chip(const Chip &chip, const std::map<std::string
}
uint8_t cfg_stat = CFG_CPE_RESET;
uint8_t cfg_mode = 0x1F; // unused mode enforces controller to stop
// Only for die 0
if (d == 0) {
// Write change status
if (die.is_using_cfg_gpios())
wr.write_cmd_chg_status(CFG_DONE);
cfg_stat |= CFG_STOP | CFG_DONE;
cfg_stat |= CFG_DONE;
if (!options.count("background")) {
cfg_stat |= CFG_STOP;
}
if (options.count("bootaddr")) {
cfg_stat |= CFG_RECONFIG;
}
if (options.count("reconfig")) {
cfg_stat |= CFG_RECONFIG | CFG_CPE_CFG;
cfg_stat |= CFG_CPE_CFG;
}
if (options.count("bootaddr") || options.count("background")) {
cfg_mode = 0x10; // active spi
// Enable autonomous clock if PLL not enabled
if (die.is_pll_cfg_empty(0)) {
die_config[Die::STATUS_CFG_START + 2 + 2] |= CFG_PLL_AUTN;
die_config[Die::STATUS_CFG_START + 2 + 3] |= CFG_AUTN_CT_I;
}
}
}
if (!die.is_serdes_cfg_empty()) {
@ -1011,7 +1095,18 @@ Bitstream Bitstream::serialise_chip(const Chip &chip, const std::map<std::string
wr.insert_crc16();
}
wr.write_cmd_chg_status(cfg_stat, die_config);
wr.write_cmd_chg_status(cfg_stat, cfg_mode, die_config);
if (d == 0) {
if (options.count("bootaddr") && !options.count("background")) {
uint32_t bootaddr = std::strtoul(options.at("bootaddr").c_str(), nullptr, 0);
wr.write_cmd_cfgrst(0x00);
wr.write_cmd_jump(bootaddr);
}
if (options.count("background") && !options.count("bootaddr")) {
wr.write_cmd_jump(scrubaddr);
}
}
}
return Bitstream(wr.get());
}

View File

@ -37,9 +37,12 @@ int main(int argc, char *argv[])
po::options_description options("Allowed options");
options.add_options()("help,h", "show help");
options.add_options()("verbose,v", "verbose output");
options.add_options()("reset", "reset all configuration latches with CMD_CFGRST");
options.add_options()("crcmode", po::value<std::string>(), "CRC error behaviour (check, ignore, unused)");
options.add_options()("spimode", po::value<std::string>(), "SPI Mode to use (single, dual, quad)");
options.add_options()("reconfig", "enable reconfiguration in bitstream");
options.add_options()("background", "enable background reconfiguration in bitstream");
options.add_options()("bootaddr", po::value<int>(), "boot address for secondary bitstream");
po::positional_options_description pos;
options.add_options()("input", po::value<std::string>()->required(), "input textual configuration");
pos.add("input", 1);
@ -82,6 +85,10 @@ int main(int argc, char *argv[])
std::map<std::string, std::string> bitopts;
if (vm.count("reset")) {
bitopts["reset"] = "yes";
}
if (vm.count("crcmode")) {
bitopts["crcmode"] = vm["crcmode"].as<std::string>();
}
@ -94,6 +101,14 @@ int main(int argc, char *argv[])
bitopts["reconfig"] = "yes";
}
if (vm.count("background")) {
bitopts["background"] = "yes";
}
if (vm.count("bootaddr")) {
bitopts["bootaddr"] = std::to_string(vm["bootaddr"].as<int>());
}
std::string textcfg((std::istreambuf_iterator<char>(config_file)), std::istreambuf_iterator<char>());
ChipConfig cc;