Hi all!
Python was a very good recommendation, thank you Rob Hammerling :-)
I dropped the idea of the array with no index, that would have been a difficult 
and nearly useless addition.
Other bad news: The PIC14/byte*2 version needs one byte GPR more than the old 
lib, PIC16/byte*4 even four bytes more.
But that is it, all other versions need the same or less GPR. Execution time 
and code size are now even 12-25% smaller than with my last version, now my 
test program in the best cases needs little more than half the time compared to 
the original lib, code is between 300 and 1000 words smaller. 
I did some tests, but only with one array at a time. 
Greets,Kiste
   
  

-- 
You received this message because you are subscribed to the Google Groups 
"jallib" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jallib/2049291384.2558336.1608403923944%40mail.yahoo.com.
# Title: Large Array library generation script
# Author: Oliver "Kiste" Seitz, copyright (c) 2009..2020, all rights reserved. 
# Adapted-by: 
# Interpreter: Python3
# Revision: \$Revision$
#
# This file is part of jallib (https://github.com/jallib/jallib)
# Released under the ZLIB license (http://www.opensource.org/licenses/zlib-license.html)
#
# Description: This script generates the file large_array.jal
#              For compatibility, also files like
#              large_array_1.jal, large_array_2.jal...
#              are generated. These include a deprecated warning.
#
# Notes: The generated library is configurable. These values can be adjusted:
#
#   max_bytes_pic16=(58*256)
#       This value defines the maximum size of each array. As of 2020, 58 banks
#       of 256 bytes each is more than the largest PIC16 controller can have.
#   max_bytes_pic14=(60*80)
#       This value defines the maximum size of each array. As of 2020, 60 banks
#       of 80 bytes each is more than the largest PIC14 controller can have.
#   number_of_arrays=4
#       The original set of Large Array libs was designed to give up to four
#       arrays. Now, as the source is generated, the number can be increased
#       if needed.
#


# Configure the generated library
max_bytes_pic16=(58*256)
max_bytes_pic14=(60*80)
number_of_arrays=4

main_output_file="large_array.jal"
compat_output_file="large_array_{0}.jal"


# make sure the limits are multiples of four, round down if neccessary
max_bytes_pic16 = max_bytes_pic16 - (max_bytes_pic16 % 4)
max_bytes_pic14 = max_bytes_pic14 - (max_bytes_pic14 % 4)


# Define strings with quasi-static texts

prologue="""-- Title: Large Array library
-- Author: Oliver "Kiste" Seitz, copyright (c) 2009..2020, all rights reserved.
-- Based on work by Matthew Schinkel - borntechi.com and Rob Jansen 
-- Adapted-by: 
-- Compiler: >=2.5r4
-- Revision: \$Revision$
--
-- This file is part of jallib (https://github.com/jallib/jallib)
-- Released under the ZLIB license (http://www.opensource.org/licenses/zlib-license.html)
--
-- Description: This library is for creating arrays that take up more than one
--              GPR segment of memory. Works for PIC14(H) and PIC16 cores. It is 
--              a complete rewrite of the original set of large_array libs.
--
-- Sources: This file is generated by script: generate_large_array.py
--
-- Notes:
-- For controllers with PIC16 core (labeled PIC18(l)f...)
-- Supports byte array with up to {0} entries (LARGE_ARRAY_1_VARIABLE_SIZE = 1)
-- Supports word array with up to {1} entries (LARGE_ARRAY_1_VARIABLE_SIZE = 2)
-- Supports dword array with up to {2} entries (LARGE_ARRAY_1_VARIABLE_SIZE = 4)
--
-- For controllers with PIC14 core (labeled PIC16(l)f... or PIC12(l)f...)
-- Supports byte array with up to {3} entries (LARGE_ARRAY_1_VARIABLE_SIZE = 1)
-- Supports word array with up to {4} entries (LARGE_ARRAY_1_VARIABLE_SIZE = 2)
-- Supports dword array with up to {5} entries (LARGE_ARRAY_1_VARIABLE_SIZE = 4)
--
--
-- Can create up to {6} arrays, named large_array_1, large_array_2...
-- Use "alias new_array_name is large_array_1" to rename the array
-- 
--
-- Example:
-- const LARGE_ARRAY_1_SIZE = 600        -- choose number of array variables, not bytes
-- const LARGE_ARRAY_1_VARIABLE_SIZE = 2 -- choose size of variables (word)
-- const LARGE_ARRAY_2_SIZE = 400        -- 
-- const LARGE_ARRAY_2_VARIABLE_SIZE = 4 -- 
-- include large_array                   -- include the array library
-- alias first_array is large_array_1    -- rename/alias the array to suit your program
-- alias second_array is large_array_2
--
-- Important: There is no range check on the index in the array.
--


-- Check for the target CPU
if ! defined(_large_array_core) then
   if (target_cpu == PIC_14H) | (target_cpu == PIC_14) then
      const _large_array_core=14
   elsif (target_cpu == PIC_16) then
      const _large_array_core=16
   else
      _ERROR "Large Array not supported for this PIC"
   end if
end if   

"""


