Skip to content

Commit 818fabe

Browse files
committed
Improve robustness of ecppack JED file generator. Allow NOTEs to be generated.
1 parent c84aae2 commit 818fabe

File tree

1 file changed

+46
-10
lines changed

1 file changed

+46
-10
lines changed

libtrellis/tools/ecppack.cpp

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ uint32_t get_num_config_fuses(Trellis::ChipInfo &ci) {
5151
}
5252
}
5353

54+
int num_digits(uint32_t num) {
55+
int count = 0;
56+
do {
57+
num /= 10;
58+
count++;
59+
} while(num != 0);
60+
61+
return count;
62+
}
63+
5464
int main(int argc, char *argv[])
5565
{
5666
using namespace Trellis;
@@ -68,6 +78,7 @@ int main(int argc, char *argv[])
6878
options.add_options()("svf", po::value<std::string>(), "output SVF file");
6979
options.add_options()("svf-rowsize", po::value<int>(), "SVF row size in bits (default 8000)");
7080
options.add_options()("jed", po::value<std::string>(), "output JED file");
81+
options.add_options()("jed-note", po::value<vector<std::string>>(), "emit NOTE field in JED file");
7182
options.add_options()("compress", "compress bitstream to reduce size");
7283
options.add_options()("spimode", po::value<std::string>(), "SPI Mode to use (fast-read, dual-spi, qspi)");
7384
options.add_options()("background", "enable background reconfiguration in bitstream");
@@ -377,8 +388,15 @@ int main(int argc, char *argv[])
377388

378389
jed_file << "\x02*" << endl; // STX plus "design specification" (not filled in).
379390
full_checksum += calc_checksum("\x02*\n");
380-
// jed_file << "\x03" << hex << uppercase << setw(4) << full_checksum << endl;
381-
// return 0;
391+
392+
if (vm.count("jed-note")) {
393+
ostringstream note_field;
394+
for(auto &n: vm["jed-note"].as<vector<string>>()) {
395+
note_field << "NOTE " << n << "*" << endl;
396+
full_checksum += calc_checksum(note_field.str());
397+
jed_file << note_field.str();
398+
}
399+
}
382400

383401
ostringstream fusecnt_field;
384402
uint32_t fusecnt;
@@ -389,6 +407,7 @@ int main(int argc, char *argv[])
389407
return 1;
390408
}
391409

410+
// TODO: QP (package information not implied in textual representation).
392411
fusecnt_field << "QF" << fusecnt << '*' << endl;
393412
full_checksum += calc_checksum(fusecnt_field.str());
394413
jed_file << fusecnt_field.str();
@@ -397,19 +416,36 @@ int main(int argc, char *argv[])
397416
full_checksum += calc_checksum("G0*\n");
398417
jed_file << "F0*" << endl; // Default fuse value.
399418
full_checksum += calc_checksum("F0*\n");
400-
jed_file << "L0" << endl;
401-
full_checksum += calc_checksum("L0\n");
402419

420+
// The JEDEC spec says leading 0s are optional. My own experience is
421+
// that some programmers require leading 0s.
422+
ostringstream list_field;
423+
list_field << "L" << setw(num_digits(fusecnt)) << setfill('0') << 0 << endl;
424+
full_checksum += calc_checksum(list_field.str());
425+
jed_file << list_field.str();
426+
427+
// Strip the leading comment- it wastes precious fuse space and
428+
// some programmers (e.g STEP-MXO2) even rely on the preamble being
429+
// the first bytes.
430+
vector<uint8_t> preamble = {0xFF, 0xFF, 0xBD, 0xB3, 0xFF, 0xFF };
431+
auto start_iter = search(begin(bitstream), end(bitstream), begin(preamble), end(preamble));
432+
433+
if(start_iter == end(bitstream)) {
434+
cerr << "Could not extract preamble from bitstream" << endl;
435+
return 1;
436+
}
437+
438+
auto start_offs = start_iter - bitstream.begin();
403439

404440
size_t i = 0;
405441
while(i < fusecnt/8) {
406442
if(i < bitstream.size()) {
407443
size_t len = min(size_t(16), bitstream.size() - i);
408444

409445
for (unsigned int j = 0; j < len; j++) {
410-
uint8_t byte = uint8_t(bitstream[j + i]);
446+
uint8_t byte = uint8_t(bitstream[j + i + start_offs]);
411447
checksum += reverse_byte(byte);
412-
full_checksum += calc_checksum(std::bitset<8>{byte}.to_string());
448+
full_checksum += calc_checksum(bitset<8>{byte}.to_string());
413449
jed_file << std::bitset<8>{byte};
414450
}
415451

@@ -442,10 +478,10 @@ int main(int argc, char *argv[])
442478
jed_file << "*" << endl;
443479
full_checksum += calc_checksum("*\n");
444480

445-
ostringstream oss;
446-
oss << "C" << hex << uppercase << setfill('0') << setw(4) << checksum << '*' << endl;
447-
full_checksum += calc_checksum(oss.str());
448-
jed_file << oss.str();
481+
ostringstream checksum_field;
482+
checksum_field << "C" << hex << uppercase << setfill('0') << setw(4) << checksum << '*' << endl;
483+
full_checksum += calc_checksum(checksum_field.str());
484+
jed_file << checksum_field.str();
449485

450486
full_checksum += calc_checksum("\x03");
451487
jed_file << "\x03" << hex << uppercase << setw(4) << setfill('0') << full_checksum << endl;

0 commit comments

Comments
 (0)