diff --git a/src/pflib/ECON.cxx b/src/pflib/ECON.cxx index a0122dba5..0817118c1 100644 --- a/src/pflib/ECON.cxx +++ b/src/pflib/ECON.cxx @@ -235,34 +235,66 @@ void ECON::setRegisters( std::map> ECON::getRegisters( const std::map>& selected) { - // output map: page_id -> (register address -> value) - std::map> chip_reg; - const int page_id = 0; // always page 0 + constexpr int MAX_BATCH_SIZE = 128; + std::map> chip_reg; + const int page_id = 0; std::map all_regs; + // Build sorted list of registers to read + std::vector> reads_to_perform; // (address, nbytes) + if (selected.empty()) { - // if no specific registers are requested, read all registers - // printf("[DEBUG] Selected map is empty — reading all registers.\n"); 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]; - } + reads_to_perform.emplace_back(reg_addr, nbytes); } } else { - // only read the registers in selected[0] 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]; + reads_to_perform.emplace_back(reg_addr, nbytes); + } + } + } + + // Sort by address + std::sort(reads_to_perform.begin(), reads_to_perform.end()); + + // Batch adjacent reads with size limit + if (!reads_to_perform.empty()) { + int start_addr = reads_to_perform[0].first; + int current_end = start_addr + reads_to_perform[0].second; + + for (size_t i = 1; i < reads_to_perform.size(); ++i) { + int next_addr = reads_to_perform[i].first; + int next_nbytes = reads_to_perform[i].second; + int potential_size = next_addr + next_nbytes - start_addr; + + // Check if contiguous AND under size limit + if (next_addr == current_end && potential_size <= MAX_BATCH_SIZE) { + // Extend the batch + current_end = next_addr + next_nbytes; + } else { + // Non-contiguous or too large - perform the batch + int batch_size = current_end - start_addr; + std::vector batch_data = getValues(start_addr, batch_size); + + for (int j = 0; j < batch_size; ++j) { + all_regs[start_addr + j] = batch_data[j]; } + + // Start new batch + start_addr = next_addr; + current_end = next_addr + next_nbytes; } } + + // Perform the final batch + int batch_size = current_end - start_addr; + std::vector batch_data = getValues(start_addr, batch_size); + for (int j = 0; j < batch_size; ++j) { + all_regs[start_addr + j] = batch_data[j]; + } } for (const auto& [reg, val] : all_regs) { diff --git a/test/compile.cxx b/test/compile.cxx index 7cfa3419d..66ba38c2b 100644 --- a/test/compile.cxx +++ b/test/compile.cxx @@ -312,4 +312,65 @@ BOOST_AUTO_TEST_CASE(full_lut_econd) { "The generated register LUT does not match the expected LUT"); } +BOOST_AUTO_TEST_CASE(read_three_aligner_params) { + pflib::Compiler c = pflib::Compiler::get("econd"); + + std::map> registers; + + // First, set all registers to zero to avoid warnings + auto reg_lut = c.build_register_byte_lut(); + for (const auto& [reg_addr, nbytes] : reg_lut) { + for (size_t i = 0; i < nbytes; i++) { + registers[0][reg_addr + i] = 0; + } + } + + // Now overwrite with our three parameters of interest + c.compile("ALIGNER", "GLOBAL_MATCH_PATTERN_VAL", 10760600711006082389ULL, + registers); + c.compile("ALIGNER", "GLOBAL_IDLE_HDR_VAL", 12, registers); + c.compile("ALIGNER", "GLOBAL_ORBSYN_CNT_LOAD_VAL", 3514, registers); + + // Decompile + auto chip_params = c.decompile(registers, true, true); + auto aligner_it = chip_params.find("ALIGNER"); + if (aligner_it != chip_params.end()) { + const auto& params = aligner_it->second; + + auto check_param = [&](const std::string& param_name, uint64_t expected) { + auto it = params.find(param_name); + if (it != params.end()) { + bool match = (it->second == expected); + std::cout << param_name << ":" << std::endl; + std::cout << " Found: " << std::dec << it->second << " (0x" + << std::hex << std::uppercase << it->second << ")" + << std::endl; + std::cout << " Expected: " << std::dec << expected << " (0x" + << std::hex << std::uppercase << expected << ")" << std::endl; + std::cout << " Status: " << (match ? "PASS ✓" : "FAIL ✗") + << std::endl + << std::endl; + BOOST_CHECK_EQUAL(it->second, expected); + } else { + std::cout << param_name << ":" << std::endl; + std::cout << " Status: NOT FOUND ✗" << std::endl; + std::cout << " Expected: " << std::dec << expected << " (0x" + << std::hex << std::uppercase << expected << ")" << std::endl + << std::endl; + BOOST_FAIL("Parameter not found: " + param_name); + } + }; + + check_param("GLOBAL_MATCH_PATTERN_VAL", 10760600711006082389ULL); + check_param("GLOBAL_IDLE_HDR_VAL", 12); + check_param("GLOBAL_ORBSYN_CNT_LOAD_VAL", 3514); + } else { + std::cout << "ERROR: ALIGNER page not found in decompiled output!" + << std::endl; + BOOST_FAIL("ALIGNER page not found"); + } + + std::cout << "=== End of Test ===" << std::endl; +} // end of BOOST_AUTO_TEST_CASE(read_three_aligner_params) + BOOST_AUTO_TEST_SUITE_END()