PIC14 port: an idea about BANKSELs

  • hda

    hda - 2006-11-13

    There is a bug related to BANKSEL directives in the latest 2.6.0 release: even if two variables are in different banks, the compiler does not generate BANKSEL directive between using of them. In latest snapshots, this problem is decided by inserting BANKSEL before every using of every variable. The result is working, but non-optimal code.
    I have an idea about resolving this problem: to merge all variables that we want to be in the same bank, into a structure, and do not generate BANKSEL directives when last accessed variable is in the same bank as the currently accessed. f/e:
    struct bank1 { int i,j,.......} b1;
    struct bank2 { int k,l,.......} b2;
    Something like this is used in proprietary HI-TECH PICC (tm) compiler: if we want some variable to take place in 1,2 or 3 bank, we have to add "bank#" modifier to its declaration. Maybe it is a good idea to add this feature to SDCC?

    • Mac Cody

      Mac Cody - 2006-11-13

      I'm not sure if this is a complete solution of the problem.  I would presume that this approach would also take into account all of the special-purpose registers in PIC (e.g. PORTA, PORTB, etc.).  From previous experience with SDCC 2.6.0, the problem is all a matter of context.  That is, what has happened prior to the execution of each line of code as far as register and variable accesses.  Every place in the code where an "if-else" conditional, "for" loop, "while" loop, "do-while" loop, "switch-case" tree,  or "goto-label" (ick!) occurs has potential for context ambiguity.

      In the thread of bug report 1577882 (Partial BANKSEL for PORTA assignment at while(1) loop start), I made the following suggestion for handling the context issue:

      > I think a "simple" approach would be to maintain
      > optimization but maintain a context flag or context state
      > that would get "reset" at the beginning and ending of each
      > loop, conditional, and switch.  Within the context of a
      > loop, conditional block, or switch case, optimization could
      > occur.  If another loop, conditional, or switch were
      > encountered within that context, any optimization context
      > would be flushed.  This may be more work than it may be
      > worth.  Optimization would be most prevalent in long lines
      > of non-branching code.

      Perhaps, in the SDCC preprocessor, a scan for the occurrence of potential context ambiguities (the presence of control code elements as described above) could be performed to mark the locations where optimization context should be flushed.  Since I am not familar with the internals of SDCC, I have no clue how to modify the code to handle the context marking or flag management.  Still, I think that this is the approach that should be taken to solve the BANKSEL optimization issue.

      • Robas Teodor

        Robas Teodor - 2006-11-19

        Well, some optimisation can be made, if we consider that in some controllers memory is mapped. For example in 16f84 there are only 5 registers that may do need BANKSEL. The rest can be accessed from any memory bank, especially RAM. Maybe this registers (memory areas) can be defined in CPU specific header file.
        What is your opinion about this ?

        • Raphael Neider

          Raphael Neider - 2006-11-23

          This is a correct approach---and even partially implemented: the device descriptions (include/pic14devices.txt) provide bankmask, regmap, and memmap entries that can be exploited for this purpose.

          I just (SDCC r4478) implemented
          * no BANKSEL for STATUS (unnecessary, but would break interrupt handlers)
          * no BANKSEL for registers known to reside in all banks that might currently be selected (based on hard-coded regmasks, mostly used for SFRs that reside in all banks, STATUS, PCLATH, FSR, ...)
          * no BANKSEL from regA to regA, i.e., a pCode walker iterates over the whole code and keeps track of the register name used in the last BANKSEL, works even for (regA + X) references in multi-byte variables

          Additionally, I have the pseudo stack (STKxx) and the copy locations for W, STATUS, and PCLATH (WSAVE, SSAVE, and PSAVE) placed into a true sharebank (udata_shr) and let gplink do the actual allocation (this was suggested in a different thread). Consequently, STKxx do not require any BANKSELs any more.

          !!!As a consequence, I strongly recommend rebuilding the library after upgrading SDCC!!!

          The problem I am about to tackle next is dealing more efficiently with local variables:
          The r0xPQRS may are all be placed into different banks, making accesses to them terribly inefficient. I think about clustering them in chunks of, say, 8--16 bytes and have these clusters allocated continuously into a single bank. The clustering would be based on BANKSEL frequencies between them and should reduce code size considerably.

          I will also look into optimizing tiny devices as you proposed: IF there is only one bank for non-SFR registers (i.e., addresses 0x20--0x7F (or lower memory limit) are mapped into all banks via a 'memmap 0x20 0x7F <bankmsk>'), THEN SDCC should emit BANKSELs only for SFRs.
          This needs some looking into as I do not know in how far the memmask and regmask entries are actually parsed right now.

          Just thinking you might still want an answer,

    • Mac Cody

      Mac Cody - 2006-11-20

      I am no expert on the PIC14 port of SDCC, so I don't know if device-by-device optimizations, as you describe above, are already being performed.  I am also no authority on the many various versions of PIC14 devices, either.  I am currently only using the 16F628, though I may start using the 16F7877 later.  Other than the PCL register, I don't know how the PIC14 port of SDCC accesses memory/registers that are common across banks.  I would think that the "optimization" that is done for the PCL register could be done for other such registers.  That is to say, "with these registers/memory, BANKSELs are not needed".  It certainly would be preferable to place the optimization information, when device-specific, in the device header file.

      The concept I outlined in my previous post would be applicable to all PIC14 devices, so it would deliver optimization to all PIC14 device versions.  Some optimization would be delivered to all PIC14 device versions without having to configure each device header file.  This would be an immediate gain for all PIC14 users, rather than only those who would benefit from developers who updated the headers of specific device types.  I'm not saying that your suggestion does not have merit.  I just like to see optimizations performed that benefit the greatest number of users for the effort put forth.


Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

No, thanks