newline="""
"""

address_decode_14_1="""
      var byte section

      -- The following lines do something like
      --
      --   section=address/80
      --   address=address%80
      --
      -- Not using divisions can save quite some code space (if there are no 
      -- divisions in the program yet, other than by powers of 2).
      -- Even if not saving code space, successive subtraction is often 
      -- faster in execution time. A sample program using divisions took more
      -- than three times the execution time.
   
      section=0

      while address_hi!=0 loop
        address=address-240
        section=section+3
      end loop
   
      while address_lo>=80 loop
        address_lo=address_lo-80
        section=section+1
      end loop
 
"""


address_decode_14_2="""
      var byte section

      -- The following lines do something like
      --
      --   section=address/40
      --   address=address%40
      --
      -- Not using divisions can save quite some code space (if there are no 
      -- divisions in the program yet, other than by powers of 2).
      -- Even if not saving code space, successive subtraction is often 
      -- faster in execution time. A sample program using divisions took more
      -- than three times the execution time.
   
      section=0

      while address_hi!=0 loop
        address=address-240
        section=section+6
      end loop
   
      if address_lo>=120 then
        address_lo=address_lo-120
        section=section+3
      end if

      while address_lo>=40 loop
        address_lo=address_lo-40
        section=section+1
      end loop
 
"""


address_decode_14_4="""
      var byte section

      -- The following lines do something like
      --
      --   section=address/20
      --   address=address%20
      --
      -- Not using divisions can save quite some code space (if there are no 
      -- divisions in the program yet, other than by powers of 2).
      -- Even if not saving code space, successive subtraction is often 
      -- faster in execution time. A sample program using divisions took more
      -- than three times the execution time.
   
      section=0

      while address_hi!=0 loop
        address=address-240
        section=section+12
      end loop   

      while address_lo>=60 loop
        address_lo=address_lo-60
        section=section+3
      end loop

      while address_lo>=20 loop
        address_lo=address_lo-20
        section=section+1
      end loop
 
"""

address_decode_16_1="""
      var byte section at address_hi

"""

address_decode_16_2="""
      var byte section at address_hi

      address      =address   <<1          -- move the lo-byte's MSB to the hi-byte's LSB, i.e. 
      address_lo   =address_lo>>1          -- limit lo to 127, double hi and add carry

"""

address_decode_16_4="""
      var byte section at address_hi

      address      =address   <<2          -- move the two highest bits from lo to the low end of hi, i.e. 
      address_lo   =address_lo>>2          -- limit lo to 63, multiply hi by 4 and add carry

"""

read_function_prologue="""
   function large_array_{0}'get(word in address) return byte*{1} is
      var byte address_lo at address
      var byte address_hi at address+1
"""

write_procedure_prologue="""
   procedure large_array_{0}'put(word in address, byte*{1} in data) is
      var byte address_lo at address+0
      var byte address_hi at address+1
"""

