diff --git a/include/pflib/ECON.h b/include/pflib/ECON.h index 84e47fd61..740e9e52b 100644 --- a/include/pflib/ECON.h +++ b/include/pflib/ECON.h @@ -45,6 +45,7 @@ class ECON { const std::string& file_path); uint64_t readParameter(const std::string& page, const std::string& param, bool print_values = false); + std::map readRegisterRange(int start_addr, int end_addr); void dumpSettings(const std::string& filename, bool should_decompile); diff --git a/src/pflib/ECON.cxx b/src/pflib/ECON.cxx index c8f301b93..9f3abd49a 100644 --- a/src/pflib/ECON.cxx +++ b/src/pflib/ECON.cxx @@ -15,6 +15,7 @@ ECON::ECON(I2C& i2c, uint8_t econ_base_addr, const std::string& type_version) econ_base_{econ_base_addr}, compiler_{Compiler::get(type_version)}, type_{type_version} { + i2c_.set_bus_speed(1400); econ_reg_nbytes_lut_ = compiler_.build_register_byte_lut(); pflib_log(debug) << "ECON base addr " << packing::hex(econ_base_); @@ -240,37 +241,79 @@ std::map> ECON::getRegisters( const int page_id = 0; // always page 0 std::map all_regs; + // Batch contiguous addresses + const int MAX_READ_GAP = 8; + const int MAX_BATCH_SIZE = 256; if (selected.empty()) { - // if no specific registers are requested, read all registers - // printf("[DEBUG] Selected map is empty — reading all registers.\n"); + // Build sorted list of all register addresses we need to read + std::vector addresses; for (const auto& [reg_addr, nbytes] : econ_reg_nbytes_lut_) { - std::vector values = getValues(reg_addr, nbytes); - for (int i = 0; i < values.size(); ++i) { - // printf("Read [0x%04x] = 0x%02x\n", reg_addr + i, values[i]); - all_regs[reg_addr + i] = values[i]; + for (int i = 0; i < nbytes; i++) { + addresses.push_back(reg_addr + i); } } + // sort the addresses + std::sort(addresses.begin(), addresses.end()); + // remove duplicates if any + addresses.erase(std::unique(addresses.begin(), addresses.end()), + addresses.end()); + + for (size_t i = 0; i < addresses.size();) { + int start_addr = addresses[i]; + int end_addr = addresses[i]; + size_t j = i + 1; + + // Extend batch while addresses are close together + while (j < addresses.size() && addresses[j] - end_addr <= MAX_READ_GAP && + addresses[j] - start_addr < MAX_BATCH_SIZE) { + end_addr = addresses[j]; + j++; + } + + // Read the batch + auto batch_result = readRegisterRange(start_addr, end_addr); + for (const auto& [addr, val] : batch_result) { + chip_reg[page_id][addr] = val; + } + // advance to next batch + i = j; + } } else { - // only read the registers in selected[0] + // Similar logic for selected registers const auto& reg_map = selected.at(page_id); - for (const auto& [reg_addr, nbytes] : econ_reg_nbytes_lut_) { - if (reg_map.find(reg_addr) != reg_map.end()) { - std::vector values = getValues(reg_addr, nbytes); - for (int i = 0; i < (int)values.size(); ++i) { - // printf("Read [0x%04x] = 0x%02x\n", reg_addr + i, values[i]); - all_regs[reg_addr + i] = values[i]; - } - } + std::vector addresses; + for (const auto& [addr, _] : reg_map) { + addresses.push_back(addr); } - } + // sort the addresses + std::sort(addresses.begin(), addresses.end()); + + // Batch read the selected addresses + for (size_t i = 0; i < addresses.size();) { + int start_addr = addresses[i]; + int end_addr = addresses[i]; + size_t j = i + 1; + + while (j < addresses.size() && addresses[j] - end_addr <= MAX_READ_GAP && + addresses[j] - start_addr < MAX_BATCH_SIZE) { + end_addr = addresses[j]; + j++; + } - for (const auto& [reg, val] : all_regs) { - chip_reg[page_id][reg] = val; - } + auto batch_result = readRegisterRange(start_addr, end_addr); + for (const auto& [addr, val] : batch_result) { + if (reg_map.find(addr) != reg_map.end()) { + chip_reg[page_id][addr] = val; + } + } + // advance to next batch + i = j; + } // end loop on batches + } // end else selected not empty return chip_reg; -} +} // end of ECON::getRegisters std::map> ECON::applyParameters( const std::map>& parameters) { @@ -369,6 +412,17 @@ uint64_t ECON::readParameter(const std::string& page, const std::string& param, return values[page][param]; // return the actual register value } +std::map ECON::readRegisterRange(int start_addr, int end_addr) { + int total_bytes = end_addr - start_addr + 1; + std::vector values = getValues(start_addr, total_bytes); + + std::map result; + for (int i = 0; i < total_bytes; i++) { + result[start_addr + i] = values[i]; + } + return result; +} + void ECON::dumpSettings(const std::string& filename, bool should_decompile) { if (filename.empty()) { PFEXCEPTION_RAISE("Filename", diff --git a/src/pflib/bittware/bittware_axilite.cxx b/src/pflib/bittware/bittware_axilite.cxx index d3d64b32a..d6a8e33f3 100644 --- a/src/pflib/bittware/bittware_axilite.cxx +++ b/src/pflib/bittware/bittware_axilite.cxx @@ -21,7 +21,8 @@ AxiLite::AxiLite(const uint32_t base_address, const char* dev, : dev_{dev}, base_{base_address | 0x00c00000}, mask_{mask_space & 0xFFFFFFFCu}, - antimask_{0xFFFFFFFFu ^ mask_}, waswrite_{true} { + antimask_{0xFFFFFFFFu ^ mask_}, + waswrite_{true} { auto ptr = handle_map.find(dev); if (ptr != handle_map.end()) handle_ = ptr->second; @@ -49,9 +50,10 @@ uint32_t AxiLite::read(uint32_t addr) { "Address 0x%0x is invalid", addr)); } uint32_t val; - if (waswrite_) { // seem to need this double read, would be good to fix at firmware level... - dmaReadRegister(handle_, base_ | addr, &val); - waswrite_=false; + if (waswrite_) { // seem to need this double read, would be good to fix at + // firmware level... + dmaReadRegister(handle_, base_ | addr, &val); + waswrite_ = false; } dmaReadRegister(handle_, base_ | addr, &val); return val; @@ -63,7 +65,7 @@ void AxiLite::write(uint32_t addr, uint32_t val) { "Address 0x%0x is invalid", addr)); } dmaWriteRegister(handle_, base_ | addr, val); - waswrite_=true; + waswrite_ = true; } static int first_bit_set(uint32_t mask) {