Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 47 additions & 15 deletions src/pflib/ECON.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -235,34 +235,66 @@ void ECON::setRegisters(

std::map<int, std::map<int, uint8_t>> ECON::getRegisters(
const std::map<int, std::map<int, uint8_t>>& selected) {
// output map: page_id -> (register address -> value)
std::map<int, std::map<int, uint8_t>> chip_reg;
const int page_id = 0; // always page 0
constexpr int MAX_BATCH_SIZE = 128;

std::map<int, std::map<int, uint8_t>> chip_reg;
const int page_id = 0;
std::map<int, uint8_t> all_regs;

// Build sorted list of registers to read
std::vector<std::pair<int, int>> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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) {
Expand Down
61 changes: 61 additions & 0 deletions test/compile.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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<int, std::map<int, uint8_t>> 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()