compat_text="""-- Title: Large Array library
-- Author: Oliver "Kiste" Seitz, copyright (c) 2009..2020, all rights reserved.
-- Based on work by Matthew Schinkel - borntechi.com and Rob Jansen 
-- Adapted-by: 
-- Compiler: >=2.5r4
-- Revision: \$Revision$
--
-- This file is part of jallib (https://github.com/jallib/jallib)
-- Released under the ZLIB license (http://www.opensource.org/licenses/zlib-license.html)
--
-- Description: This file is to maintain compatibility with the old large_array library,
--              which used seperate include files for each array.
--              It doesn't do anything but include the current library, which can safely
--              be included more than once.
--
-- Sources: This file is generated by script: generate_large_array.py
--

_WARN "large_array_{0}.jal is deprecated. Please use large_array instead."

include large_array

"""
# Define subroutines which actually generate parts of the file

def define_variables_per_core():

    for output_counter in range(1,number_of_arrays+1):
        target.write( "if defined(LARGE_ARRAY_{0}_SIZE) & ! defined(_LARGE_ARRAY_{0}_COMPLETE) & (_large_array_core == {1}) then".format(output_counter,core))
        target.write(newline)
        target.write( "   if ! defined(LARGE_ARRAY_{0}_VARIABLE_SIZE) then".format(output_counter))
        target.write(newline)
        target.write( "      LARGE_ARRAY_{0}_VARIABLE_SIZE = 1                    -- default to byte*1".format(output_counter))
        target.write(newline)
        target.write( "   end if")
        target.write(newline)
        target.write( "   if (LARGE_ARRAY_{0}_VARIABLE_SIZE * LARGE_ARRAY_{0}_SIZE > {1}) then".format(output_counter,max_bytes))
        target.write(newline)
        target.write( "      _ERROR \"Large array only supports {0} bytes on this core\"".format(max_bytes))
        target.write(newline)
        target.write( "   end if")
        target.write(newline)
        
        for size_counter in [1,2,4]:
            target.write( "   if LARGE_ARRAY_{0}_VARIABLE_SIZE == {1} then".format(output_counter,size_counter) )
            target.write(newline)
            target.write( "      if LARGE_ARRAY_{0}_SIZE % {1} != 0 then ".format(output_counter,int(chunk_size/size_counter)) )
            target.write(newline)
            target.write( "         var byte*{1} _large_array_{0}_{1}_00[LARGE_ARRAY_{0}_SIZE % {2}]".format(output_counter,size_counter,int(chunk_size/size_counter)) )
            target.write(newline)
            target.write( "      else" )
            target.write(newline)
            target.write( "         var byte*{1} _large_array_{0}_{1}_00[{2}]".format(output_counter,size_counter,int(chunk_size/size_counter)) )
            target.write(newline)
            target.write( "      end if")
            target.write(newline)
            for run_counter in range(int((max_bytes/chunk_size))):
                target.write( "      var byte*{1} _large_array_{0}_{1}_{2:02d}[{3}]".format(output_counter,size_counter,run_counter+1,int(chunk_size/size_counter)))
                target.write(newline)
            target.write( "   end if" )    
            target.write(newline)
        target.write("end if")
        target.write(newline)


def define_variable_access():
    
    for output_counter in range(1,number_of_arrays+1):
        for size_counter in [1,2,4]:
            target.write(newline)
            target.write( "if defined(LARGE_ARRAY_{0}_SIZE) & (! defined(_LARGE_ARRAY_{0}_COMPLETE)) & (_large_array_core == {1}) then".format(output_counter,core,size_counter) )
            target.write(newline)
            target.write( "   if LARGE_ARRAY_{0}_VARIABLE_SIZE == {2} then".format(output_counter,core,size_counter) )
            target.write(newline)
            target.write(read_function_prologue.format(output_counter,size_counter))
            if core == 14 :
                if size_counter == 1:
                    target.write( address_decode_14_1 )
                elif size_counter == 2:
                    target.write( address_decode_14_2 )
                elif size_counter == 4:
                    target.write( address_decode_14_4 )
            if core == 16 :
                if size_counter == 1:
                    target.write( address_decode_16_1 )
                elif size_counter == 2:
                    target.write( address_decode_16_2 )
                elif size_counter == 4:
                    target.write( address_decode_16_4 )
                    
                
            for variable_counter in range(1,int(max_bytes/chunk_size)+2):
                if variable_counter>1:
                    target.write("         els")
                else:
                    target.write("         ")
                target.write( "if LARGE_ARRAY_{0}_SIZE <= {1} then".format(output_counter,int(variable_counter*chunk_size/size_counter)) )
                target.write(newline)
                target.write( "            case section of")
                target.write(newline)
                
                for run_counter in range(variable_counter):
