Data relocation when using LOAD_L2=STANDALONE
#1
Hello,

as you know PULPissimo has an option to boot from flash by setting the LOAD_L2 parameter in the tb_pulp.sv to STANDALONE.
As far as I know it won't actually boot from flash but instead load the data from flash to the L2 and execute it. Is this still the case?

So I was running the hello example from the pulp_rt_examples using the STANDALONE variant.
This works just fine but I was wondering about the contents of the different memories after the end of the computation.

We can see that when using STANDALONE the flash memory uses its preload feature to contain "slm_files/flash_stim.slm" which should be the image of the hello example.
When instead using JTAG there is a different image loaded into L2 called stim.txt.

There are several question which I hope someone can answer:



Is there a reason why the actual data from those images is different?
I'm not talking about formatting but rather the actual data itself.
For example:

The first few lines of the .slm file:
@00000000 00
@00000001 70
@00000002 00
@00000003 00
@00000004 04
@00000005 00
@00000006 00
@00000007 00
@00000008 80
@00000009 80
@0000000A 00
@0000000B 1C

The first few lines of the .txt file:
1C000000_0000000000000000
1C000008_0000000000000000
1C000010_0000000000000000



I'm pretty sure that the memory called "boot rom" contains the boot code which is unrelated to the executed (hello example) code. Is this correct?
The code of the hello example should reside somewhere in L2. Now using QuestaSim to check the contents of the different L2 sections I get confused.
There is some data in .../bank_sram_pri0_i/MEM which looks a bit scattered as there are some undefined entries.
The data in .../bank_sram_pri1_i/MEM is more coherent.
Also there is a bit of data in every 0 cut of every CUT X.
By that i mean ...CUTS[X]/RTL_0/bank_i/cut_0/MEM.

What actually resides in pri0, pri1, cut_0?
I found the data of the stim.txt in L2 (in pri0 but not starting at 0x00000000) but not in a coherent way.
Why is this the case even tho I am using STANDALONE instead of JTAG.



In regards to my previous question there is also the boot-code repo which is what I am currently trying to extend.
If I'm not mistaken the boot_code.cde which I linked to in the above post is the binary of the boot_code.c found in this repo, is that correct?
Looking at the linker script link.ld we can see that there are only two entries in the memory table: ROM and L2.
How is data actually relocated from flash to L2? As far as I remember the flash is not memory mapped or is it?
I'm trying to modify the files in a way which allows me to load (preloaded) data from flash to defined addresses in L2, similar to how the (preloaded) hello example has to somehow be relocated.
Unfortunately I'm not allowed to modify boot_code.c so I'm guessing I have to modify the linker script link.ld and the main startup file crt0.S or add additional files.
Does anyone know if it is actually possible to load data from an arbitrary address in flash to an arbitrary address in L2 during boot phase?




Thank you,
LPLA
Reply
#2
(06-09-2020, 02:10 PM)LPLA Wrote: Hello,

as you know PULPissimo has an option to boot from flash by setting the LOAD_L2 parameter in the tb_pulp.sv to STANDALONE.
As far as I know it won't actually boot from flash but instead load the data from flash to the L2 and execute it. Is this still the case?

Bluewww:
It should work but I have recently got some feedback that it required manual changes. I'll try to get them upstream.

So I was running the hello example from the pulp_rt_examples using the STANDALONE variant.
This works just fine but I was wondering about the contents of the different memories after the end of the computation.

We can see that when using STANDALONE the flash memory uses its preload feature to contain "slm_files/flash_stim.slm" which should be the image of the hello example.
When instead using JTAG there is a different image loaded into L2 called stim.txt.

There are several question which I hope someone can answer:



Is there a reason why the actual data from those images is different?
I'm not talking about formatting but rather the actual data itself.
For example:

The first few lines of the .slm file:
@00000000 00
@00000001 70
@00000002 00
@00000003 00
@00000004 04
@00000005 00
@00000006 00
@00000007 00
@00000008 80
@00000009 80
@0000000A 00
@0000000B 1C

The first few lines of the .txt file:
1C000000_0000000000000000
1C000008_0000000000000000
1C000010_0000000000000000

Bluewww:
The images should contain the same data, but I haven't looked into it  in detail. The slm file is just a verilog memory dump that is read with $readmemh into the flash's internal memory (which is why the first address is 0) and then later read by the bootcode, while the .txt files contains the information the pulp tap is supposed to inject into the interconnect that is connected to the L2 (which is why it uses the L2 base address).




I'm pretty sure that the memory called "boot rom" contains the boot code which is unrelated to the executed (hello example) code. Is this correct?
Bluewww:
yes

The code of the hello example should reside somewhere in L2. Now using QuestaSim to check the contents of the different L2 sections I get confused.
There is some data in .../bank_sram_pri0_i/MEM which looks a bit scattered as there are some undefined entries.
The data in .../bank_sram_pri1_i/MEM is more coherent.
Also there is a bit of data in every 0 cut of every CUT X.
By that i mean ...CUTS[X]/RTL_0/bank_i/cut_0/MEM.

What actually resides in pri0, pri1, cut_0?
I struggled to find the data of either the flash_stim.slm or the stim.txt files anywhere in L2.

