@@ -42,15 +42,33 @@ uint16_t calc_checksum(std::string bytes)
4242}
4343
4444uint32_t get_num_config_fuses (Trellis::ChipInfo &ci) {
45- if (ci.name == " LCMXO2-4000" ) {
45+ if (ci.name == " LCMXO2-256" ) {
46+ return (575 + 0 + 1 )*128 ; // No UFM, 1 dummy page at end.
47+ } else if (ci.name == " LCMXO2-640" ) {
48+ return (1151 + 191 + 1 )*128 ; // UFM is 0 bytes after end of CFG, 1 dummy page at end.
49+ } else if (ci.name == " LCMXO2-1200" || ci.name == " LCMXO2-640U" ) {
50+ return (2175 + 511 + 1 )*128 ; // UFM is 0 bytes after end of CFG, 1 dummy page at end.
51+ } else if (ci.name == " LCMXO2-2000" || ci.name == " LCMXO2-1200U" ) {
52+ return (3198 + 639 + 1 )*128 ; // UFM is 0 bytes after end of CFG, 1 dummy page at end.
53+ } else if (ci.name == " LCMXO2-4000" || ci.name == " LCMXO2-2000U" ) {
4654 return (5758 + 767 + 1 )*128 ; // UFM is 0 bytes after end of CFG, 1 dummy page at end.
47- } if (ci.name == " LCMXO2-7000" ) {
55+ } else if (ci.name == " LCMXO2-7000" ) {
4856 return (9211 + 1 + 2046 + 2 )*128 ; // UFM is 16 bytes after end of CFG, 2 dummy pages at end.
4957 } else {
5058 throw runtime_error (fmt (" Can not extract number of config fuses from FPGA family " << ci.name ));
5159 }
5260}
5361
62+ int num_digits (uint32_t num) {
63+ int count = 0 ;
64+ do {
65+ num /= 10 ;
66+ count++;
67+ } while (num != 0 );
68+
69+ return count;
70+ }
71+
5472int main (int argc, char *argv[])
5573{
5674 using namespace Trellis ;
@@ -68,6 +86,7 @@ int main(int argc, char *argv[])
6886 options.add_options ()(" svf" , po::value<std::string>(), " output SVF file" );
6987 options.add_options ()(" svf-rowsize" , po::value<int >(), " SVF row size in bits (default 8000)" );
7088 options.add_options ()(" jed" , po::value<std::string>(), " output JED file" );
89+ options.add_options ()(" jed-note" , po::value<vector<std::string>>(), " emit NOTE field in JED file" );
7190 options.add_options ()(" compress" , " compress bitstream to reduce size" );
7291 options.add_options ()(" spimode" , po::value<std::string>(), " SPI Mode to use (fast-read, dual-spi, qspi)" );
7392 options.add_options ()(" background" , " enable background reconfiguration in bitstream" );
@@ -377,8 +396,15 @@ int main(int argc, char *argv[])
377396
378397 jed_file << " \x02 *" << endl; // STX plus "design specification" (not filled in).
379398 full_checksum += calc_checksum (" \x02 *\n " );
380- // jed_file << "\x03" << hex << uppercase << setw(4) << full_checksum << endl;
381- // return 0;
399+
400+ if (vm.count (" jed-note" )) {
401+ ostringstream note_field;
402+ for (auto &n: vm[" jed-note" ].as <vector<string>>()) {
403+ note_field << " NOTE " << n << " *" << endl;
404+ full_checksum += calc_checksum (note_field.str ());
405+ jed_file << note_field.str ();
406+ }
407+ }
382408
383409 ostringstream fusecnt_field;
384410 uint32_t fusecnt;
@@ -389,6 +415,7 @@ int main(int argc, char *argv[])
389415 return 1 ;
390416 }
391417
418+ // TODO: QP (package information not implied in textual representation).
392419 fusecnt_field << " QF" << fusecnt << ' *' << endl;
393420 full_checksum += calc_checksum (fusecnt_field.str ());
394421 jed_file << fusecnt_field.str ();
@@ -397,19 +424,36 @@ int main(int argc, char *argv[])
397424 full_checksum += calc_checksum (" G0*\n " );
398425 jed_file << " F0*" << endl; // Default fuse value.
399426 full_checksum += calc_checksum (" F0*\n " );
400- jed_file << " L0" << endl;
401- full_checksum += calc_checksum (" L0\n " );
402427
428+ // The JEDEC spec says leading 0s are optional. My own experience is
429+ // that some programmers require leading 0s.
430+ ostringstream list_field;
431+ list_field << " L" << setw (num_digits (fusecnt)) << setfill (' 0' ) << 0 << endl;
432+ full_checksum += calc_checksum (list_field.str ());
433+ jed_file << list_field.str ();
434+
435+ // Strip the leading comment- it wastes precious fuse space and
436+ // some programmers (e.g STEP-MXO2) even rely on the preamble being
437+ // the first bytes.
438+ vector<uint8_t > preamble = {0xFF , 0xFF , 0xBD , 0xB3 , 0xFF , 0xFF };
439+ auto start_iter = search (begin (bitstream), end (bitstream), begin (preamble), end (preamble));
440+
441+ if (start_iter == end (bitstream)) {
442+ cerr << " Could not extract preamble from bitstream" << endl;
443+ return 1 ;
444+ }
445+
446+ auto start_offs = start_iter - bitstream.begin ();
403447
404448 size_t i = 0 ;
405449 while (i < fusecnt/8 ) {
406450 if (i < bitstream.size ()) {
407451 size_t len = min (size_t (16 ), bitstream.size () - i);
408452
409453 for (unsigned int j = 0 ; j < len; j++) {
410- uint8_t byte = uint8_t (bitstream[j + i]);
454+ uint8_t byte = uint8_t (bitstream[j + i + start_offs ]);
411455 checksum += reverse_byte (byte);
412- full_checksum += calc_checksum (std:: bitset<8 >{byte}.to_string ());
456+ full_checksum += calc_checksum (bitset<8 >{byte}.to_string ());
413457 jed_file << std::bitset<8 >{byte};
414458 }
415459
@@ -442,10 +486,10 @@ int main(int argc, char *argv[])
442486 jed_file << " *" << endl;
443487 full_checksum += calc_checksum (" *\n " );
444488
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 ();
489+ ostringstream checksum_field ;
490+ checksum_field << " C" << hex << uppercase << setfill (' 0' ) << setw (4 ) << checksum << ' *' << endl;
491+ full_checksum += calc_checksum (checksum_field .str ());
492+ jed_file << checksum_field .str ();
449493
450494 full_checksum += calc_checksum (" \x03 " );
451495 jed_file << " \x03 " << hex << uppercase << setw (4 ) << setfill (' 0' ) << full_checksum << endl;
0 commit comments