#                    target.write( "            {3:02d}:data = _large_array_{0}_{1}_{2:02d}[address_lo]".format(output_counter,size_counter,run_counter,variable_counter-run_counter-1))
#                    target.write( "            {3:02d}:return _large_array_{0}_{1}_{2:02d}[address_lo]".format(output_counter,size_counter,run_counter,variable_counter-run_counter-1))
                    target.write( "               {3:02d}:return _large_array_{0}_{1}_{2:02d}[address_lo]".format(output_counter,size_counter,variable_counter-run_counter-1,run_counter))
                    target.write(newline)
                target.write( "            end case" )
                target.write(newline)
    
            target.write("         end if")
            target.write(newline)
#            target.write("      return data")
#            target.write(newline)
            target.write("      end function")
            target.write(newline)
            target.write(write_procedure_prologue.format(output_counter,size_counter))
            if core == 14 :
                if size_counter == 1:
                    target.write( address_decode_14_1 )
                elif size_counter == 2:
                    target.write( address_decode_14_2 )
                elif size_counter == 4:
                    target.write( address_decode_14_4 )
            if core == 16 :
                if size_counter == 1:
                    target.write( address_decode_16_1 )
                elif size_counter == 2:
                    target.write( address_decode_16_2 )
                elif size_counter == 4:
                    target.write( address_decode_16_4 )
                    
                
            for variable_counter in range(1,int(max_bytes/chunk_size)+2):
                if variable_counter>1:
                    target.write("         els")
                else:
                    target.write("         ")
                target.write( "if LARGE_ARRAY_{0}_SIZE <= {1} then".format(output_counter,int(variable_counter*chunk_size/size_counter)) )
                target.write(newline)
                target.write( "            case section of")
                target.write(newline)
                
                for run_counter in range(variable_counter):
#                    target.write( "            {3:02d}: _large_array_{0}_{1}_{2:02d}[address_lo] = data".format(output_counter,size_counter,run_counter,variable_counter-run_counter-1))
                    target.write( "               {3:02d}: _large_array_{0}_{1}_{2:02d}[address_lo] = data".format(output_counter,size_counter,variable_counter-run_counter-1,run_counter))
                    target.write(newline)
                target.write( "            end case" )
                target.write(newline)
    
            target.write("         end if")
            target.write(newline)
            target.write("      end procedure")
            target.write(newline)
            target.write("      const _LARGE_ARRAY_{0}_COMPLETE = true".format(output_counter,core,size_counter) )
            target.write(newline)

            target.write("  end if")
            target.write(newline)
            target.write("end if")
            target.write(newline)

########################################################################################################################################
#####################################               MAIN PROGRAM               #########################################################
########################################################################################################################################

# Create the library file

target=open(main_output_file,'wt')

target.write(prologue.format(max_bytes_pic16,int(max_bytes_pic16/2),int(max_bytes_pic16/4),max_bytes_pic14,int(max_bytes_pic14/2),int(max_bytes_pic14/4),number_of_arrays ) ) 

target.write("-- Define all arrays that might be used, the compiler will eliminate unused arrays automatically.")
target.write(newline)
chunk_size=80
max_bytes=max_bytes_pic14
core=14
define_variables_per_core()

chunk_size=256
max_bytes=max_bytes_pic16
core=16
define_variables_per_core()

target.write(newline)
target.write( "-- Now define functions and procedures to read from and write to the sectional arrays.")
target.write(newline)

chunk_size=80
max_bytes=max_bytes_pic14
core=14
define_variable_access()

chunk_size=256
max_bytes=max_bytes_pic16
core=16
define_variable_access()

target.close()

# Create the compatibility files

for output_counter in range(1,number_of_arrays+1):
    target=open(compat_output_file.format(output_counter),'wt')
    target.write(compat_text.format(output_counter))
    target.close()
    
    

Reply via email to