@@ -303,6 +303,7 @@ uint32_t Altera::idCode()
303303#define MAX10_BYPASS {0xFF , 0x03 }
304304
305305typedef struct {
306+ uint32_t check_addr0; // something to check before sequence
306307 uint32_t dsm_addr;
307308 uint32_t dsm_len; // 32bits
308309 uint32_t ufm_addr; // UFM1 addr
@@ -315,6 +316,7 @@ typedef struct {
315316
316317static const std::map<uint32_t , max10_mem_t > max10_memory_map = {
317318 {0x031820dd , {
319+ 0x80005 , // check_addr0
318320 0x0000 , 512 , // DSM
319321 0x0200 , {4096 , 4096 }, // UFM
320322 0x2200 , {35840 , 14848 , 20992 }, // CFM
@@ -329,66 +331,115 @@ void Altera::max10_program()
329331 _bit.parse ();
330332 _bit.displayHeader ();
331333
332- uint32_t base_addr; // CFM2 addr
333- uint32_t offset = 0 ;
334+ uint32_t base_addr;
334335
336+ /* Needs to have some specifics informations about internal flash size/organisation
337+ * and some magics.
338+ */
335339 auto mem_map = max10_memory_map.find (_idcode);
336340 if (mem_map == max10_memory_map.end ()) {
337341 printError (" Model not supported. Please update max10_memory_map." );
338342 throw std::runtime_error (" Model not supported. Please update max10_memory_map." );
339343 }
340- max10_mem_t mem = mem_map->second ;
344+ const max10_mem_t mem = mem_map->second ;
341345
342- const uint8_t *cfm_data = _bit.getData (" CFM0" );
343- const uint8_t *ufm_data = _bit.getData (" UFM" );
346+ /*
347+ * MAX10 memory map differs according to internal configuration mode
348+ * - 1 dual compressed image: CFM0 is used for img0, CFM1 + CFM2 for img1
349+ * - 2 single uncompressed image: CFM0 + CFM1 are used, CFM2 used to additional UFM
350+ * - 3/4 single (un)compressed image with mem init: CFM0 + CFM1 + CFM2
351+ * - 5 single compressed image: CFM0 is used, CFM1&CFM2 used to additional UFM
352+ */
353+ /* For Mode (POF content):
354+ * 1 : UFM: UFM1+UFM0 (in this order, this POF section size == memory section size),
355+ * CFM1: CFM2+CFM1 (in this order, this section == CFM2+CFM1 size),
356+ * CFM0: CFM0 (this section size == CFM0 size)
357+ *
358+ * 2 : UFM: UFM1+UFM0+CFM2 (in this order, this section size == full UFM section size + CFM2 size)
359+ * CFM0: CFM1+CFM0 (in this order, this section size == CFM1+CFM0)
360+ *
361+ * 3/4: UFM: UFM1+UFM0 (in this order, this section size == full UFM section size)
362+ * CFM0: CFM2+CFM1+CFM0 (in this order, this section size == full CFM section size)
363+ *
364+ * 5 : UFM: UFM1+UFM0+CFM2+CFM1 (in this order, this section size == full UFM section size + CFM2 size + CFM1 size)
365+ * CFM0: CFM0 (this section size == CFM0)
366+ */
367+ /* OPTIONS:
368+ * ON_CHIP_BITSTREAM_DECOMPRESSION ON/OFF
369+ * Dual Compressed Images (256Kbits UFM):
370+ * set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "DUAL IMAGES"
371+ * Single Compressed Image (1376Kbits UFM):
372+ * set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE"
373+ * Single Compressed Image with Memory Initialization (256Kbits UFM):
374+ * set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE WITH ERAM"
375+ * Single Uncompressed Image (912Kbits UFM):
376+ * set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE IMAGE"
377+ * Single Uncompressed Image with Memory Initialization (256Kbits UFM):
378+ * set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE IMAGE WITH ERAM"
379+ */
380+
381+ /*
382+ * Memory organisation based on internal flash configuration mode is great but in fact
383+ * POF configuration data match MAX10 memory organisation:
384+ * its more easy to start with POF's CFM section and uses pointer based on prev ptr and section size
385+ */
386+
387+ uint8_t *ufm_data[2 ], *cfm_data[3 ]; // memory pointers (2 for UFM, 3 for CFM)
388+
389+ // UFM Mapping
390+ ufm_data[0 ] = _bit.getData (" UFM" );
391+ ufm_data[1 ] = &ufm_data[0 ][mem.ufm_len [0 ] * 4 ]; // Just after UFM0 (but size may differs
392+
393+ // CFM Mapping
394+ cfm_data[2 ] = &ufm_data[1 ][mem.ufm_len [1 ] * 4 ]; // First CFM section in FPGA internal flash
395+ cfm_data[1 ] = &cfm_data[2 ][mem.cfm_len [2 ] * 4 ]; // Second CFM section but just after CFM2
396+ cfm_data[0 ] = &cfm_data[1 ][mem.cfm_len [1 ] * 4 ]; // last CFM section but just after CFM1
397+
398+ // DSM Mapping
344399 const uint8_t *dsm_data = _bit.getData (" ICB" );
345400 const int dsm_len = _bit.getLength (" ICB" ) / 32 ; // getLength (bits) dsm_len in 32bits word
346401
402+
403+ // Start!
347404 max_10_flow_enable ();
348405
349406 max10_flow_erase ();
350407 max10_dsm_verify ();
351408
352409 /* Write */
353- // CFM2->0
354- offset = 0 ;
355- base_addr = mem.cfm_addr ;
356- for (int i = 2 ; i >= 0 ; i--) {
357- printInfo (" Write CFM" + std::to_string (i));
358- writeXFM (cfm_data, base_addr, offset, mem.cfm_len [i]);
359- base_addr += mem.cfm_len [i];
360- offset += (mem.cfm_len [i] * 4 );
361- }
362- // UFM1->0
363- offset = 0 ;
410+
411+ // UFM 1 -> 0
364412 base_addr = mem.ufm_addr ;
365413 for (int i = 1 ; i >= 0 ; i--) {
366414 printInfo (" Write UFM" + std::to_string (i));
367- writeXFM (ufm_data, base_addr, offset, mem.ufm_len [i]);
368- offset += mem.ufm_len [i] * 4 ;
415+ writeXFM (ufm_data[i], base_addr, 0 , mem.ufm_len [i]);
369416 base_addr += mem.ufm_len [i];
370417 }
371418
419+ // CFM2 -> 0
420+ base_addr = mem.cfm_addr ;
421+ for (int i = 2 ; i >= 0 ; i--) {
422+ printInfo (" Write CFM" + std::to_string (i));
423+ writeXFM (cfm_data[i], base_addr, 0 , mem.cfm_len [i]);
424+ base_addr += mem.cfm_len [i];
425+ }
426+
372427 /* Verify */
373428 if (_verify) {
429+ // UFM 1 -> 0
430+ base_addr = mem.ufm_addr ;
431+ for (int i = 1 ; i >= 0 ; i--) {
432+ printInfo (" Verify UFM" + std::to_string (i));
433+ verifyxFM (ufm_data[i], base_addr, 0 , mem.ufm_len [i]);
434+ base_addr += mem.ufm_len [i];
435+ }
436+
374437 // CFM2->0
375- offset = 0 ;
376438 base_addr = mem.cfm_addr ;
377439 for (int i = 2 ; i >= 0 ; i--) {
378440 printInfo (" Verify CFM" + std::to_string (i));
379- verifyxFM (cfm_data, base_addr, offset , mem.cfm_len [i]);
441+ verifyxFM (cfm_data[i] , base_addr, 0 , mem.cfm_len [i]);
380442 base_addr += mem.cfm_len [i];
381- offset += (mem.cfm_len [i] * 4 );
382- }
383-
384- // UFM1->0
385- offset = 0 ;
386- base_addr = mem.ufm_addr ;
387- for (int i = 1 ; i >= 0 ; i--) {
388- printInfo (" Verify UFM" + std::to_string (i));
389- verifyxFM (ufm_data, base_addr, offset, mem.ufm_len [i]);
390- offset += mem.ufm_len [i] * 4 ;
391- base_addr += mem.ufm_len [i];
392443 }
393444 }
394445
@@ -434,7 +485,7 @@ void Altera::writeXFM(const uint8_t *cfg_data, uint32_t base_addr, uint32_t offs
434485 /* precompute some delays required during loop */
435486 const uint32_t isc_program2_delay = 320000 / _clk_period; // ns must be 350us
436487
437- ProgressBar progress (" Verify " , len, 50 , _quiet);
488+ ProgressBar progress (" Write Flash " , len, 50 , _quiet);
438489 for (uint32_t i = 0 ; i < len; i+=512 ) {
439490 bool must_send_sir = true ;
440491 uint32_t max = (i + 512 <= len)? 512 : len - i;
0 commit comments