Bluewww:
The 0x1c00'0000 to 0x1c00'8000 is mapped to pri0 (32 KiB), 0x1c00'8000 to 0x1c01'0000 is mapped to pr1 (32 KiB), 0x1c01'0000 to 1c08'0000 (448 KiB) is mapped to CUTS[0]/.../bank_i/* to CUTS[3]/.../bank_i/* in an 4-byte(=word) interleaved manner, meaning the first word goes into bank 0, the next one into bank 1, the next one into bank 2 etc. Now furthemore each bank is split into 7 consecutive cuts (cut_0 to cut_6) where each cut is 16 KiB. The way the memory instances were named is not ideal.



In regards to my previous question there is also the boot-code repo which is what I am currently trying to extend.
If I'm not mistaken the boot_code.cde which I linked to in the above post is the binary of the boot_code.c found in this repo, is that correct?

Bluewww:
yes, though it is possible that the .cde is outdated since it has been a while we imported the last version

Looking at the linker script link.ld we can see that there are only two entries in the memory table: ROM and L2.
How is data actually relocated from flash to L2? As far as I remember the flash is not memory mapped or is it?

Bluewww:
boot_code.c contains a routine that configures the udma to load data from the flash over qspi into the L2. This should happen when you set the STANDALONE flag im the testbench.

I'm trying to modify the files in a way which allows me to load (preloaded) data from flash to defined addresses in L2, similar to how the (preloaded) hello example has to somehow be relocated.
Unfortunately I'm not allowed to modify boot_code.c so I'm guessing I have to modify the linker script link.ld and the main startup file crt0.S or add additional files.
Does anyone know if it is actually possible to load data from an arbitrary address in flash to an arbitrary address in L2 during boot phase?

Bluewww:
You would have to study boot_code.c to see if it provides that capability, but I don't think so. What is possible though is that you have a shim binary that gets loaded into L2 and executed, which contains code to load the rest of the data you want from any flash address to any l2 address.



Thank you,
LPLA
Reply
#3
Sorry for the late answer but I have been watching some tutorials and experimenting a bit.

First of all, thank you for the information.
To give a little update on my current state:

I am working with the files found in the boot code repo.
First thing I did was create a file called my_test_data.c which only contains data (integer, array, etc.) to see if I can relocate them during booting.

Let us look at the two interesting arrays:
1) int normal_arr[] = {0x55555555, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0x55555555, 0x55555555};
2) int attribute_arr[] __attribute__ ((section(".my_test_section"))) = {0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666, 0x66666666};

The idea is to later on have my additional data in seperate files each with its own attribute.

Then I modified the linker script by adding this line in the MEMORY section:
CUT01       : ORIGIN = 0x1C020000, LENGTH = 0x1000

I also added to the SECTION section: (more than necessary but I wanted to make sure)
    .my_test_section :
    {
        . = ALIGN(4);
        KEEP(*(.my_test_section))
        _mts_start = .;
        *(.text.*)
        *(.text)
        *(.data.*)
        *(.data)
        *(.comment)
        *(.comment.*)
        *(.my_test_section)
        *(.my_test_section*)
        *(.my_test_section.*)
        *(.attribute_arr)
        *(.attribute_arr*)
        *(.attribute_arr.*)
        . = ALIGN(4);
        _mts_end = .;
    } > CUT01

I also created the map file to get a better understanding of what happens with the data in my_test_data.c (or rather the output file that gets generated from it).
Regarding the two arrays I can see them in the map file:

The normal_arr:
 .data.normal_arr
                0x000000001a000450       0x20 /.../bootloader/fc/my_test_data.o
                0x000000001a000450                normal_arr

The attribute_arr:
 .my_test_section
                0x000000001c020000       0x20 /.../bootloader/fc/my_test_data.o
                0x000000001c020000                attribute_arr

Now as you can see both of them are 36 Bytes which seems to be correct as both arrays are 8 integer.
But for some reason the attribute_arr doesn't end up in L2 at the address I specified (or anywhere else for that matter) but the normal_arr resides in ROM (which makes sense as it's part of the .data section).
I thought that adding the appropriate entries in the linker script and creating data with the section attribute should be enough but somewhere along the line it seems like I have made a mistake or several mistakes.
Maybe someone has done something similar and wants to share their knowledge?

Thank you,
LPLA
Reply
#4
The range from 0x1A00_0000 to 0x1A00_2000 is mapped to the boot rom.
https://github.com/pulp-platform/pulpiss...asheet.pdf

You can't put in anything outside that range, It will be invisible or just not work.
Reply
#5
(06-29-2020, 12:25 PM)bluewww Wrote: The range from 0x1A00_0000 to 0x1A00_2000 is mapped to the boot rom.
https://github.com/pulp-platform/pulpiss...asheet.pdf

You can't put in anything outside that range, It will be invisible or just not work.

If I take a look at the linker (link.ld) inside the boot code repo I can see that there are two memory regions available for allocation.
First one is ROM with origin 0x1A000000 and second one is L2 with origin 0x1C000000.
This is in line with the memory map from the datasheet you linked.
Also the SECTIONS show that the linker already puts data into L2, not only in ROM.

Code:
    .heapl2ram :
    {
       *(.ram)
       *(.heapl2ram)
    } > L2

    .stack :
    {
       . = ALIGN(4);
      stack = . + 1024;
    } > L2



I have to admit that I'm not sure what kind of data is moved to L2 as the data inside the pri0 bank (0x1c00'0000 to 0x1c00'8000) seems to be randomly distributed with gaps between the entries. The data inside the pri1 bank (0x1c00'8000 to 0x1c01'0000) on the other hand is coherent without any gaps between data.
There are also a few entries starting at 0x1c01'0000. Could you please go into detail a bit more when you say that it's not possible to put anything outside the range of the boot rom (0x1a000000 to 0x1a002000)? Maybe I'm totally missing something but to me it seems like it is possible and it's already being done.


Thank you.
Reply


Forum Jump: