diff --git a/.gitignore b/.gitignore index 97c7a5d..6194437 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,4 @@ release/ *.zip Documentation/html output/ - +*.bat diff --git a/Documentation/Doxygen/src/images/board_test.png b/Documentation/Doxygen/src/images/board_test.png new file mode 100644 index 0000000..a38d16d Binary files /dev/null and b/Documentation/Doxygen/src/images/board_test.png differ diff --git a/Source/gaussian.c b/Source/gaussian.c index dc24af7..4f93e4b 100644 --- a/Source/gaussian.c +++ b/Source/gaussian.c @@ -26,10 +26,11 @@ #include "cv/linear_filters.h" #include "dsp/basic_math_functions.h" -static const q15_t grad[9] = { 0x0800, 0x1000, 0x0800, - 0x1000, 0x2000, 0x1000, - 0x0800, 0x1000, 0x0800 - }; +static const q15_t gaussian_kernel[9] = { 0x0800, 0x1000, 0x0800, + 0x1000, 0x2000, 0x1000, + 0x0800, 0x1000, 0x0800 + }; + /** @@ -56,7 +57,7 @@ void arm_gaussian_filter_3x3_fixp(const arm_cv_image_gray8_t* ImageIn, q63_t res; q15_t matrix_in[9] = { ImageIn->pData[indice-w-1], ImageIn->pData[indice-w], ImageIn->pData[indice-w+1], ImageIn->pData[indice - 1], ImageIn->pData[indice], ImageIn->pData[indice + 1], ImageIn->pData[indice +w -1], ImageIn->pData[ indice + w], ImageIn->pData[indice + w+1]}; //this dot product output on 34.30, so a shift of 15 is enought to bring us back into q15 but because we didn't convert our input Image previously, we have to do a shift to the left by 7, this is possible due to the increase of precisionn of the multiplication/dotproduct, so we only need a shif of 15-7 8 - arm_dot_prod_q15(&grad[0], &matrix_in[0], 9, &res); + arm_dot_prod_q15(&gaussian_kernel[0], &matrix_in[0], 9, &res); res = res>>8; ImageOut->pData[indice] =(q15_t)(res); } @@ -72,7 +73,9 @@ void arm_gaussian_filter_3x3_fixp(const arm_cv_image_gray8_t* ImageIn, int x = 0; int y = 0; - for( int y =0; y < ImageIn->height; y++) + + + for( int y = 0; y < ImageIn->height; y++) { ImageOut->pData[y*ImageOut->width +x] = ImageIn->pData[y*ImageOut->width +x] <<7; } diff --git a/Testing/board/.gitignore b/Testing/board/.gitignore new file mode 100644 index 0000000..8c2de4f --- /dev/null +++ b/Testing/board/.gitignore @@ -0,0 +1,9 @@ +results/ +references/ +inputs/ +RTE/ +cprj/ +*cbuild-pack.yml +disasm.s +test.dat +summary.html diff --git a/Testing/board/Patterns/Girl3.tiff b/Testing/board/Patterns/Girl3.tiff new file mode 100644 index 0000000..3609c77 Binary files /dev/null and b/Testing/board/Patterns/Girl3.tiff differ diff --git a/Testing/board/Patterns/Gray21.tiff b/Testing/board/Patterns/Gray21.tiff new file mode 100644 index 0000000..05219c6 Binary files /dev/null and b/Testing/board/Patterns/Gray21.tiff differ diff --git a/Testing/board/Patterns/House.tiff b/Testing/board/Patterns/House.tiff new file mode 100644 index 0000000..a5badd6 Binary files /dev/null and b/Testing/board/Patterns/House.tiff differ diff --git a/Testing/board/Patterns/House2.tiff b/Testing/board/Patterns/House2.tiff new file mode 100644 index 0000000..af54a7b Binary files /dev/null and b/Testing/board/Patterns/House2.tiff differ diff --git a/Testing/board/Patterns/JellyBeans.tiff b/Testing/board/Patterns/JellyBeans.tiff new file mode 100644 index 0000000..dd35fb6 Binary files /dev/null and b/Testing/board/Patterns/JellyBeans.tiff differ diff --git a/Testing/board/Patterns/JellyBeans2.tiff b/Testing/board/Patterns/JellyBeans2.tiff new file mode 100644 index 0000000..31be820 Binary files /dev/null and b/Testing/board/Patterns/JellyBeans2.tiff differ diff --git a/Testing/board/Patterns/Mandrill.tiff b/Testing/board/Patterns/Mandrill.tiff new file mode 100644 index 0000000..7b2c649 Binary files /dev/null and b/Testing/board/Patterns/Mandrill.tiff differ diff --git a/Testing/board/Patterns/Mandrill_cropped.tiff b/Testing/board/Patterns/Mandrill_cropped.tiff new file mode 100644 index 0000000..7a7fdf5 Binary files /dev/null and b/Testing/board/Patterns/Mandrill_cropped.tiff differ diff --git a/Testing/board/Patterns/Moon.tiff b/Testing/board/Patterns/Moon.tiff new file mode 100644 index 0000000..3f8d972 Binary files /dev/null and b/Testing/board/Patterns/Moon.tiff differ diff --git a/Testing/board/Patterns/Peppers.tiff b/Testing/board/Patterns/Peppers.tiff new file mode 100644 index 0000000..d9bd156 Binary files /dev/null and b/Testing/board/Patterns/Peppers.tiff differ diff --git a/Testing/board/Patterns/ResolutionChart.tiff b/Testing/board/Patterns/ResolutionChart.tiff new file mode 100644 index 0000000..be91fd1 Binary files /dev/null and b/Testing/board/Patterns/ResolutionChart.tiff differ diff --git a/Testing/board/Patterns/Ruler.tiff b/Testing/board/Patterns/Ruler.tiff new file mode 100644 index 0000000..e8d28a0 Binary files /dev/null and b/Testing/board/Patterns/Ruler.tiff differ diff --git a/Testing/board/README.md b/Testing/board/README.md new file mode 100644 index 0000000..0b5e062 --- /dev/null +++ b/Testing/board/README.md @@ -0,0 +1,328 @@ +# README + +## Introduction + +The goal of the test framework included in this folder is to run regression of all the CMSIS-CV kernels with different cores (M4, M55) and different compilers (AC6,GCC) on FVP. clang not yet supported because of issues with semi-hosting in input mode (issues that may not be clang related). + +The framework is relying on the CMSIS build tools for building with different compilers. + +To run a regression for the first time: + +```shell +python runall.py --gen +``` + +The summary is generated in `summary.html` and will list all errors if any (build error, test failure ...) + +The live status will display the last failing groups: + +![board_test](../../Documentation/Doxygen/src/images/board_test.png) + +### Option details + +#### `-avh` AVH folder + +Where to find the FVP executable. By default it is the uVision folder on Windows. + +#### `-d` Debug log for command launch + +Display commands that are executed to debug potential problems (FVP not launched etc ...) + +#### `-n` No force rebuild + +First build of a group will fully rebuild (regenerate cmake) and regenerate RTE. + +It is important when the build is switching between compilers of targets. + +If you debug and test only with one compiler / target, you may want to disable it to have faster rebuild. + +#### `--gen` Generate inputs and references + +First time there are no input images or reference patterns. They need to be generated. + +#### `--results` Generate test result images + +Results (in .dat file) may be converted to images or `.npy` files and recorded in specific folders. It can be useful for debug. Otherwise, the system is just validating the test but not recording the result. + +#### `--dev` Kernel development mode + +In development mode, only the development kernel is used. + +#### `--norun` Don't run the FVP + +Don't run. Can be useful to generate an `.axf` or `.elf` and the corresponding input file and then use this without this test script to debug. + +Once it is done, it is possible to rebuild this `.axf`/`.elf` using `cbuild` without having to re-run this script. + +Useful for preparing an executable for debug or to run on board. + +#### `--group` Select a test group + +Only build / run the specified test group + +#### `--test` Select a specific test + +Only the selected test in the selected group will be run. + +Useful for debug when you want to rebuild/rerun only a specific test. + +### Customizing `runall.py` compiler and targets + +`configFiles` variable is describing the config files required to run each FVP. + +`avhExe` name of the executable to run for each FVP (windows name. You need to change it to run on Linux) + +`compiler` : Structure describing the compiler / target configuration that must be built / run. + +Note that for `gcc` the link script for M4 and M7 have not yet been updated + +## Test descriptions + +### The file `test_dec.py` + +#### `allSuites` : Descriptions of all the tests + +This is a list of test group. Each list item describe a test group and a list of tests in this group. + +The test group is defined with + +```python + "name" : "Linear Filters", + "define": "TESTGROUP1", + "inputs": [Image([(16,16) + ,(32,32)], + format=Format.GRAY8, + path="Patterns/Mandrill.tiff"), + Image([(16,16) + ,(32,32)], + format=Format.RGB, + path="Patterns/Mandrill.tiff")], + "tests":[] +``` + +`name` : name used in the test report to display the status + +`define` : Compilation define used to compile only a specific test group + +`inputs` : Set of images available to all of the test of this test group. + +`tests`: List of tests in this test group. + +Each test in this list has format: + +```python +{"desc":"Copy gray8 image 16x16", +"funcid": 1, +"useimg": [0], +"reference": CopyInput(), +"check" : IdenticalImage() +} +``` + +`desc` : Title for test report + +`funcid`: Function to run for this test. (Starting at ID = 0 in the test group) + +`useimg` : Images used as input of this test. The index (starting at zero) are indexes in the image set for the test group containing this test. It is only used on the Python side to be bale to compute if the test has passed or failed. The Python needs the test input to generate the reference test patterns. + +`reference`: Python object used to generate the reference pattern for this test. When it is called, it will receive all image inputs. + +`check`: Python object used to validate if the test has passed or not. When it is called it receive the reference and output images for the test + +#### `devTest` : Description of development + +When you develop a new test, you can use the test mode where a shorter description can be used: + +```python +devTest = { + "inputs": [Image([(16,16)], + format=Format.GRAY8, + path="Patterns/Mandrill.tiff")], + "reference": CopyInput(), + "check" : IdenticalImage() +} +``` + + + +### Test input generation + +The `inputs` field receive Python object that knows how to generate a list of image or tensors. Those list are then concatenate din the to make the final set of images for the test group. + +#### Image + +```Python +def __init__(self,dims,format=Format.GRAY8,path=None): +``` + +It is an image generators that can generate several sized images from an image on disk. + +`dims` is a list of dimensions. + +For instance, + +``` python +Image([(16,16) + ,(32,32)], + format=Format.GRAY8, + path="Patterns/Mandrill.tiff") +``` + +The `Image`object generates two images of size (16,16) and (32,32) in gray. The images are resized from the pattern image `Mandrill.tiff`. + +In case the format is neither `gray8` or `rgb888` then the image has to be exported as a general NumPy tensor using `GenTensor` + +```python +def __init__(self,a,b,c,the_type) +``` + + + +The 3 dimensions are passed followed by the NumPy type. + +The framework support tensors of 1 to 4 dimensions but as an example we only provided a Python class to generate tensors of 3 dimensions. It should not be difficult to build variant of this class. + +### Reference pattern generation + +When input images have been generated, reference patterns must be generated : the output of the test. + +In the example we only provided an object that is making a copy of the list of input (the list of input to the test that is different from the list of images in the test group. Most often this list of images will contain only one image.) + +```python +def __call__(self,args,group_id,test_id,srcs): +``` + +The reference object is called to generate reference patterns. The arguments of the call are: + +`args` : argument passed to the script + +`group_id` being run + +`test_id` being run + +`srcs` : List of input images + +`args`,`group_id` and `test_id` are used to record the reference image on disk. + +For instance, the function is using: + +```python +for image_id,img in enumerate(srcs): + record_reference_img(args,group_id,test_id,image_id,img) +``` + +Generally when you create a reference image, you need to use this record_reference_omg to record thr image. + +You need an `image_id` and an `img` argument. + +Import and export is done thought the class `AlgoImage` defined in `export.py` + +This class can either contain a `Pillow` image or a Numpy tensor. It is the class you get when reading a reference or input image from disk or when you save an image / tensor to disk or when you create an input image or tensor. + +### Test validation + +The validation function is called with: + +```python +def __call__(self,ref,result): +``` + +It receives a list of inputs and a list of references. + +The images are of `AlgoImage` type. + +Two examples are provided: + +`IdenticalTensor` and `IdenticalImage` + +## Writing a test group in C + +A test group is implemented as a switch case to run different function depending on the function id: + +```CPP +void run_test(const unsigned char* inputs, + const uint32_t testid, + const uint32_t funcid, + unsigned char* &wbuf, + uint32_t &total_bytes) +{ + + wbuf = nullptr; + switch(funcid) + { + case 0: + test_rgb(inputs,wbuf,total_bytes,testid); + break; + case 1: + test_gray8(inputs,wbuf,total_bytes,testid); + break; + } + +} +``` + +`wbuf` is the write buffer where the set of output images for this test is written. + +Each test is receiving the `testid` that can be used to identify what are the images from the imageset to use as input of the test., + +Let's look at `test_gray8` to understand the details: + +```CPP +void test_gray8(const unsigned char* inputs, + unsigned char* &outputs, + uint32_t &total_bytes, + uint32_t testid) +{ + uint32_t nb_dims,dim0,dim1,dim2,dim3;; + int bufid = TENSOR_START + 0; + if (testid == 1) + bufid = TENSOR_START + 1 ; +``` + +`inputs` is the set of images available to the tests. Each buffer in this set can be accessed through the APIs provided by `common.h` and `load.hpp`. + +`outputs` and `total_bytes` are used to return the set of output images. + +In the input set, some buffers are used for the test description. The images and tensors that can be used for the tests only start at `TENSOR_START`. + +According to the `testid`, the test is defining which image to use in the input test set. + +Then we get the tensor dimensions of the input tensor: + +```CPP +get_buffer_shape(inputs,bufid,&nb_dims,&dim0,&dim1,&dim2,&dim3); +``` + +If the input tensor is an image, there is an API to get the width and height. + +Then we describe the format of images and tensors in the output of this tests (the output is a set of images / tensors) + +```CPP +std::vector desc = {BufferDescription(Shape(dim0,dim1) + ,kIMG_GRAY8_TYPE) + }; +``` + +In this example, we define an output image (two dimensions) with same width and height as input and using gray8. + +Note that `dim0`, `dim1`, `dim2` would generally correspond to `height`, `width`,`channels` ... + +Once the output has been described, we create a buffer for the output set: + +```CPP +outputs = create_write_buffer(desc,total_bytes); +``` + +Now we access the input image in the input set and the output image in the output set: + +```CPP +const uint8_t *src = Buffer::read(inputs,bufid); +uint8_t *dst = Buffer::write(outputs,0); +``` + +We finally copy the input onto the output: + +```CPP + memcpy(dst,src,get_buffer_length(inputs,bufid)); +``` + diff --git a/Testing/board/cdefault.yml b/Testing/board/cdefault.yml new file mode 100644 index 0000000..b0502ee --- /dev/null +++ b/Testing/board/cdefault.yml @@ -0,0 +1,151 @@ +default: + + compiler: AC6 + + misc: + - for-compiler: AC6 + C: + - -Wsign-compare + - -Wdouble-promotion + - -DNDEBUG + - -Wall + - -Wextra + - -Werror + - -std=c11 + - -Ofast + - -ffast-math + - -Wno-packed + - -Wno-missing-variable-declarations + - -Wno-missing-prototypes + - -Wno-missing-noreturn + - -Wno-sign-conversion + - -Wno-nonportable-include-path + - -Wno-reserved-id-macro + - -Wno-unused-macros + - -Wno-documentation-unknown-command + - -Wno-documentation + - -Wno-license-management + - -Wno-parentheses-equality + - -Wno-reserved-identifier + - -ffunction-sections + - -Wno-nan-infinity-disabled + - -DARM_MATH_LOOPUNROLL + - -g + CPP: + - -fno-rtti + - -fno-exceptions + - -DNDEBUG + - -Wall + - -Wextra + - -std=c++17 + - -Ofast + - -ffast-math + - -Wno-unused-function + - -ffunction-sections + - -mllvm -disable-vector-combine + - -g + ASM: + - -masm=auto + Link: + - --entry=Reset_Handler + - --info=summarysizes + - --info=sizes + - --info=totals + - --info=unused + - --info=veneers + + - for-compiler: GCC + C: + - -Wsign-compare + - -Wdouble-promotion + - -DNDEBUG + - -Wall + - -Wextra + - -Werror + - -std=c11 + - -Ofast + - -ffast-math + - -Wno-packed + - -Wno-missing-prototypes + - -Wno-missing-noreturn + - -Wno-sign-conversion + - -Wno-unused-macros + - -ffunction-sections + - -DARM_MATH_LOOPUNROLL + - -flax-vector-conversions + - -Wno-maybe-uninitialized + - -fdata-sections + - -fno-unroll-loops + CPP: + - -fno-rtti + - -fno-exceptions + - -DNDEBUG + - -Wall + - -Wextra + - -std=c++17 + - -Ofast + - -ffast-math + - -Wno-unused-function + - -ffunction-sections + - -fdata-sections + - -Wno-psabi + - -fno-unroll-loops + - -flax-vector-conversions + ASM: + - -masm=auto + Link: + - --specs=nano.specs + - -Wl,-Map=$elf()$.map + - -lm + - -Wl,--wrap=SysTick_Handler + - -Wl,--gc-sections + Library: + - -lm + + - for-compiler: CLANG + C: + - -Wsign-compare + - -Wdouble-promotion + - -DNDEBUG + - -Wall + - -Wextra + - -Werror + - -std=c11 + - -Ofast + - -ffast-math + - -Wno-packed + - -Wno-missing-variable-declarations + - -Wno-missing-prototypes + - -Wno-missing-noreturn + - -Wno-sign-conversion + - -Wno-nonportable-include-path + - -Wno-reserved-id-macro + - -Wno-unused-macros + - -Wno-documentation-unknown-command + - -Wno-documentation + - -Wno-parentheses-equality + - -Wno-reserved-identifier + - -ffunction-sections + - -DARM_MATH_LOOPUNROLL + - -Wno-nan-infinity-disabled + - -DCINPUT # because of issue with semihosting + - -DNOOUTPUT # because of issue with semihosting + CPP: + - -fno-rtti + - -fno-exceptions + - -DNDEBUG + - -Wall + - -Wextra + - -std=c++17 + - -Ofast + - -ffast-math + - -Wno-unused-function + - -ffunction-sections + - -Wno-nan-infinity-disabled + - -DCINPUT # because of issue with semihosting + - -DNOOUTPUT # because of issue with semihosting + ASM: + - -masm=auto + Link: + - -Wl,-Map=$elf()$.map + - -Wl,--gc-sections diff --git a/Testing/board/cinput.c b/Testing/board/cinput.c new file mode 100644 index 0000000..d51951e --- /dev/null +++ b/Testing/board/cinput.c @@ -0,0 +1,184 @@ +#include "cinput.h" +#include "arm_math_types.h" + +#ifndef ALIGN_NETWORK +#define ALIGN_NETWORK __ALIGNED(16) +#endif + +#if defined(CINPUT) + +ALIGN_NETWORK +const uint8_t cinput[NB_CINPUT]={0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00, +0x00,0x00,0x40,0x06,0x00,0x00,0x01,0x00,0x00,0x00, +0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, +0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00, +0x14,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x04,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x68,0x00, +0x00,0x00,0x70,0x00,0x00,0x00,0x78,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00, +}; +#endif diff --git a/Testing/board/cinput.h b/Testing/board/cinput.h new file mode 100644 index 0000000..f775357 --- /dev/null +++ b/Testing/board/cinput.h @@ -0,0 +1,22 @@ +#ifndef CINPUT_H +#define CINPUT_H + +#include "arm_math_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if defined(CINPUT) + +#define NB_CINPUT 1720 +extern const uint8_t cinput[NB_CINPUT]; + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Testing/board/clang_sse300.c b/Testing/board/clang_sse300.c new file mode 100644 index 0000000..c647090 --- /dev/null +++ b/Testing/board/clang_sse300.c @@ -0,0 +1,65 @@ +#include "RTE_Components.h" +#include + +#include "Driver_USART.h" +#include "stdout_USART.h" + + + + +static int stdin_getc(FILE *file) { + (void)file; + return(0); +} + + +// iostream has references to stdin and stderr and there is a link +// error if not defined. +static FILE __stdin = FDEV_SETUP_STREAM(NULL, + stdin_getc, + NULL, + _FDEV_SETUP_READ); +FILE *const stdin = &__stdin; + +static int stderr_putc(char c, FILE *file) { + (void)file; + return(0); +} + +static FILE __stderr = FDEV_SETUP_STREAM(stderr_putc, + NULL, + NULL, + _FDEV_SETUP_WRITE); +FILE *const stderr = &__stderr; + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- + +// STDOUT USART Interface + +// Connect to hardware via Driver_USART# <0-255> +// Select driver control block for USART interface +#define USART_DRV_NUM 0 + +// Baudrate +#define USART_BAUDRATE 115200 + +// + + +#define _USART_Driver_(n) Driver_USART##n +#define USART_Driver_(n) _USART_Driver_(n) + +extern ARM_DRIVER_USART USART_Driver_(USART_DRV_NUM); +#define ptrUSART (&USART_Driver_(USART_DRV_NUM)) + +int stdout_putchar(const unsigned char ch) { + uint8_t buf[1]; + + buf[0] = ch; + if (ptrUSART->Send(buf, 1) != ARM_DRIVER_OK) { + return (-1); + } + while (ptrUSART->GetTxCount() != 1); + return (ch); +} + diff --git a/Testing/board/cmsiscv.cproject.yml b/Testing/board/cmsiscv.cproject.yml new file mode 100644 index 0000000..b0e83d7 --- /dev/null +++ b/Testing/board/cmsiscv.cproject.yml @@ -0,0 +1,133 @@ +project: + groups: + - group: cmsiscv + files: + - file: ../../Source/cannysobel.c + - file: ../../Source/gaussian.c + - group: Tests + files: + - file: src/common.c + - file: src/load.cpp + - file: cinput.c + - file: tests/test_group1.cpp + - file: tests/test_group2.cpp + - file: tests/test_dev.cpp + - file: clang_sse300.c + for-context: + - +MPS3-Corstone-300 + for-compiler: + - CLANG + - group: App + files: + - file: main.cpp + add-path: + - ../../Include + - src + - . + + components: + - component: ARM::CMSIS:CORE + - component: ARM::CMSIS:DSP@1.15.0 + - component: ARM::Device:Startup&C Startup + for-context: + - +VHT-Corstone-300 + - +VHT-M0P + - +VHT-M4 + - +VHT-M7 + - +MPS3-Corstone-300 + - component: ARM::Device:Definition + for-context: + - +VHT-Corstone-300 + - +MPS3-Corstone-300 + - component: CMSIS-Compiler:CORE + for-context: + - +MPS3-Corstone-300 + - component: CMSIS-Compiler:STDOUT:Custom@1.0.0 + for-context: + - +MPS3-Corstone-300 + - component: ARM::Device:USART STDOUT + for-context: + - +MPS3-Corstone-300 + - component: ARM::CMSIS Driver:USART + for-context: + - +MPS3-Corstone-300 + - component: ARM::Device:Native Driver:SysCounter + for-context: + - +VHT-Corstone-300 + - +MPS3-Corstone-300 + - component: ARM::Device:Native Driver:SysTimer + for-context: + - +VHT-Corstone-300 + - +MPS3-Corstone-300 + - component: ARM::Device:Native Driver:Timeout + for-context: + - +VHT-Corstone-300 + - +MPS3-Corstone-300 + - component: ARM::Device:Native Driver:UART + for-context: + - +MPS3-Corstone-300 + + linker: + - script: linker_scripts/gcc_sse300_mps3.ld + for-context: + - +MPS3-Corstone-300 + - +VHT-Corstone-300 + for-compiler: GCC + + - script: linker_scripts/clang_sse300_mps3.sct + for-context: + - +MPS3-Corstone-300 + - +VHT-Corstone-300 + for-compiler: CLANG + + - script: linker_scripts/ac6_sse300_mps3_s.sct + for-context: + - +MPS3-Corstone-300 + - +VHT-Corstone-300 + for-compiler: AC6 + + - regions: linker_scripts/SSE-300-MPS3/region_defs.h + for-context: + - +MPS3-Corstone-300 + - +VHT-Corstone-300 + + - script: linker_scripts/gcc_m0p_mps3.ld + for-context: + - +VHT-M0P + for-compiler: GCC + + - script: linker_scripts/clang_m0p_mps3.ld + for-context: + - +VHT-M0P + for-compiler: CLANG + + - script: linker_scripts/ac6_m0p_mps3_s.sct + for-context: + - +VHT-M0P + for-compiler: AC6 + + - regions: linker_scripts/ARMCM0P/region_defs.h + for-context: + - +VHT-M0P + + + - script: linker_scripts/ac6_m4_mps3_s.sct + for-context: + - +VHT-M4 + for-compiler: AC6 + + - regions: linker_scripts/ARMCM4/region_defs.h + for-context: + - +VHT-M4 + + + - script: linker_scripts/ac6_m7_mps3_s.sct + for-context: + - +VHT-M7 + for-compiler: AC6 + + - regions: linker_scripts/ARMCM7/region_defs.h + for-context: + - +VHT-M7 + + diff --git a/Testing/board/cmsiscv.csolution.yml b/Testing/board/cmsiscv.csolution.yml new file mode 100644 index 0000000..ab39d55 --- /dev/null +++ b/Testing/board/cmsiscv.csolution.yml @@ -0,0 +1,127 @@ +solution: + compiler: AC6@6.22.0 + + language-C: c11 + language-CPP: c++17 + cdefault: + + packs: + - pack: ARM::CMSIS@6.0.0 + - pack: ARM::CMSIS-DSP@1.15.0 + - pack: ARM::V2M_MPS3_SSE_300_BSP@1.4.0 + - pack: ARM::CMSIS-Compiler@2.0.0 + - pack: ARM::Cortex_DFP@1.0.0 + + target-types: + - type: MPS3-Corstone-300 + device: ARM::SSE-300-MPS3 + board: ARM::V2M-MPS3-SSE-300-FVP + define: + - CORTEXM + - SSE300MPS3 + - MPS3 + - ARMCM55 + - CINPUT + - NOOUTPUT + - HASCACHE + misc: + - for-compiler: GCC + C: + - -Wno-sign-compare + - -Wno-unused-parameter + CPP: + - -Wno-sign-compare + - -Wno-unused-parameter + Link: + - --specs=nosys.specs + - for-compiler: CLANG + C: + - -Wno-sign-compare + - -Wno-unused-parameter + CPP: + - -Wno-sign-compare + - -Wno-unused-parameter + Link: + - -lcrt0 + + - type: VHT-Corstone-300 + device: ARM::SSE-300-MPS3 + board: ARM::V2M-MPS3-SSE-300-FVP + define: + - CORTEXM + - ARMCM55 + - FVP + misc: + - for-compiler: GCC + Link: + - --specs=rdimon.specs + Library: + - -lrdimon + - for-compiler: CLANG + Link: + - -lcrt0-semihost + - -lsemihost + + - type: VHT-M0P + device: ARMCM0P + define: + - CORTEXM + - ARMCM0P + - DISABLEFLOAT16 + - FVP + misc: + - for-compiler: GCC + Link: + - --specs=rdimon.specs + Library: + - -lrdimon + - for-compiler: CLANG + Link: + - -lcrt0-semihost + - -lsemihost + + - type: VHT-M4 + device: ARMCM4 + define: + - CORTEXM + - ARMCM4_FP + - DISABLEFLOAT16 + - FVP + misc: + - for-compiler: GCC + Link: + - --specs=rdimon.specs + Library: + - -lrdimon + - for-compiler: CLANG + Link: + - -lcrt0-semihost + - -lsemihost + + - type: VHT-M7 + device: ARMCM7 + define: + - CORTEXM + - ARMCM7_DP + - DISABLEFLOAT16 + - FVP + - HASCACHE + misc: + - for-compiler: GCC + Link: + - --specs=rdimon.specs + Library: + - -lrdimon + - for-compiler: CLANG + Link: + - -lcrt0-semihost + - -lsemihost + + build-types: + - type: Release + debug: on + + + projects: + - project: ./cmsiscv.cproject.yml + \ No newline at end of file diff --git a/Testing/board/debug.py b/Testing/board/debug.py new file mode 100644 index 0000000..c01ad61 --- /dev/null +++ b/Testing/board/debug.py @@ -0,0 +1,7 @@ +from scripts.export import * + +with open("results/output_0.dat","rb") as f: + r = read_tensors(f) + +for i in r: + print(i.tensor) \ No newline at end of file diff --git a/Testing/board/fvp_configs/VHT-Corstone-300.txt b/Testing/board/fvp_configs/VHT-Corstone-300.txt new file mode 100644 index 0000000..e352bec --- /dev/null +++ b/Testing/board/fvp_configs/VHT-Corstone-300.txt @@ -0,0 +1,9 @@ +core_clk.mul=100000000 +cpu0.semihosting-enable=1 +cpu0.semihosting-heap_base=0x0 +cpu0.semihosting-heap_limit=0x0 +cpu0.semihosting-stack_base=0x0 +cpu0.semihosting-stack_limit=0x0 +cpu0.FPU=1 +cpu0.MVE=2 +mps3_board.visualisation.disable-visualisation=1 diff --git a/Testing/board/fvp_configs/VHT-M0P.txt b/Testing/board/fvp_configs/VHT-M0P.txt new file mode 100644 index 0000000..4892c1e --- /dev/null +++ b/Testing/board/fvp_configs/VHT-M0P.txt @@ -0,0 +1,3 @@ +fvp_mps2.mps2_visualisation.disable-visualisation=1 +armcortexm0plusct.semihosting-enable=1 +armcortexm0plusct.NUM_MPU_REGION=0x8 diff --git a/Testing/board/fvp_configs/VHT-M4.txt b/Testing/board/fvp_configs/VHT-M4.txt new file mode 100644 index 0000000..fda8c02 --- /dev/null +++ b/Testing/board/fvp_configs/VHT-M4.txt @@ -0,0 +1,3 @@ +fvp_mps2.mps2_visualisation.disable-visualisation=1 +armcortexm4ct.semihosting-enable=1 +armcortexm4ct.vfp-present=1 diff --git a/Testing/board/fvp_configs/VHT-M7DP.txt b/Testing/board/fvp_configs/VHT-M7DP.txt new file mode 100644 index 0000000..acc5fac --- /dev/null +++ b/Testing/board/fvp_configs/VHT-M7DP.txt @@ -0,0 +1,15 @@ +# Parameters: +# instance.parameter=value #(type, mode) default = 'def value' : description : [min..max] +#---------------------------------------------------------------------------------------------- +fvp_mps2.mps2_visualisation.disable-visualisation=1 # (bool , init-time) default = '0' : Enable/disable visualisation +armcortexm7ct.vfp-present=1 # (bool , init-time) default = '1' : Set whether the model has VFP support +armcortexm7ct.semihosting-enable=1 # (bool , init-time) default = '1' : Enable semihosting SVC traps. Applications that do not use semihosting must set this parameter to false. +armcortexm7ct.semihosting-Thumb_SVC=0xAB # (int , init-time) default = '0xAB' : T32 SVC number for semihosting : [0x0..0xFF] +armcortexm7ct.semihosting-cmd_line="" # (string, init-time) default = '' : Command line available to semihosting SVC calls +armcortexm7ct.semihosting-heap_base=0x0 # (int , init-time) default = '0x0' : Virtual address of heap base : [0x0..0xFFFFFFFF] +armcortexm7ct.semihosting-heap_limit=0 # (int , init-time) default = '0x10700000' : Virtual address of top of heap : [0x0..0xFFFFFFFF] +armcortexm7ct.semihosting-stack_base=0 # (int , init-time) default = '0x10700000' : Virtual address of base of descending stack : [0x0..0xFFFFFFFF] +armcortexm7ct.semihosting-stack_limit=0 # (int , init-time) default = '0x10800000' : Virtual address of stack limit : [0x0..0xFFFFFFFF] +armcortexm7ct.semihosting-cwd="" # (string, init-time) default = '' : Base directory for semihosting file access. +armcortexm7ct.DP_FLOAT=1 # (bool , init-time) default = '1' : Support 8-byte floats +#---------------------------------------------------------------------------------------------- diff --git a/Testing/board/linker_scripts/ARMCM0P/region_defs.h b/Testing/board/linker_scripts/ARMCM0P/region_defs.h new file mode 100644 index 0000000..b66150b --- /dev/null +++ b/Testing/board/linker_scripts/ARMCM0P/region_defs.h @@ -0,0 +1,60 @@ +#ifndef REGIONS_ARMCM0P_H +#define REGIONS_ARMCM0P_H + + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- + +// Device pack: ARM::Cortex_DFP@1.0.0 +// Device pack used to generate this file + +// ROM Configuration +// ======================= +// ROM=<__ROM0> +// Base address <0x0-0xFFFFFFFF:8> +// Defines base address of memory region. +// Default: 0x00000000 +#define __ROM0_BASE 0x00000000 +// Region size [bytes] <0x0-0xFFFFFFFF:8> +// Defines size of memory region. +// Default: 0x00040000 +#define __ROM0_SIZE 0x00040000 +// Default region +// Enables memory region globally for the application. +#define __ROM0_DEFAULT 1 +// Startup +// Selects region to be used for startup code. +#define __ROM0_STARTUP 1 +// + +// + +// RAM Configuration +// ======================= +// RAM=<__RAM0> +// Base address <0x0-0xFFFFFFFF:8> +// Defines base address of memory region. +// Default: 0x20000000 +#define __RAM0_BASE 0x20000000 +// Region size [bytes] <0x0-0xFFFFFFFF:8> +// Defines size of memory region. +// Default: 0x00020000 +#define __RAM0_SIZE 0x00040000 +// Default region +// Enables memory region globally for the application. +#define __RAM0_DEFAULT 1 +// No zero initialize +// Excludes region from zero initialization. +#define __RAM0_NOINIT 0 +// + +// + +// Stack / Heap Configuration +// Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +// Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +#define __STACK_SIZE 0x00002000 +#define __HEAP_SIZE 0x00038000 +// + + +#endif /* REGIONS_ARMCM0P_H */ diff --git a/Testing/board/linker_scripts/ARMCM4/region_defs.h b/Testing/board/linker_scripts/ARMCM4/region_defs.h new file mode 100644 index 0000000..093a8e0 --- /dev/null +++ b/Testing/board/linker_scripts/ARMCM4/region_defs.h @@ -0,0 +1,60 @@ +#ifndef REGIONS_ARMCM4_H +#define REGIONS_ARMCM4_H + + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- + +// Device pack: ARM::Cortex_DFP@1.0.0 +// Device pack used to generate this file + +// ROM Configuration +// ======================= +// ROM=<__ROM0> +// Base address <0x0-0xFFFFFFFF:8> +// Defines base address of memory region. +// Default: 0x00000000 +#define __ROM0_BASE 0x00000000 +// Region size [bytes] <0x0-0xFFFFFFFF:8> +// Defines size of memory region. +// Default: 0x00040000 +#define __ROM0_SIZE 0x00400000 +// Default region +// Enables memory region globally for the application. +#define __ROM0_DEFAULT 1 +// Startup +// Selects region to be used for startup code. +#define __ROM0_STARTUP 1 +// + +// + +// RAM Configuration +// ======================= +// RAM=<__RAM0> +// Base address <0x0-0xFFFFFFFF:8> +// Defines base address of memory region. +// Default: 0x20000000 +#define __RAM0_BASE 0x20000000 +// Region size [bytes] <0x0-0xFFFFFFFF:8> +// Defines size of memory region. +// Default: 0x00020000 +#define __RAM0_SIZE 0x00500000 +// Default region +// Enables memory region globally for the application. +#define __RAM0_DEFAULT 1 +// No zero initialize +// Excludes region from zero initialization. +#define __RAM0_NOINIT 0 +// + +// + +// Stack / Heap Configuration +// Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +// Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +#define __STACK_SIZE 0x00004000 +#define __HEAP_SIZE 0x00300000 +// + + +#endif /* REGIONS_ARMCM4_H */ diff --git a/Testing/board/linker_scripts/ARMCM7/region_defs.h b/Testing/board/linker_scripts/ARMCM7/region_defs.h new file mode 100644 index 0000000..093a8e0 --- /dev/null +++ b/Testing/board/linker_scripts/ARMCM7/region_defs.h @@ -0,0 +1,60 @@ +#ifndef REGIONS_ARMCM4_H +#define REGIONS_ARMCM4_H + + +//-------- <<< Use Configuration Wizard in Context Menu >>> -------------------- + +// Device pack: ARM::Cortex_DFP@1.0.0 +// Device pack used to generate this file + +// ROM Configuration +// ======================= +// ROM=<__ROM0> +// Base address <0x0-0xFFFFFFFF:8> +// Defines base address of memory region. +// Default: 0x00000000 +#define __ROM0_BASE 0x00000000 +// Region size [bytes] <0x0-0xFFFFFFFF:8> +// Defines size of memory region. +// Default: 0x00040000 +#define __ROM0_SIZE 0x00400000 +// Default region +// Enables memory region globally for the application. +#define __ROM0_DEFAULT 1 +// Startup +// Selects region to be used for startup code. +#define __ROM0_STARTUP 1 +// + +// + +// RAM Configuration +// ======================= +// RAM=<__RAM0> +// Base address <0x0-0xFFFFFFFF:8> +// Defines base address of memory region. +// Default: 0x20000000 +#define __RAM0_BASE 0x20000000 +// Region size [bytes] <0x0-0xFFFFFFFF:8> +// Defines size of memory region. +// Default: 0x00020000 +#define __RAM0_SIZE 0x00500000 +// Default region +// Enables memory region globally for the application. +#define __RAM0_DEFAULT 1 +// No zero initialize +// Excludes region from zero initialization. +#define __RAM0_NOINIT 0 +// + +// + +// Stack / Heap Configuration +// Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +// Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +#define __STACK_SIZE 0x00004000 +#define __HEAP_SIZE 0x00300000 +// + + +#endif /* REGIONS_ARMCM4_H */ diff --git a/Testing/board/linker_scripts/SSE-300-MPS3/region_defs.h b/Testing/board/linker_scripts/SSE-300-MPS3/region_defs.h new file mode 100644 index 0000000..32ac16b --- /dev/null +++ b/Testing/board/linker_scripts/SSE-300-MPS3/region_defs.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016-2022 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __REGION_DEFS_H__ +#define __REGION_DEFS_H__ + +#include "region_limits.h" + +/* ************************************************************** + * WARNING: this file is parsed both by the C/C++ compiler + * and the linker. As a result the syntax must be valid not only + * for C/C++ but for the linker scripts too. + * Beware of the following limitations: + * - LD (GCC linker) requires white space around operators. + * - UL postfix for macros is not suported by the linker script + ****************************************************************/ + +/* Secure regions */ +#define S_CODE_START ( S_ROM_ALIAS ) +#define S_CODE_SIZE ( TOTAL_S_ROM_SIZE ) +#define S_CODE_LIMIT ( S_CODE_START + S_CODE_SIZE ) + +#define S_DATA_START ( S_RAM_ALIAS ) +#define S_DATA_SIZE ( TOTAL_S_RAM_SIZE ) +#define S_DATA_LIMIT ( S_DATA_START + S_DATA_SIZE ) + +#define S_DDR4_START ( S_DDR4_ALIAS ) +#define S_DDR4_SIZE ( TOTAL_S_DDR4_SIZE ) +#define S_DDR4_LIMIT ( S_DDR4_START + S_DDR4_SIZE ) + +#endif /* __REGION_DEFS_H__ */ diff --git a/Testing/board/linker_scripts/SSE-300-MPS3/region_limits.h b/Testing/board/linker_scripts/SSE-300-MPS3/region_limits.h new file mode 100644 index 0000000..8fba518 --- /dev/null +++ b/Testing/board/linker_scripts/SSE-300-MPS3/region_limits.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018-2022 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __REGION_LIMITS_H__ +#define __REGION_LIMITS_H__ + +/* ************************************************************** + * WARNING: this file is parsed both by the C/C++ compiler + * and the linker. As a result the syntax must be valid not only + * for C/C++ but for the linker scripts too. + * Beware of the following limitations: + * - LD (GCC linker) requires white space around operators. + * - UL postfix for macros is not suported by the linker script + ****************************************************************/ + +/* Secure Code */ +#define S_ROM_ALIAS (0x10000000) /* ITCM_BASE_S */ +#define TOTAL_S_ROM_SIZE (0x00080000) /* 512 kB */ + +/* Secure Data */ +#define S_RAM_ALIAS (0x30000000) /* DTCM_BASE_S */ +#define TOTAL_S_RAM_SIZE (0x00080000) /* 512 kB */ + +/* Secure DDR4 */ +#define S_DDR4_ALIAS (0x70000000) /* DDR4_BLK1_BASE_S */ +#define TOTAL_S_DDR4_SIZE (0x10000000) /* 256 MB */ + +/* Heap and Stack sizes for secure and nonsecure applications */ +#define HEAP_SIZE (0x00300000) /* 1 KiB */ +#define STACK_SIZE (0x00004000) /* 1 KiB */ + +#endif /* __REGION_LIMITS_H__ */ diff --git a/Testing/board/linker_scripts/ac6_m0p_mps3_s.sct b/Testing/board/linker_scripts/ac6_m0p_mps3_s.sct new file mode 100644 index 0000000..4d6e579 --- /dev/null +++ b/Testing/board/linker_scripts/ac6_m0p_mps3_s.sct @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/*---------------------------------------------------------------------------- + Scatter File Definitions definition + *----------------------------------------------------------------------------*/ + +LR_ROM0 __ROM0_BASE __ROM0_SIZE { + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + ER_CMSE_VENEER __ROM0_BASE+__ROM0_SIZE -__ROM0_SIZE { + *(Veneer$$CMSE) + } + #define ER_CMSE_VENEER_SIZE AlignExpr(ImageLength(ER_CMSE_VENEER), 8) +#else + #define ER_CMSE_VENEER_SIZE 0 +#endif + + ER_ROM0 __ROM0_BASE (__ROM0_SIZE - ER_CMSE_VENEER_SIZE) { + *.o (RESET, +First) + *(InRoot$$Sections) + *(+RO +XO) + } + + RW_NOINIT __RAM0_BASE UNINIT (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE) { + *(.bss.noinit) + } + + RW_RAM0 AlignExpr(+0, 8) (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - AlignExpr(ImageLength(RW_NOINIT), 8)) { + *(+RW +ZI) + } + +#if __HEAP_SIZE > 0 + ARM_LIB_HEAP (AlignExpr(+0, 8)) EMPTY __HEAP_SIZE { ; Reserve empty region for heap + } +#endif + + ARM_LIB_STACK (__RAM0_BASE + __RAM0_SIZE - __STACKSEAL_SIZE) EMPTY -__STACK_SIZE { ; Reserve empty region for stack + } + +#if __STACKSEAL_SIZE > 0 + STACKSEAL +0 EMPTY 8 { ; Reserve empty region for stack seal immediately after stack + } +#endif + +#if __RAM1_SIZE > 0 + RW_RAM1 __RAM1_BASE __RAM1_SIZE { + .ANY (+RW +ZI) + } +#endif + +#if __RAM2_SIZE > 0 + RW_RAM2 __RAM2_BASE __RAM2_SIZE { + .ANY (+RW +ZI) + } +#endif + +#if __RAM3_SIZE > 0 + RW_RAM3 __RAM3_BASE __RAM3_SIZE { + .ANY (+RW +ZI) + } +#endif +} + +#if __ROM1_SIZE > 0 +LR_ROM1 __ROM1_BASE __ROM1_SIZE { + ER_ROM1 +0 __ROM1_SIZE { + .ANY (+RO +XO) + } +} +#endif + +#if __ROM2_SIZE > 0 +LR_ROM2 __ROM2_BASE __ROM2_SIZE { + ER_ROM2 +0 __ROM2_SIZE { + .ANY (+RO +XO) + } +} +#endif + +#if __ROM3_SIZE > 0 +LR_ROM3 __ROM3_BASE __ROM3_SIZE { + ER_ROM3 +0 __ROM3_SIZE { + .ANY (+RO +XO) + } +} +#endif diff --git a/Testing/board/linker_scripts/ac6_m4_mps3_s.sct b/Testing/board/linker_scripts/ac6_m4_mps3_s.sct new file mode 100644 index 0000000..25569b9 --- /dev/null +++ b/Testing/board/linker_scripts/ac6_m4_mps3_s.sct @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/*---------------------------------------------------------------------------- + Scatter File Definitions definition + *----------------------------------------------------------------------------*/ + +LR_ROM0 __ROM0_BASE __ROM0_SIZE { + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + ER_CMSE_VENEER __ROM0_BASE+__ROM0_SIZE -__ROM0_SIZE { + *(Veneer$$CMSE) + } + #define ER_CMSE_VENEER_SIZE AlignExpr(ImageLength(ER_CMSE_VENEER), 8) +#else + #define ER_CMSE_VENEER_SIZE 0 +#endif + + ER_ROM0 __ROM0_BASE (__ROM0_SIZE - ER_CMSE_VENEER_SIZE) { + *.o (RESET, +First) + *(InRoot$$Sections) + *(+RO-CODE +XO) + } + + RW_NOINIT __RAM0_BASE UNINIT (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE) { + *(.bss.noinit) + } + + RW_RAM0 AlignExpr(+0, 8) (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - AlignExpr(ImageLength(RW_NOINIT), 8)) { + *(+RW +ZI +RO-DATA) + } + +#if __HEAP_SIZE > 0 + ARM_LIB_HEAP (AlignExpr(+0, 8)) EMPTY __HEAP_SIZE { ; Reserve empty region for heap + } +#endif + + ARM_LIB_STACK (__RAM0_BASE + __RAM0_SIZE - __STACKSEAL_SIZE) EMPTY -__STACK_SIZE { ; Reserve empty region for stack + } + +#if __STACKSEAL_SIZE > 0 + STACKSEAL +0 EMPTY 8 { ; Reserve empty region for stack seal immediately after stack + } +#endif + +#if __RAM1_SIZE > 0 + RW_RAM1 __RAM1_BASE __RAM1_SIZE { + .ANY (+RW +ZI) + } +#endif + +#if __RAM2_SIZE > 0 + RW_RAM2 __RAM2_BASE __RAM2_SIZE { + .ANY (+RW +ZI) + } +#endif + +#if __RAM3_SIZE > 0 + RW_RAM3 __RAM3_BASE __RAM3_SIZE { + .ANY (+RW +ZI) + } +#endif +} + +#if __ROM1_SIZE > 0 +LR_ROM1 __ROM1_BASE __ROM1_SIZE { + ER_ROM1 +0 __ROM1_SIZE { + .ANY (+RO +XO) + } +} +#endif + +#if __ROM2_SIZE > 0 +LR_ROM2 __ROM2_BASE __ROM2_SIZE { + ER_ROM2 +0 __ROM2_SIZE { + .ANY (+RO +XO) + } +} +#endif + +#if __ROM3_SIZE > 0 +LR_ROM3 __ROM3_BASE __ROM3_SIZE { + ER_ROM3 +0 __ROM3_SIZE { + .ANY (+RO +XO) + } +} +#endif diff --git a/Testing/board/linker_scripts/ac6_m7_mps3_s.sct b/Testing/board/linker_scripts/ac6_m7_mps3_s.sct new file mode 100644 index 0000000..25569b9 --- /dev/null +++ b/Testing/board/linker_scripts/ac6_m7_mps3_s.sct @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/*---------------------------------------------------------------------------- + Scatter File Definitions definition + *----------------------------------------------------------------------------*/ + +LR_ROM0 __ROM0_BASE __ROM0_SIZE { + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + ER_CMSE_VENEER __ROM0_BASE+__ROM0_SIZE -__ROM0_SIZE { + *(Veneer$$CMSE) + } + #define ER_CMSE_VENEER_SIZE AlignExpr(ImageLength(ER_CMSE_VENEER), 8) +#else + #define ER_CMSE_VENEER_SIZE 0 +#endif + + ER_ROM0 __ROM0_BASE (__ROM0_SIZE - ER_CMSE_VENEER_SIZE) { + *.o (RESET, +First) + *(InRoot$$Sections) + *(+RO-CODE +XO) + } + + RW_NOINIT __RAM0_BASE UNINIT (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE) { + *(.bss.noinit) + } + + RW_RAM0 AlignExpr(+0, 8) (__RAM0_SIZE - __HEAP_SIZE - __STACK_SIZE - AlignExpr(ImageLength(RW_NOINIT), 8)) { + *(+RW +ZI +RO-DATA) + } + +#if __HEAP_SIZE > 0 + ARM_LIB_HEAP (AlignExpr(+0, 8)) EMPTY __HEAP_SIZE { ; Reserve empty region for heap + } +#endif + + ARM_LIB_STACK (__RAM0_BASE + __RAM0_SIZE - __STACKSEAL_SIZE) EMPTY -__STACK_SIZE { ; Reserve empty region for stack + } + +#if __STACKSEAL_SIZE > 0 + STACKSEAL +0 EMPTY 8 { ; Reserve empty region for stack seal immediately after stack + } +#endif + +#if __RAM1_SIZE > 0 + RW_RAM1 __RAM1_BASE __RAM1_SIZE { + .ANY (+RW +ZI) + } +#endif + +#if __RAM2_SIZE > 0 + RW_RAM2 __RAM2_BASE __RAM2_SIZE { + .ANY (+RW +ZI) + } +#endif + +#if __RAM3_SIZE > 0 + RW_RAM3 __RAM3_BASE __RAM3_SIZE { + .ANY (+RW +ZI) + } +#endif +} + +#if __ROM1_SIZE > 0 +LR_ROM1 __ROM1_BASE __ROM1_SIZE { + ER_ROM1 +0 __ROM1_SIZE { + .ANY (+RO +XO) + } +} +#endif + +#if __ROM2_SIZE > 0 +LR_ROM2 __ROM2_BASE __ROM2_SIZE { + ER_ROM2 +0 __ROM2_SIZE { + .ANY (+RO +XO) + } +} +#endif + +#if __ROM3_SIZE > 0 +LR_ROM3 __ROM3_BASE __ROM3_SIZE { + ER_ROM3 +0 __ROM3_SIZE { + .ANY (+RO +XO) + } +} +#endif diff --git a/Testing/board/linker_scripts/ac6_sse300_mps3_s.sct b/Testing/board/linker_scripts/ac6_sse300_mps3_s.sct new file mode 100644 index 0000000..a212266 --- /dev/null +++ b/Testing/board/linker_scripts/ac6_sse300_mps3_s.sct @@ -0,0 +1,92 @@ + +;/* +; * Copyright (c) 2018-2021 Arm Limited. All rights reserved. +; * +; * Licensed under the Apache License, Version 2.0 (the "License"); +; * you may not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * http://www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an "AS IS" BASIS, +; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; * +; */ + +;#include "region_defs.h" + +LR_CODE S_CODE_START { + ER_CODE S_CODE_START { + *.o (RESET +First) + .ANY (+RO-CODE) + /* different test vectors */ + * (InRoot$$Sections) + } + + /* + * Place the CMSE Veneers (containing the SG instruction) after the code, in + * a separate 32 bytes aligned region so that the SAU can programmed to just + * set this region as Non-Secure Callable. The maximum size of this + * executable region makes it only used the space left over by the ER_CODE + * region so that you can rely on code+veneer size combined will not exceed + * the S_CODE_SIZE value. We also substract from the available space the + * area used to align this section on 32 bytes boundary (for SAU conf). + */ + ER_CODE_CMSE_VENEER +0 ALIGN 32 { + *(Veneer$$CMSE) + } + /* + * This dummy region ensures that the next one will be aligned on a 32 bytes + * boundary, so that the following region will not be mistakenly configured + * as Non-Secure Callable by the SAU. + */ + ER_CODE_CMSE_VENEER_DUMMY +0 ALIGN 32 EMPTY 0 {} + + /* This empty, zero long execution region is here to mark the limit address + * of the last execution region that is allocated in SRAM. + */ + CODE_WATERMARK +0 EMPTY 0x0 { + } + /* Make sure that the sections allocated in the SRAM does not exceed the + * size of the SRAM available. + */ + ScatterAssert(ImageLimit(CODE_WATERMARK) <= S_CODE_START + S_CODE_SIZE) + + ER_DATA S_DATA_START { + .ANY (+ZI +RW +RO-DATA) + } + + ARM_LIB_STACK +0 ALIGN 32 EMPTY STACK_SIZE { ; Reserve empty region for stack + } + + STACKSEAL +0 EMPTY 0x8 { + } + + /* This empty, zero long execution region is here to mark the limit address + * of the last execution region that is allocated in SRAM. + */ + SRAM_WATERMARK +0 EMPTY 0x0 { + } + /* Make sure that the sections allocated in the SRAM does not exceed the + * size of the SRAM available. + */ + ScatterAssert(ImageLimit(SRAM_WATERMARK) <= S_DATA_START + S_DATA_SIZE) +} + +LR_MEM S_DDR4_START { + #if HEAP_SIZE > 0 + ARM_LIB_HEAP +0 ALIGN 8 EMPTY HEAP_SIZE { ; Reserve empty region for heap + } + #endif + + + + DDR4_WATERMARK +0 EMPTY 0x0 { + } + + ScatterAssert(ImageLimit(DDR4_WATERMARK) <= S_DDR4_START + S_DDR4_SIZE) + +} \ No newline at end of file diff --git a/Testing/board/linker_scripts/ac6_sse310_mps3_s.sct b/Testing/board/linker_scripts/ac6_sse310_mps3_s.sct new file mode 100644 index 0000000..0650639 --- /dev/null +++ b/Testing/board/linker_scripts/ac6_sse310_mps3_s.sct @@ -0,0 +1,60 @@ + +;/* +; * Copyright (c) 2018-2021 Arm Limited +; * +; * Licensed under the Apache License, Version 2.0 (the "License"); +; * you may not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * http://www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an "AS IS" BASIS, +; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; * +; */ + + + +LR_CODE S_CODE_START { + ER_CODE S_CODE_START { + *.o (RESET +First) + .ANY (+RO) + /* different test vectors */ + * (InRoot$$Sections) + } + + /* This empty, zero long execution region is here to mark the limit address + * of the last execution region that is allocated in SRAM. + */ + CODE_WATERMARK +0 EMPTY 0x0 { + } + /* Make sure that the sections allocated in the SRAM does not exceed the + * size of the SRAM available. + */ + ScatterAssert(ImageLimit(CODE_WATERMARK) <= S_CODE_START + S_CODE_SIZE) + + ER_DATA S_DATA_START { + .ANY (+ZI +RW +RO-DATA) + } + + #if HEAP_SIZE > 0 + ARM_LIB_HEAP +0 ALIGN 8 EMPTY HEAP_SIZE { ; Reserve empty region for heap + } + #endif + + ARM_LIB_STACK +0 ALIGN 32 EMPTY STACK_SIZE { ; Reserve empty region for stack + } + + /* This empty, zero long execution region is here to mark the limit address + * of the last execution region that is allocated in SRAM. + */ + SRAM_WATERMARK +0 EMPTY 0x0 { + } + /* Make sure that the sections allocated in the SRAM does not exceed the + * size of the SRAM available. + */ + ScatterAssert(ImageLimit(SRAM_WATERMARK) <= S_DATA_START + S_DATA_SIZE) +} diff --git a/Testing/board/linker_scripts/clang_m0p_mps3.ld b/Testing/board/linker_scripts/clang_m0p_mps3.ld new file mode 100644 index 0000000..40f955c --- /dev/null +++ b/Testing/board/linker_scripts/clang_m0p_mps3.ld @@ -0,0 +1,353 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2019 Keith Packard + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/* ---------------------------------------------------------------------------- + Memory definition + *----------------------------------------------------------------------------*/ +MEMORY +{ + ROM0 (rx!w) : ORIGIN = __ROM0_BASE, LENGTH = __ROM0_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx!w) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx!w) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx!w) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (w!rx) : ORIGIN = __RAM0_BASE, LENGTH = __RAM0_SIZE +#if __RAM1_SIZE > 0 + RAM1 (w!rx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (w!rx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (w!rx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +ENTRY(Reset_Handler) + +PHDRS +{ + text PT_LOAD; + ram PT_LOAD; + ram_init PT_LOAD; + tls PT_TLS; +} + +SECTIONS +{ + .init : { + KEEP (*(.vectors)) + KEEP (*(.text.init.enter)) + KEEP (*(.data.init.enter)) + KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*))) + } >ROM0 AT>ROM0 :text + + .text : { + + /* code */ + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.* .opd .opd.*) + *(.gnu.linkonce.t.*) + KEEP (*(.fini .fini.*)) + __text_end = .; + + PROVIDE (__etext = __text_end); + PROVIDE (_etext = __text_end); + PROVIDE (etext = __text_end); + + /* read-only data */ + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + *(.data.rel.ro .data.rel.ro.*) + *(.got .got.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + /* lists of constructors and destructors */ + PROVIDE_HIDDEN ( __preinit_array_start = . ); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN ( __preinit_array_end = . ); + + PROVIDE_HIDDEN ( __init_array_start = . ); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array .ctors)) + PROVIDE_HIDDEN ( __init_array_end = . ); + + PROVIDE_HIDDEN ( __fini_array_start = . ); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array .dtors)) + PROVIDE_HIDDEN ( __fini_array_end = . ); + + } >ROM0 AT>ROM0 :text + + .toc : { + *(.toc .toc.*) + } >ROM0 AT>ROM0 :text + + /* additional sections when compiling with C++ exception support */ + + .except_ordered : { + *(.gcc_except_table *.gcc_except_table.*) + KEEP (*(.eh_frame .eh_frame.*)) + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >ROM0 AT>ROM0 :text + + .except_unordered : { + . = ALIGN(8); + + PROVIDE(__exidx_start = .); + *(.ARM.exidx*) + PROVIDE(__exidx_end = .); + } >ROM0 AT>ROM0 :text + + + /* + * Data values which are preserved across reset + */ + .preserve (NOLOAD) : { + PROVIDE(__preserve_start__ = .); + KEEP(*(SORT_BY_NAME(.preserve.*))) + KEEP(*(.preserve)) + PROVIDE(__preserve_end__ = .); + } >RAM0 AT>RAM0 :ram + + .data : { + *(.data .data.*) + *(.gnu.linkonce.d.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.* .sdata2.*) + *(.gnu.linkonce.s.*) + } >RAM0 AT>ROM0 :ram_init + PROVIDE(__data_start = ADDR(.data)); + PROVIDE(__data_source = LOADADDR(.data)); + + /* Thread local initialized data. This gets + * space allocated as it is expected to be placed + * in ram to be used as a template for TLS data blocks + * allocated at runtime. We're slightly abusing that + * by placing the data in flash where it will be copied + * into the allocate ram addresses by the existing + * data initialization code in crt0 + */ + .tdata : { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE(__data_end = .); + PROVIDE(__tdata_end = .); + } >RAM0 AT>ROM0 :tls :ram_init + PROVIDE( __tls_base = ADDR(.tdata)); + PROVIDE( __tdata_start = ADDR(.tdata)); + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) ); + PROVIDE( __data_source_end = __tdata_source_end ); + PROVIDE( __tdata_size = SIZEOF(.tdata) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata),ALIGNOF(.tbss)) ); + + PROVIDE( __edata = __data_end ); + PROVIDE( _edata = __data_end ); + PROVIDE( edata = __data_end ); + PROVIDE( __data_size = __data_end - __data_start ); + PROVIDE( __data_source_size = __data_source_end - __data_source ); + + .tbss (NOLOAD) : { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } >RAM0 AT>RAM0 :tls :ram + PROVIDE( __bss_start = ADDR(.tbss)); + PROVIDE( __tbss_start = ADDR(.tbss)); + PROVIDE( __tbss_offset = ADDR(.tbss) - ADDR(.tdata) ); + PROVIDE( __tbss_size = SIZEOF(.tbss) ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) ); + + /* + * The linker special cases .tbss segments which are + * identified as segments which are not loaded and are + * thread_local. + * + * For these segments, the linker does not advance 'dot' + * across them. We actually need memory allocated for tbss, + * so we create a special segment here just to make room + */ + /* + .tbss_space (NOLOAD) : { + . = ADDR(.tbss); + . = . + SIZEOF(.tbss); + } >RAM0 AT>RAM0 :ram + */ + + .bss (NOLOAD) : { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + + /* Align the heap */ + . = ALIGN(8); + __bss_end = .; + } >RAM0 AT>RAM0 :ram + PROVIDE( __non_tls_bss_start = ADDR(.bss) ); + PROVIDE( __end = __bss_end ); + PROVIDE( _end = __bss_end ); + PROVIDE( end = __bss_end ); + PROVIDE( __bss_size = __bss_end - __bss_start ); + + /* Make the rest of memory available for heap storage */ + PROVIDE (__heap_start = __end); +#ifdef __HEAP_SIZE + PROVIDE (__heap_end = __heap_start + __HEAP_SIZE); + PROVIDE (__heap_size = __HEAP_SIZE); +#else + PROVIDE (__heap_end = __stack - __STACK_SIZE); + PROVIDE (__heap_size = __heap_end - __heap_start); +#endif + .heap (NOLOAD) : { + . += __heap_size; + } >RAM0 :ram + + /* Define a stack region to make sure it fits in memory */ + PROVIDE(__stack = ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE); + PROVIDE(__stack_limit = __stack - __STACK_SIZE); + .stack (__stack_limit) (NOLOAD) : { + . += __STACK_SIZE; + } >RAM0 :ram + +#if __STACKSEAL_SIZE > 0 + PROVIDE(__stack_seal = __stack) + .stackseal (__stack) (NOLOAD) : + { + . += __STACKSEAL_SIZE; + } >RAM0 :ram +#endif + + /* Throw away C++ exception handling information */ + + /* + + /DISCARD/ : { + *(.note .note.*) + *(.eh_frame .eh_frame.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx*) + } + + */ + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1. */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions. */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2. */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2. */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions. */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3. */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF 5. */ + .debug_addr 0 : { *(.debug_addr) } + .debug_line_str 0 : { *(.debug_line_str) } + .debug_loclists 0 : { *(.debug_loclists) } + .debug_macro 0 : { *(.debug_macro) } + .debug_names 0 : { *(.debug_names) } + .debug_rnglists 0 : { *(.debug_rnglists) } + .debug_str_offsets 0 : { *(.debug_str_offsets) } + .debug_sup 0 : { *(.debug_sup) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } +} +/* + * Check that sections that are copied from flash to RAM have matching + * padding, so that a single memcpy() of __data_size copies the correct bytes. + */ +ASSERT( __data_size == __data_source_size, + "ERROR: .data/.tdata flash size does not match RAM size"); diff --git a/Testing/board/linker_scripts/clang_m4_mps3.ld b/Testing/board/linker_scripts/clang_m4_mps3.ld new file mode 100644 index 0000000..40f955c --- /dev/null +++ b/Testing/board/linker_scripts/clang_m4_mps3.ld @@ -0,0 +1,353 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2019 Keith Packard + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/* ---------------------------------------------------------------------------- + Memory definition + *----------------------------------------------------------------------------*/ +MEMORY +{ + ROM0 (rx!w) : ORIGIN = __ROM0_BASE, LENGTH = __ROM0_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx!w) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx!w) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx!w) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (w!rx) : ORIGIN = __RAM0_BASE, LENGTH = __RAM0_SIZE +#if __RAM1_SIZE > 0 + RAM1 (w!rx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (w!rx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (w!rx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +ENTRY(Reset_Handler) + +PHDRS +{ + text PT_LOAD; + ram PT_LOAD; + ram_init PT_LOAD; + tls PT_TLS; +} + +SECTIONS +{ + .init : { + KEEP (*(.vectors)) + KEEP (*(.text.init.enter)) + KEEP (*(.data.init.enter)) + KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*))) + } >ROM0 AT>ROM0 :text + + .text : { + + /* code */ + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.* .opd .opd.*) + *(.gnu.linkonce.t.*) + KEEP (*(.fini .fini.*)) + __text_end = .; + + PROVIDE (__etext = __text_end); + PROVIDE (_etext = __text_end); + PROVIDE (etext = __text_end); + + /* read-only data */ + *(.rdata) + *(.rodata .rodata.*) + *(.gnu.linkonce.r.*) + + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + *(.data.rel.ro .data.rel.ro.*) + *(.got .got.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + /* lists of constructors and destructors */ + PROVIDE_HIDDEN ( __preinit_array_start = . ); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN ( __preinit_array_end = . ); + + PROVIDE_HIDDEN ( __init_array_start = . ); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array .ctors)) + PROVIDE_HIDDEN ( __init_array_end = . ); + + PROVIDE_HIDDEN ( __fini_array_start = . ); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array .dtors)) + PROVIDE_HIDDEN ( __fini_array_end = . ); + + } >ROM0 AT>ROM0 :text + + .toc : { + *(.toc .toc.*) + } >ROM0 AT>ROM0 :text + + /* additional sections when compiling with C++ exception support */ + + .except_ordered : { + *(.gcc_except_table *.gcc_except_table.*) + KEEP (*(.eh_frame .eh_frame.*)) + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >ROM0 AT>ROM0 :text + + .except_unordered : { + . = ALIGN(8); + + PROVIDE(__exidx_start = .); + *(.ARM.exidx*) + PROVIDE(__exidx_end = .); + } >ROM0 AT>ROM0 :text + + + /* + * Data values which are preserved across reset + */ + .preserve (NOLOAD) : { + PROVIDE(__preserve_start__ = .); + KEEP(*(SORT_BY_NAME(.preserve.*))) + KEEP(*(.preserve)) + PROVIDE(__preserve_end__ = .); + } >RAM0 AT>RAM0 :ram + + .data : { + *(.data .data.*) + *(.gnu.linkonce.d.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.* .sdata2.*) + *(.gnu.linkonce.s.*) + } >RAM0 AT>ROM0 :ram_init + PROVIDE(__data_start = ADDR(.data)); + PROVIDE(__data_source = LOADADDR(.data)); + + /* Thread local initialized data. This gets + * space allocated as it is expected to be placed + * in ram to be used as a template for TLS data blocks + * allocated at runtime. We're slightly abusing that + * by placing the data in flash where it will be copied + * into the allocate ram addresses by the existing + * data initialization code in crt0 + */ + .tdata : { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE(__data_end = .); + PROVIDE(__tdata_end = .); + } >RAM0 AT>ROM0 :tls :ram_init + PROVIDE( __tls_base = ADDR(.tdata)); + PROVIDE( __tdata_start = ADDR(.tdata)); + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) ); + PROVIDE( __data_source_end = __tdata_source_end ); + PROVIDE( __tdata_size = SIZEOF(.tdata) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata),ALIGNOF(.tbss)) ); + + PROVIDE( __edata = __data_end ); + PROVIDE( _edata = __data_end ); + PROVIDE( edata = __data_end ); + PROVIDE( __data_size = __data_end - __data_start ); + PROVIDE( __data_source_size = __data_source_end - __data_source ); + + .tbss (NOLOAD) : { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } >RAM0 AT>RAM0 :tls :ram + PROVIDE( __bss_start = ADDR(.tbss)); + PROVIDE( __tbss_start = ADDR(.tbss)); + PROVIDE( __tbss_offset = ADDR(.tbss) - ADDR(.tdata) ); + PROVIDE( __tbss_size = SIZEOF(.tbss) ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) ); + + /* + * The linker special cases .tbss segments which are + * identified as segments which are not loaded and are + * thread_local. + * + * For these segments, the linker does not advance 'dot' + * across them. We actually need memory allocated for tbss, + * so we create a special segment here just to make room + */ + /* + .tbss_space (NOLOAD) : { + . = ADDR(.tbss); + . = . + SIZEOF(.tbss); + } >RAM0 AT>RAM0 :ram + */ + + .bss (NOLOAD) : { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + + /* Align the heap */ + . = ALIGN(8); + __bss_end = .; + } >RAM0 AT>RAM0 :ram + PROVIDE( __non_tls_bss_start = ADDR(.bss) ); + PROVIDE( __end = __bss_end ); + PROVIDE( _end = __bss_end ); + PROVIDE( end = __bss_end ); + PROVIDE( __bss_size = __bss_end - __bss_start ); + + /* Make the rest of memory available for heap storage */ + PROVIDE (__heap_start = __end); +#ifdef __HEAP_SIZE + PROVIDE (__heap_end = __heap_start + __HEAP_SIZE); + PROVIDE (__heap_size = __HEAP_SIZE); +#else + PROVIDE (__heap_end = __stack - __STACK_SIZE); + PROVIDE (__heap_size = __heap_end - __heap_start); +#endif + .heap (NOLOAD) : { + . += __heap_size; + } >RAM0 :ram + + /* Define a stack region to make sure it fits in memory */ + PROVIDE(__stack = ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE); + PROVIDE(__stack_limit = __stack - __STACK_SIZE); + .stack (__stack_limit) (NOLOAD) : { + . += __STACK_SIZE; + } >RAM0 :ram + +#if __STACKSEAL_SIZE > 0 + PROVIDE(__stack_seal = __stack) + .stackseal (__stack) (NOLOAD) : + { + . += __STACKSEAL_SIZE; + } >RAM0 :ram +#endif + + /* Throw away C++ exception handling information */ + + /* + + /DISCARD/ : { + *(.note .note.*) + *(.eh_frame .eh_frame.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx*) + } + + */ + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1. */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions. */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2. */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2. */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions. */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3. */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF 5. */ + .debug_addr 0 : { *(.debug_addr) } + .debug_line_str 0 : { *(.debug_line_str) } + .debug_loclists 0 : { *(.debug_loclists) } + .debug_macro 0 : { *(.debug_macro) } + .debug_names 0 : { *(.debug_names) } + .debug_rnglists 0 : { *(.debug_rnglists) } + .debug_str_offsets 0 : { *(.debug_str_offsets) } + .debug_sup 0 : { *(.debug_sup) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } +} +/* + * Check that sections that are copied from flash to RAM have matching + * padding, so that a single memcpy() of __data_size copies the correct bytes. + */ +ASSERT( __data_size == __data_source_size, + "ERROR: .data/.tdata flash size does not match RAM size"); diff --git a/Testing/board/linker_scripts/clang_sse300_mps3.sct b/Testing/board/linker_scripts/clang_sse300_mps3.sct new file mode 100644 index 0000000..2f0f424 --- /dev/null +++ b/Testing/board/linker_scripts/clang_sse300_mps3.sct @@ -0,0 +1,364 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2019 Keith Packard + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/* ---------------------------------------------------------------------------- + Memory definition + *----------------------------------------------------------------------------*/ +MEMORY +{ + ROM0 (rx!w) : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE + 0x000000 +#if __ROM1_SIZE > 0 + ROM1 (rx!w) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx!w) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx!w) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (w!rx) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE + 0x000000 +#if S_DDR4_SIZE > 0 + RAM1 (rw) : ORIGIN = S_DDR4_START, LENGTH = S_DDR4_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (w!rx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (w!rx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +ENTRY(Reset_Handler) + +PHDRS +{ + text PT_LOAD; + ram PT_LOAD; + ram_init PT_LOAD; + tls PT_TLS; +} + +SECTIONS +{ + .init : { + KEEP (*(.vectors)) + KEEP (*(.text.init.enter)) + KEEP (*(.data.init.enter)) + KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*))) + } >ROM0 AT>ROM0 :text + + .text : { + + /* code */ + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.* .opd .opd.*) + *(.gnu.linkonce.t.*) + KEEP (*(.fini .fini.*)) + __text_end = .; + + PROVIDE (__etext = __text_end); + PROVIDE (_etext = __text_end); + PROVIDE (etext = __text_end); + + *(.gnu.linkonce.r.*) + + + + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + *(.data.rel.ro .data.rel.ro.*) + *(.got .got.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + /* lists of constructors and destructors */ + PROVIDE_HIDDEN ( __preinit_array_start = . ); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN ( __preinit_array_end = . ); + + PROVIDE_HIDDEN ( __init_array_start = . ); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array .ctors)) + PROVIDE_HIDDEN ( __init_array_end = . ); + + PROVIDE_HIDDEN ( __fini_array_start = . ); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array .dtors)) + PROVIDE_HIDDEN ( __fini_array_end = . ); + + } >ROM0 AT>ROM0 :text + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .veneers : + { + . = ALIGN(32); + KEEP(*(.gnu.sgstubs)) + } > ROM0 AT>ROM0 :text +#endif + + .toc : { + *(.toc .toc.*) + } >ROM0 AT>ROM0 :text + + /* additional sections when compiling with C++ exception support */ + + .except_ordered : { + *(.gcc_except_table *.gcc_except_table.*) + KEEP (*(.eh_frame .eh_frame.*)) + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >ROM0 AT>ROM0 :text + + .except_unordered : { + . = ALIGN(8); + + PROVIDE(__exidx_start = .); + *(.ARM.exidx*) + PROVIDE(__exidx_end = .); + } >ROM0 AT>ROM0 :text + + + /* + * Data values which are preserved across reset + */ + .preserve (NOLOAD) : { + PROVIDE(__preserve_start__ = .); + KEEP(*(SORT_BY_NAME(.preserve.*))) + KEEP(*(.preserve)) + PROVIDE(__preserve_end__ = .); + } >RAM0 AT>RAM0 :ram + + .data : { + *(.data .data.*) + *(.gnu.linkonce.d.*) + + /* read-only data */ + *(.rdata) + *(.rodata .rodata.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.* .sdata2.*) + *(.gnu.linkonce.s.*) + } >RAM0 AT>ROM0 :ram_init + PROVIDE(__data_start = ADDR(.data)); + PROVIDE(__data_source = LOADADDR(.data)); + + /* Thread local initialized data. This gets + * space allocated as it is expected to be placed + * in ram to be used as a template for TLS data blocks + * allocated at runtime. We're slightly abusing that + * by placing the data in flash where it will be copied + * into the allocate ram addresses by the existing + * data initialization code in crt0 + */ + .tdata : { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE(__data_end = .); + PROVIDE(__tdata_end = .); + } >RAM0 AT>ROM0 :tls :ram_init + PROVIDE( __tls_base = ADDR(.tdata)); + PROVIDE( __tdata_start = ADDR(.tdata)); + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) ); + PROVIDE( __data_source_end = __tdata_source_end ); + PROVIDE( __tdata_size = SIZEOF(.tdata) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata),ALIGNOF(.tbss)) ); + + PROVIDE( __edata = __data_end ); + PROVIDE( _edata = __data_end ); + PROVIDE( edata = __data_end ); + PROVIDE( __data_size = __data_end - __data_start ); + PROVIDE( __data_source_size = __data_source_end - __data_source ); + + .tbss (NOLOAD) : { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } >RAM0 AT>RAM0 :tls :ram + PROVIDE( __bss_start = ADDR(.tbss)); + PROVIDE( __tbss_start = ADDR(.tbss)); + PROVIDE( __tbss_offset = ADDR(.tbss) - ADDR(.tdata) ); + PROVIDE( __tbss_size = SIZEOF(.tbss) ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) ); + + /* + * The linker special cases .tbss segments which are + * identified as segments which are not loaded and are + * thread_local. + * + * For these segments, the linker does not advance 'dot' + * across them. We actually need memory allocated for tbss, + * so we create a special segment here just to make room + */ + /* + .tbss_space (NOLOAD) : { + . = ADDR(.tbss); + . = . + SIZEOF(.tbss); + } >RAM0 AT>RAM0 :ram + */ + + .bss (NOLOAD) : { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + + /* Align the heap */ + . = ALIGN(8); + __bss_end = .; + } >RAM0 AT>RAM0 :ram + PROVIDE( __non_tls_bss_start = ADDR(.bss) ); + PROVIDE( __end = __bss_end ); + PROVIDE( _end = __bss_end ); + PROVIDE( end = __bss_end ); + PROVIDE( __bss_size = __bss_end - __bss_start ); + + /* Make the rest of memory available for heap storage */ + PROVIDE (__heap_start = __end); +#ifdef HEAP_SIZE + PROVIDE (__heap_end = __heap_start + HEAP_SIZE); + PROVIDE (__heap_size = HEAP_SIZE); +#else + PROVIDE (__heap_end = __stack - STACK_SIZE); + PROVIDE (__heap_size = __heap_end - __heap_start); +#endif + .heap (NOLOAD) : { + . += __heap_size; + } >RAM1 :ram + + /* Define a stack region to make sure it fits in memory */ + PROVIDE(__stack = ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE); + PROVIDE(__stack_limit = __stack - STACK_SIZE); + .stack (__stack_limit) (NOLOAD) : { + . += STACK_SIZE; + } >RAM0 :ram + +#if __STACKSEAL_SIZE > 0 + PROVIDE(__stack_seal = __stack); + .stackseal (__stack) (NOLOAD) : + { + . += __STACKSEAL_SIZE; + } >RAM0 :ram +#endif + + /* Throw away C++ exception handling information */ + + /* + + /DISCARD/ : { + *(.note .note.*) + *(.eh_frame .eh_frame.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx*) + } + + */ + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1. */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions. */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2. */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2. */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions. */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3. */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF 5. */ + .debug_addr 0 : { *(.debug_addr) } + .debug_line_str 0 : { *(.debug_line_str) } + .debug_loclists 0 : { *(.debug_loclists) } + .debug_macro 0 : { *(.debug_macro) } + .debug_names 0 : { *(.debug_names) } + .debug_rnglists 0 : { *(.debug_rnglists) } + .debug_str_offsets 0 : { *(.debug_str_offsets) } + .debug_sup 0 : { *(.debug_sup) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } +} +/* + * Check that sections that are copied from flash to RAM have matching + * padding, so that a single memcpy() of __data_size copies the correct bytes. + */ +ASSERT( __data_size == __data_source_size, + "ERROR: .data/.tdata flash size does not match RAM size"); diff --git a/Testing/board/linker_scripts/clang_sse310_mps3.sct b/Testing/board/linker_scripts/clang_sse310_mps3.sct new file mode 100644 index 0000000..3f48771 --- /dev/null +++ b/Testing/board/linker_scripts/clang_sse310_mps3.sct @@ -0,0 +1,363 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright © 2019 Keith Packard + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/* ---------------------------------------------------------------------------- + Memory definition + *----------------------------------------------------------------------------*/ +MEMORY +{ + ROM0 (rx!w) : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE + 0x000000 +#if __ROM1_SIZE > 0 + ROM1 (rx!w) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx!w) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx!w) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (w!rx) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE + 0x000000 +#if __RAM1_SIZE > 0 + RAM1 (w!rx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (w!rx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (w!rx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +ENTRY(Reset_Handler) + +PHDRS +{ + text PT_LOAD; + ram PT_LOAD; + ram_init PT_LOAD; + tls PT_TLS; +} + +SECTIONS +{ + .init : { + KEEP (*(.vectors)) + KEEP (*(.text.init.enter)) + KEEP (*(.data.init.enter)) + KEEP (*(SORT_BY_NAME(.init) SORT_BY_NAME(.init.*))) + } >ROM0 AT>ROM0 :text + + .text : { + + /* code */ + *(.text.unlikely .text.unlikely.*) + *(.text.startup .text.startup.*) + *(.text .text.* .opd .opd.*) + *(.gnu.linkonce.t.*) + KEEP (*(.fini .fini.*)) + __text_end = .; + + PROVIDE (__etext = __text_end); + PROVIDE (_etext = __text_end); + PROVIDE (etext = __text_end); + + *(.gnu.linkonce.r.*) + + + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + *(.data.rel.ro .data.rel.ro.*) + *(.got .got.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + /* lists of constructors and destructors */ + PROVIDE_HIDDEN ( __preinit_array_start = . ); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN ( __preinit_array_end = . ); + + PROVIDE_HIDDEN ( __init_array_start = . ); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array .ctors)) + PROVIDE_HIDDEN ( __init_array_end = . ); + + PROVIDE_HIDDEN ( __fini_array_start = . ); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array .dtors)) + PROVIDE_HIDDEN ( __fini_array_end = . ); + + } >ROM0 AT>ROM0 :text + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .veneers : + { + . = ALIGN(32); + KEEP(*(.gnu.sgstubs)) + } > ROM0 AT>ROM0 :text +#endif + + .toc : { + *(.toc .toc.*) + } >ROM0 AT>ROM0 :text + + /* additional sections when compiling with C++ exception support */ + + .except_ordered : { + *(.gcc_except_table *.gcc_except_table.*) + KEEP (*(.eh_frame .eh_frame.*)) + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >ROM0 AT>ROM0 :text + + .except_unordered : { + . = ALIGN(8); + + PROVIDE(__exidx_start = .); + *(.ARM.exidx*) + PROVIDE(__exidx_end = .); + } >ROM0 AT>ROM0 :text + + + /* + * Data values which are preserved across reset + */ + .preserve (NOLOAD) : { + PROVIDE(__preserve_start__ = .); + KEEP(*(SORT_BY_NAME(.preserve.*))) + KEEP(*(.preserve)) + PROVIDE(__preserve_end__ = .); + } >RAM0 AT>RAM0 :ram + + .data : { + *(.data .data.*) + *(.gnu.linkonce.d.*) + + /* read-only data */ + *(.rdata) + *(.rodata .rodata.*) + + /* Need to pre-align so that the symbols come after padding */ + . = ALIGN(8); + + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.* .sdata2.*) + *(.gnu.linkonce.s.*) + } >RAM0 AT>ROM0 :ram_init + PROVIDE(__data_start = ADDR(.data)); + PROVIDE(__data_source = LOADADDR(.data)); + + /* Thread local initialized data. This gets + * space allocated as it is expected to be placed + * in ram to be used as a template for TLS data blocks + * allocated at runtime. We're slightly abusing that + * by placing the data in flash where it will be copied + * into the allocate ram addresses by the existing + * data initialization code in crt0 + */ + .tdata : { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE(__data_end = .); + PROVIDE(__tdata_end = .); + } >RAM0 AT>ROM0 :tls :ram_init + PROVIDE( __tls_base = ADDR(.tdata)); + PROVIDE( __tdata_start = ADDR(.tdata)); + PROVIDE( __tdata_source = LOADADDR(.tdata) ); + PROVIDE( __tdata_source_end = LOADADDR(.tdata) + SIZEOF(.tdata) ); + PROVIDE( __data_source_end = __tdata_source_end ); + PROVIDE( __tdata_size = SIZEOF(.tdata) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata),ALIGNOF(.tbss)) ); + + PROVIDE( __edata = __data_end ); + PROVIDE( _edata = __data_end ); + PROVIDE( edata = __data_end ); + PROVIDE( __data_size = __data_end - __data_start ); + PROVIDE( __data_source_size = __data_source_end - __data_source ); + + .tbss (NOLOAD) : { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } >RAM0 AT>RAM0 :tls :ram + PROVIDE( __bss_start = ADDR(.tbss)); + PROVIDE( __tbss_start = ADDR(.tbss)); + PROVIDE( __tbss_offset = ADDR(.tbss) - ADDR(.tdata) ); + PROVIDE( __tbss_size = SIZEOF(.tbss) ); + PROVIDE( __tls_size = __tls_end - __tls_base ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) ); + + /* + * The linker special cases .tbss segments which are + * identified as segments which are not loaded and are + * thread_local. + * + * For these segments, the linker does not advance 'dot' + * across them. We actually need memory allocated for tbss, + * so we create a special segment here just to make room + */ + /* + .tbss_space (NOLOAD) : { + . = ADDR(.tbss); + . = . + SIZEOF(.tbss); + } >RAM0 AT>RAM0 :ram + */ + + .bss (NOLOAD) : { + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + + /* Align the heap */ + . = ALIGN(8); + __bss_end = .; + } >RAM0 AT>RAM0 :ram + PROVIDE( __non_tls_bss_start = ADDR(.bss) ); + PROVIDE( __end = __bss_end ); + PROVIDE( _end = __bss_end ); + PROVIDE( end = __bss_end ); + PROVIDE( __bss_size = __bss_end - __bss_start ); + + /* Make the rest of memory available for heap storage */ + PROVIDE (__heap_start = __end); +#ifdef HEAP_SIZE + PROVIDE (__heap_end = __heap_start + HEAP_SIZE); + PROVIDE (__heap_size = HEAP_SIZE); +#else + PROVIDE (__heap_end = __stack - STACK_SIZE); + PROVIDE (__heap_size = __heap_end - __heap_start); +#endif + .heap (NOLOAD) : { + . += __heap_size; + } >RAM0 :ram + + /* Define a stack region to make sure it fits in memory */ + PROVIDE(__stack = ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE); + PROVIDE(__stack_limit = __stack - STACK_SIZE); + .stack (__stack_limit) (NOLOAD) : { + . += STACK_SIZE; + } >RAM0 :ram + +#if __STACKSEAL_SIZE > 0 + PROVIDE(__stack_seal = __stack); + .stackseal (__stack) (NOLOAD) : + { + . += __STACKSEAL_SIZE; + } >RAM0 :ram +#endif + + /* Throw away C++ exception handling information */ + + /* + + /DISCARD/ : { + *(.note .note.*) + *(.eh_frame .eh_frame.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + *(.ARM.exidx*) + } + + */ + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1. */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions. */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2. */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2. */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions. */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3. */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF 5. */ + .debug_addr 0 : { *(.debug_addr) } + .debug_line_str 0 : { *(.debug_line_str) } + .debug_loclists 0 : { *(.debug_loclists) } + .debug_macro 0 : { *(.debug_macro) } + .debug_names 0 : { *(.debug_names) } + .debug_rnglists 0 : { *(.debug_rnglists) } + .debug_str_offsets 0 : { *(.debug_str_offsets) } + .debug_sup 0 : { *(.debug_sup) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } +} +/* + * Check that sections that are copied from flash to RAM have matching + * padding, so that a single memcpy() of __data_size copies the correct bytes. + */ +ASSERT( __data_size == __data_source_size, + "ERROR: .data/.tdata flash size does not match RAM size"); diff --git a/Testing/board/linker_scripts/gcc_m0p_mps3.ld b/Testing/board/linker_scripts/gcc_m0p_mps3.ld new file mode 100644 index 0000000..a018e5d --- /dev/null +++ b/Testing/board/linker_scripts/gcc_m0p_mps3.ld @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/* ---------------------------------------------------------------------------- + Memory definition + *----------------------------------------------------------------------------*/ +MEMORY +{ + ROM0 (rx) : ORIGIN = __ROM0_BASE, LENGTH = __ROM0_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (rwx) : ORIGIN = __RAM0_BASE, LENGTH = __RAM0_SIZE +#if __RAM1_SIZE > 0 + RAM1 (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (rwx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (rwx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext (deprecated) + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.vectors)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > ROM0 + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .gnu.sgstubs : + { + . = ALIGN(32); + } > ROM0 +#endif + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ROM0 + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ROM0 + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + + /* Add each additional data section here */ +/* + LONG (LOADADDR(.data2)) + LONG (ADDR(.data2)) + LONG (SIZEOF(.data2) / 4) +*/ + __copy_table_end__ = .; + } > ROM0 + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + +/* .bss initialization to zero is already done during C Run-Time Startup. + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) +*/ + + /* Add each additional bss section here */ +/* + LONG (ADDR(.bss2)) + LONG (SIZEOF(.bss2) / 4) +*/ + __zero_table_end__ = .; + } > ROM0 + + /* + * This __etext variable is kept for backward compatibility with older, + * ASM based startup files. + */ + PROVIDE(__etext = LOADADDR(.data)); + + .data : ALIGN(4) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM0 AT > ROM0 + + /* + * Secondary data section, optional + * + * Remember to add each additional data section + * to the .copy.table above to assure proper + * initialization during startup. + */ +/* + .data2 : ALIGN(4) + { + . = ALIGN(4); + __data2_start__ = .; + *(.data2) + *(.data2.*) + . = ALIGN(4); + __data2_end__ = .; + + } > RAM1 AT > ROM0 +*/ + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM0 AT > RAM0 + + /* + * Secondary bss section, optional + * + * Remember to add each additional bss section + * to the .zero.table above to assure proper + * initialization during startup. + */ +/* + .bss2 : + { + . = ALIGN(4); + __bss2_start__ = .; + *(.bss2) + *(.bss2.*) + . = ALIGN(4); + __bss2_end__ = .; + } > RAM1 AT > RAM1 +*/ + + .heap (NOLOAD) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM0 + + .stack (ORIGIN(RAM0) + LENGTH(RAM0) - __STACK_SIZE - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM0 + PROVIDE(__stack = __StackTop); + +#if __STACKSEAL_SIZE > 0 + .stackseal (ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackSeal = .; + . = . + 8; + . = ALIGN(8); + } > RAM0 +#endif + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/Testing/board/linker_scripts/gcc_m4_mps3.ld b/Testing/board/linker_scripts/gcc_m4_mps3.ld new file mode 100644 index 0000000..a018e5d --- /dev/null +++ b/Testing/board/linker_scripts/gcc_m4_mps3.ld @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/* ---------------------------------------------------------------------------- + Memory definition + *----------------------------------------------------------------------------*/ +MEMORY +{ + ROM0 (rx) : ORIGIN = __ROM0_BASE, LENGTH = __ROM0_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (rwx) : ORIGIN = __RAM0_BASE, LENGTH = __RAM0_SIZE +#if __RAM1_SIZE > 0 + RAM1 (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (rwx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (rwx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext (deprecated) + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.vectors)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > ROM0 + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .gnu.sgstubs : + { + . = ALIGN(32); + } > ROM0 +#endif + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ROM0 + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ROM0 + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + + /* Add each additional data section here */ +/* + LONG (LOADADDR(.data2)) + LONG (ADDR(.data2)) + LONG (SIZEOF(.data2) / 4) +*/ + __copy_table_end__ = .; + } > ROM0 + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + +/* .bss initialization to zero is already done during C Run-Time Startup. + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) +*/ + + /* Add each additional bss section here */ +/* + LONG (ADDR(.bss2)) + LONG (SIZEOF(.bss2) / 4) +*/ + __zero_table_end__ = .; + } > ROM0 + + /* + * This __etext variable is kept for backward compatibility with older, + * ASM based startup files. + */ + PROVIDE(__etext = LOADADDR(.data)); + + .data : ALIGN(4) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM0 AT > ROM0 + + /* + * Secondary data section, optional + * + * Remember to add each additional data section + * to the .copy.table above to assure proper + * initialization during startup. + */ +/* + .data2 : ALIGN(4) + { + . = ALIGN(4); + __data2_start__ = .; + *(.data2) + *(.data2.*) + . = ALIGN(4); + __data2_end__ = .; + + } > RAM1 AT > ROM0 +*/ + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM0 AT > RAM0 + + /* + * Secondary bss section, optional + * + * Remember to add each additional bss section + * to the .zero.table above to assure proper + * initialization during startup. + */ +/* + .bss2 : + { + . = ALIGN(4); + __bss2_start__ = .; + *(.bss2) + *(.bss2.*) + . = ALIGN(4); + __bss2_end__ = .; + } > RAM1 AT > RAM1 +*/ + + .heap (NOLOAD) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM0 + + .stack (ORIGIN(RAM0) + LENGTH(RAM0) - __STACK_SIZE - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM0 + PROVIDE(__stack = __StackTop); + +#if __STACKSEAL_SIZE > 0 + .stackseal (ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackSeal = .; + . = . + 8; + . = ALIGN(8); + } > RAM0 +#endif + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/Testing/board/linker_scripts/gcc_sse300_mps3.ld b/Testing/board/linker_scripts/gcc_sse300_mps3.ld new file mode 100644 index 0000000..acc44ac --- /dev/null +++ b/Testing/board/linker_scripts/gcc_sse300_mps3.ld @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/* ---------------------------------------------------------------------------- + Memory definition + *----------------------------------------------------------------------------*/ +MEMORY +{ + ROM0 (rx) : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (rw) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE +#if S_DDR4_SIZE > 0 + RAM1 (rw) : ORIGIN = S_DDR4_START, LENGTH = S_DDR4_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (rw) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (rw) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext (deprecated) + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.vectors)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + /* *(.rodata*) */ + + KEEP(*(.eh_frame*)) + } > ROM0 + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .gnu.sgstubs : + { + . = ALIGN(32); + } > ROM0 +#endif + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ROM0 + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ROM0 + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + + /* Add each additional data section here */ +/* + LONG (LOADADDR(.data2)) + LONG (ADDR(.data2)) + LONG (SIZEOF(.data2) / 4) +*/ + __copy_table_end__ = .; + } > ROM0 + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + +/* .bss initialization to zero is already done during C Run-Time Startup. + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) +*/ + + /* Add each additional bss section here */ +/* + LONG (ADDR(.bss2)) + LONG (SIZEOF(.bss2) / 4) +*/ + __zero_table_end__ = .; + } > ROM0 + + /* + * This __etext variable is kept for backward compatibility with older, + * ASM based startup files. + */ + PROVIDE(__etext = LOADADDR(.data)); + + .data : ALIGN(4) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + *(.rodata*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM0 AT > ROM0 + + /* + * Secondary data section, optional + * + * Remember to add each additional data section + * to the .copy.table above to assure proper + * initialization during startup. + */ +/* + .data2 : ALIGN(4) + { + . = ALIGN(4); + __data2_start__ = .; + *(.data2) + *(.data2.*) + . = ALIGN(4); + __data2_end__ = .; + + } > RAM1 AT > ROM0 +*/ + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM0 AT > RAM0 + + /* + * Secondary bss section, optional + * + * Remember to add each additional bss section + * to the .zero.table above to assure proper + * initialization during startup. + */ +/* + .bss2 : + { + . = ALIGN(4); + __bss2_start__ = .; + *(.bss2) + *(.bss2.*) + . = ALIGN(4); + __bss2_end__ = .; + } > RAM1 AT > RAM1 +*/ + + .heap (NOLOAD) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM1 + + .stack (ORIGIN(RAM1) + LENGTH(RAM1) - STACK_SIZE - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM1 + PROVIDE(__stack = __StackTop); + +#if __STACKSEAL_SIZE > 0 + .stackseal (ORIGIN(RAM1) + LENGTH(RAM1) - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackSeal = .; + . = . + 8; + . = ALIGN(8); + } > RAM1 +#endif + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/Testing/board/linker_scripts/gcc_sse310_mps3_s.ld b/Testing/board/linker_scripts/gcc_sse310_mps3_s.ld new file mode 100644 index 0000000..7bea37e --- /dev/null +++ b/Testing/board/linker_scripts/gcc_sse310_mps3_s.ld @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2023 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ---------------------------------------------------------------------------- + Stack seal size definition + *----------------------------------------------------------------------------*/ +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#define __STACKSEAL_SIZE ( 8 ) +#else +#define __STACKSEAL_SIZE ( 0 ) +#endif + +/* ---------------------------------------------------------------------------- + Memory definition + *----------------------------------------------------------------------------*/ +MEMORY +{ + ROM0 (rx) : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE +#if __ROM1_SIZE > 0 + ROM1 (rx) : ORIGIN = __ROM1_BASE, LENGTH = __ROM1_SIZE +#endif +#if __ROM2_SIZE > 0 + ROM2 (rx) : ORIGIN = __ROM2_BASE, LENGTH = __ROM2_SIZE +#endif +#if __ROM3_SIZE > 0 + ROM3 (rx) : ORIGIN = __ROM3_BASE, LENGTH = __ROM3_SIZE +#endif + + RAM0 (rwx) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE +#if __RAM1_SIZE > 0 + RAM1 (rwx) : ORIGIN = __RAM1_BASE, LENGTH = __RAM1_SIZE +#endif +#if __RAM2_SIZE > 0 + RAM2 (rwx) : ORIGIN = __RAM2_BASE, LENGTH = __RAM2_SIZE +#endif +#if __RAM3_SIZE > 0 + RAM3 (rwx) : ORIGIN = __RAM3_BASE, LENGTH = __RAM3_SIZE +#endif +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext (deprecated) + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.vectors)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + /* *(.rodata*) */ + + KEEP(*(.eh_frame*)) + } > ROM0 + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + .gnu.sgstubs : + { + . = ALIGN(32); + } > ROM0 +#endif + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ROM0 + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ROM0 + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + + LONG (LOADADDR(.data)) + LONG (ADDR(.data)) + LONG (SIZEOF(.data) / 4) + + /* Add each additional data section here */ +/* + LONG (LOADADDR(.data2)) + LONG (ADDR(.data2)) + LONG (SIZEOF(.data2) / 4) +*/ + __copy_table_end__ = .; + } > ROM0 + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + +/* .bss initialization to zero is already done during C Run-Time Startup. + LONG (ADDR(.bss)) + LONG (SIZEOF(.bss) / 4) +*/ + + /* Add each additional bss section here */ +/* + LONG (ADDR(.bss2)) + LONG (SIZEOF(.bss2) / 4) +*/ + __zero_table_end__ = .; + } > ROM0 + + /* + * This __etext variable is kept for backward compatibility with older, + * ASM based startup files. + */ + PROVIDE(__etext = LOADADDR(.data)); + + .data : ALIGN(4) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + *(.rodata*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM0 AT > ROM0 + + /* + * Secondary data section, optional + * + * Remember to add each additional data section + * to the .copy.table above to assure proper + * initialization during startup. + */ +/* + .data2 : ALIGN(4) + { + . = ALIGN(4); + __data2_start__ = .; + *(.data2) + *(.data2.*) + . = ALIGN(4); + __data2_end__ = .; + + } > RAM1 AT > ROM0 +*/ + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM0 AT > RAM0 + + /* + * Secondary bss section, optional + * + * Remember to add each additional bss section + * to the .zero.table above to assure proper + * initialization during startup. + */ +/* + .bss2 : + { + . = ALIGN(4); + __bss2_start__ = .; + *(.bss2) + *(.bss2.*) + . = ALIGN(4); + __bss2_end__ = .; + } > RAM1 AT > RAM1 +*/ + + .heap (NOLOAD) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > RAM0 + + .stack (ORIGIN(RAM0) + LENGTH(RAM0) - STACK_SIZE - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > RAM0 + PROVIDE(__stack = __StackTop); + +#if __STACKSEAL_SIZE > 0 + .stackseal (ORIGIN(RAM0) + LENGTH(RAM0) - __STACKSEAL_SIZE) (NOLOAD) : + { + . = ALIGN(8); + __StackSeal = .; + . = . + 8; + . = ALIGN(8); + } > RAM0 +#endif + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/Testing/board/main.cpp b/Testing/board/main.cpp new file mode 100644 index 0000000..01618bd --- /dev/null +++ b/Testing/board/main.cpp @@ -0,0 +1,134 @@ +#include "RTE_Components.h" +#include CMSIS_device_header +#include "stdio.h" + +#if defined(MPS3) +#include "cmsis_driver_config.h" +#include "stdout_USART.h" +#endif + +#include +#include "common.h" +#include "load.hpp" + +#include +#include // for ostringstream + +volatile uint32_t nb_sys_tick_round=0; +#define MAX_SYSTICK 0xFFFFFFUL + +extern "C" { + void SysTick_Handler(void); +} + +void SysTick_Handler(void) { /* SysTick interrupt Handler. */ + nb_sys_tick_round++; /* See startup file startup_LPC17xx.s for SysTick vector */ +} + + +extern "C" uint32_t SystemCoreClock; + + +float time_in_ms() { + return(1000.0*(MAX_SYSTICK-SysTick->VAL + MAX_SYSTICK * nb_sys_tick_round)/SystemCoreClock); +} + +long time_in_cycles() { + return(MAX_SYSTICK - SysTick->VAL + MAX_SYSTICK * nb_sys_tick_round); +} + + + +extern void run_test(const unsigned char* inputs, + const uint32_t testid, + const uint32_t funcid, + unsigned char* &wbuf, + uint32_t &total_bytes); + +void run_test_group() +{ + long start,end; + const unsigned char* inputs = load_test_mem("test.dat"); + // List of tests + const uint32_t *tests_id = Buffer::read(inputs,0); + const uint32_t nb_tests = get_buffer_length(inputs,0) >> 2; + const uint32_t *enabled = Buffer::read(inputs,1); + + + for(uint32_t id = 0;id < nb_tests; id++) + { + if (enabled[id]) + { + uint32_t func_id = tests_id[id]; + unsigned char *outputs = nullptr; + uint32_t total_bytes; + + printf("Test %d\r\n",id); +#if defined (__ICACHE_PRESENT) + SCB_InvalidateICache(); +#endif +#if defined (__DCACHE_PRESENT) + SCB_InvalidateDCache(); +#endif + start = time_in_cycles(); + run_test(inputs,id,func_id,outputs,total_bytes); + end = time_in_cycles(); + printf("Cycles = %ld\r\n",end-start); + +#if !defined(NOOUTPUT) + if (outputs) + { + std::ostringstream out; + out << "results/output_" << id << ".dat"; + save_mem(out.str().c_str(),outputs,total_bytes); + + aligned_free((void*)outputs); + + } + else + { + printf("No output generated for %d\r\n",id); + } +#endif + printf("\r\n"); + } + } + + +} + + + +int main(void) +{ + int systick_status = 0; + +#if defined(MPS3) + stdout_init(); +#endif + + +#if defined (__ICACHE_PRESENT) + SCB_EnableICache(); +#endif + +#if defined (__DCACHE_PRESENT) + SCB_EnableDCache(); +#endif + + systick_status = SysTick_Config(MAX_SYSTICK); + if (systick_status != 0) + { + printf("Can't enable SysTick\r\n"); + } + + run_test_group(); + + + printf(__TIME__"\r\n"); + printf("END_TEST\r\n"); + + +} + + diff --git a/Testing/board/runall.py b/Testing/board/runall.py new file mode 100644 index 0000000..53c1d98 --- /dev/null +++ b/Testing/board/runall.py @@ -0,0 +1,380 @@ +import argparse +import pickle +import sys +import subprocess +import os +import colorama +import glob +import sys + +oldprint = print + +from rich import print +from rich.live import Live +from rich.table import Table + + +from scripts.export import * +from scripts.test_utils import * +from test_desc import * + +from pathlib import Path + +Path("references").mkdir(parents=True, exist_ok=True) +Path("inputs").mkdir(parents=True, exist_ok=True) +Path("results/img").mkdir(parents=True, exist_ok=True) + +parser = argparse.ArgumentParser(description='Parse test description') +parser.add_argument('-avh', nargs='?',type = str, default="C:/Keil_v5/ARM/VHT", help="AVH folder") +parser.add_argument('-d', action='store_true', help="Debug log for command launch") +parser.add_argument('-n', action='store_true', help="No force rebuild") +parser.add_argument('--gen', action='store_true', help="Generate inputs and references") +parser.add_argument('--results', action='store_true', help="Generate test result images") +parser.add_argument('--dev', action='store_true', help="Kernel development mode") + +# In norun, the .dat is generated and the project build +# but no AVH is run +parser.add_argument('--norun', action='store_true', help="Don't run in dev mode") + +parser.add_argument('--group', nargs='?',type = int, default=None, help="Only test group to run") +parser.add_argument('--test', nargs='?',type = int, default=None, help="Only test to run in a test group") + +args = parser.parse_args() + + +DEBUG=False +if args.d: + DEBUG=True + + +sys.path.append("..") + +ERROR_OCCURED = False + +def printTitle(s): + print(f"\n[bold green]{s}[/bold green]") + +def printSubTitle(s): + print(f"\n[bold yellow]{s}[/bold yellow]") + +def printError(s): + print(f"\n[bold red]{s}[/bold red]") + +def printMessage(s): + print(f"\n[bold cyan]{s}[/bold cyan]") + + +def getTitle(l,s): + return(f"\n[bold green]{s}[/bold green]") + +def getSubTitle(l,s): + return(f"\n[bold yellow]{s}[/bold yellow]") + +def getError(l,s): + return(f"\n[bold red]{s}[/bold red]") + +def getMessage(l,s): + return(f"\n[bold cyan]{s}[/bold cyan]") + +class Result: + def __init__(self,msg,error=False): + self._error = error + self._msg = msg + + @property + def error(self): + return self._error + + @property + def msg(self): + return self._msg + + + +# Run a command and get error or result +# For the test report we don't need the stderr +# in case of error since the test report is giving +# all the details. So, there is an option to +# disable the dump of stderr +def run(*args,mustPrint=False,dumpStdErr=True,live=None): + global ERROR_OCCURED + global DEBUG + try: + if DEBUG: + live.console.print(" ".join(args)) + result=subprocess.run(args,text=True,capture_output=True,timeout=600) + if result.returncode !=0 : + ERROR_OCCURED = True + if dumpStdErr: + return(Result(result.stderr + "\n\nSTDOUT:\n\n" + result.stdout,error=True)) + else: + return(Result(result.stdout,error=True)) + + if mustPrint: + live.console.print(result.stdout) + return(Result(result.stdout)) + except Exception as e: + printError(live,"Exception occured") + ERROR_OCCURED = True + return(Result(str(e),error=True)) + + + + + +# Configuration file for AVH core +configFiles={ + "CS300":"VHT-Corstone-300.txt", + "M7DP":"VHT-M7DP.txt", + "M4FP":"VHT-M4.txt", + "M0plus":"VHT-M0P.txt", +} + +# Windows executable +# (At some point this script will also support +# unix) +avhExe={ + "CS310":"VHT_Corstone_SSE-310.exe", + "CS300":"VHT_Corstone_SSE-300_Ethos-U55.exe", + "M55":"VHT_MPS2_Cortex-M55.exe", + "M33_DSP_FP":"VHT_MPS2_Cortex-M33.exe", + "M7DP":"VHT_MPS2_Cortex-M7.exe", + "M4FP":"VHT_MPS2_Cortex-M4.exe", + "M3":"VHT_MPS2_Cortex-M3.exe", + "M23":"VHT_MPS2_Cortex-M23.exe", + "M0plus":"VHT_MPS2_Cortex-M0plus.exe", +} + +AVHROOT = args.avh + +# Run AVH +def runAVH(live,build,core): + axf="cprj/out/cmsiscv/%s/Release/cmsiscv.axf" % (build,) + elf="cprj/out/cmsiscv/%s/Release/cmsiscv.elf" % (build,) + app = axf + if os.path.exists(axf): + app = axf + if os.path.exists(elf): + app = elf + config = os.path.join("fvp_configs",configFiles[core]) + avh = os.path.join(AVHROOT,avhExe[core]) + res=run(avh,"-f",config,app,live=live) + return(res) + +def clean_old_results(): + g = glob.glob("results/*.dat") + for f in g: + os.remove(f) + + +# Solution and build file for all +# the tests +# It is a pair : csolution target type and AVH identification +# AVH identification is used to find the executable +# and the configuration file +compiler={ + 'AC6':[ + ("VHT-Corstone-300","CS300"), + # No core config for running on AVH so it is a board run + #("MPS3-Corstone-300",), + ("VHT-M4","M4FP"), + ("VHT-M7","M7DP"), + ], + #'CLANG':[ + # ("VHT-Corstone-300","CS300"), + #], + 'GCC':[ + ("VHT-Corstone-300","CS300"), + ] +} + +HTMLHEADER=""" +
+CMSIS-CV Test summary +
+ +""" + +HTMLFOOTER=""" + +""" + +# We can select a specific test only when a specific group has been selected +if args.group is None: + args.test = None + + + +def gen_table(the_list): + table = Table() + table.add_column("Compiler",width=15,vertical="top") + table.add_column("Target",width=25,vertical="top") + table.add_column("Test Group",width=20,vertical="top") + table.add_column("Status",width=20,vertical="top") + + for i in the_list: + table.add_row(*i) + return table + +if args.dev: + args.results = True + printMessage("Kernel development mode enabled") + allSuites = mk_test_suite_from_dev(devTest) + #print(allSuites) +if args.gen: + printMessage("Generate input images") + # Generate all input images for all test groups + # Can be used for debugging an error + for group_id,testSuite in enumerate(allSuites): + print(f"Generate group {group_id}") + clean_input_images(args,group_id) + generate_input_images(args,group_id,testSuite) + + printMessage("Generate reference images") + # Generate all reference images + for group_id,testSuite in enumerate(allSuites): + print(f"Generate group {group_id}") + clean_reference_images(args,group_id) + generate_reference_images(args,group_id,testSuite) + +if args.results: + printMessage("Result images will be recorded (images or .npy files)") + +if args.n: + printMessage("Solution will not be fully rebuilt") + print("It is ok if you don't mix different target and compilers") + +if args.norun: + printMessage("Tests won't be executed") + +if not args.group is None: + printMessage(f"Only group {args.group} will be built/run") + if not args.test is None: + printMessage(f"Only test {args.test} will be built/run") + +# Run the tests and log the result +# in a summary.html file + +MAX_ROWS=4 +latest=[] +with Live(gen_table([]), refresh_per_second=4) as live: + + with open("summary.html","w") as f: + print(HTMLHEADER,file=f) + nb_compilers = len(compiler) + for compid,c in enumerate(compiler): + #printTitle(live,f"Process compiler {c} ({compid+1}/{nb_compilers})") + tableCompiler = getTitle(live,f"{c} ({compid+1}/{nb_compilers})") + #if res.error: + # printError("Error csolution") + # print("

Error converting csolution %s

" % s,file=f)
+            #    print(res.msg,file=f)
+            #    print("
",file=f) + # continue + print("

Compiler %s

" % c,file=f) + maxNbBuilds=len(compiler[c]) + buildNb=0 + for target_core in compiler[c]: + if len(target_core)>1: + build,core = target_core + else: + build = target_core[0] + core = None + buildNb = buildNb + 1 + print("

Target %s

" % build,file=f) + #printTitle(live,"Process target %s (%d/%d)" % (build,buildNb,maxNbBuilds)) + tableTarget = getTitle(live,"%s (%d/%d)" % (build,buildNb,maxNbBuilds)) + buildFile="cmsiscv.Release+%s" % build + maxNb = len(allSuites) + + + for group_id,testSuite in enumerate(allSuites): + if (len(latest)>MAX_ROWS): + latest=latest[1:] + + if (args.group is None) or args.group == group_id: + if args.group is None: + #printSubTitle(live,f'Process group : {testSuite["name"]} ({group_id+1}/{maxNb})') + tableGroup=getSubTitle(live,f'{testSuite["name"]} ({group_id+1}/{maxNb})') + else: + #printSubTitle(live,f'Process group : {testSuite["name"]}') + tableGroup=getSubTitle(live,f'{testSuite["name"]}') + latest.append([tableCompiler,tableTarget,tableGroup,"?"]) + + imgs = prepare_tests_group(args,group_id,testSuite) + #live.console.print("Building ...") + msg = "Building..." + latest[-1][-1]=msg + if (not args.group is None or group_id==0): + # -r is needed for first + # build when we switch + # between different solutions + # (Like one using AC6 and the other + # using gcc) + if args.n: + #live.console.print("Incremental build") + msg += " Incremental build" + latest[-1][-1]=msg + live.update(renderable=gen_table(latest)) + res=run("cbuild","-O" ,"cprj",'cmsiscv.csolution.yml',"--toolchain" ,c,"-c",buildFile,live=live) + else: + #live.console.print("Rebuild all (and RTE update)") + msg += " Rebuild all (and RTE update)" + latest[-1][-1]=msg + live.update(renderable=gen_table(latest)) + res=run("cbuild","-O" ,"cprj",'cmsiscv.csolution.yml',"--update-rte","-r","--toolchain" ,c,"-c",buildFile,live=live) + else: + #live.console.print("Incremental build") + msg += " Incremental build" + latest[-1][-1]=msg + live.update(renderable=gen_table(latest)) + res=run("cbuild","-O" ,"cprj",'cmsiscv.csolution.yml',"--toolchain" ,c,"-c",buildFile,live=live) + + + if res.error: + latest[-1][-1]="[red]Error cbuild" + live.update(renderable=gen_table(latest)) + #printError(live,"Error cbuild") + print(f'

Error building {testSuite["name"]}

',file=f)
+                           print(res.msg,file=f)
+                           print("
",file=f) + continue + if not args.norun and (not core is None): + latest[-1][-1]="Run AVH" + live.update(renderable=gen_table(latest)) + #printSubTitle(live,"Run AVH") + clean_old_results() + res=runAVH(live,build,core) + if res.error: + latest[-1][-1]="[red]Error running AVH" + live.update(renderable=gen_table(latest)) + #printError(live,"Error running AVH") + print("

Error running %s

" % s,file=f)
+                               print(res.msg,file=f)
+                               print("
",file=f) + continue + else: + had_error = validate_test_group(args,c,build,group_id,testSuite,imgs,f) + if had_error: + ERROR_OCCURED = True + latest[-1][-1]="[red]Failed" + live.update(renderable=gen_table(latest)) + continue + # In case of no issue, we drop the status + # Status table only contain failure + latest=latest[:-1] + live.update(renderable=gen_table(latest)) + + + print(HTMLFOOTER,file=f) + +# Refresh cursor +oldprint('\033[?25h', end="") + +if ERROR_OCCURED: + sys.exit("Error occurred") +else: + sys.exit(0) + + + diff --git a/Testing/board/scripts/__init__.py b/Testing/board/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Testing/board/scripts/convert_to_c.py b/Testing/board/scripts/convert_to_c.py new file mode 100644 index 0000000..a9a974d --- /dev/null +++ b/Testing/board/scripts/convert_to_c.py @@ -0,0 +1,72 @@ +import argparse +from .export import serialize_tensors,read_tensors + + +def convert(filename,name,input): + with open(input,"rb") as f: + res = f.read() + + COLS = 10 + with open(f"{filename}.c","w") as c: + nb = 0 + l = len(res) + print(f"""#include "{filename}.h" +#include "arm_math_types.h" + +#ifndef ALIGN_NETWORK +#define ALIGN_NETWORK __ALIGNED(16) +#endif + +#if defined(CINPUT) +""",file=c) + print("ALIGN_NETWORK",file=c) + print(f"const uint8_t {name}[NB_{name.upper()}]={{",file=c,end="") + for b in res: + print("0x%02x," % b,file=c,end="") + nb = nb + 1 + if (nb == COLS): + nb = 0 + print("",file=c) + print("};",file=c) + print("#endif",file=c) + + with open(f"{filename}.h","w") as c: + nb = 0 + l = len(res) + print(f"""#ifndef {name.upper()}_H +#define {name.upper()}_H + +#include "arm_math_types.h" + +#ifdef __cplusplus +extern "C" +{{ +#endif + +#if defined(CINPUT) + """,file=c) + print(f"#define NB_{name.upper()} {l}",file=c) + print(f"extern const uint8_t {name}[NB_{name.upper()}];",file=c) + + print(""" +#endif + +#ifdef __cplusplus +} +#endif +""",file=c) + + print("#endif",file=c) + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + prog='convert_to_c', + description='Convert network to a C array') + + parser.add_argument('filename') + parser.add_argument('-n', '--name',default="network") + parser.add_argument('-i', '--input') + + args = parser.parse_args() + + convert(args.filename,args.name,args.i) \ No newline at end of file diff --git a/Testing/board/scripts/export.py b/Testing/board/scripts/export.py new file mode 100644 index 0000000..ba19f7e --- /dev/null +++ b/Testing/board/scripts/export.py @@ -0,0 +1,411 @@ +import numpy as np +import struct +from PIL import Image +import PIL +import numpy as np +import os + +def _serialize_u32(file, tensor): + """ writes one uint32 tensor to file that is open in wb mode """ + tensor = tensor.astype(np.uint32).flatten() + b = struct.pack(f'{len(tensor)}L', *tensor) + file.write(b) + return(len(b)) + +def _serialize_u16(file, tensor): + """ writes one uint32 tensor to file that is open in wb mode """ + tensor = tensor.astype(np.uint16).flatten() + b = struct.pack(f'{len(tensor)}H', *tensor) + file.write(b) + return(len(b)) + +def _serialize_u8(file, tensor): + """ writes one f32 tensor to file that is open in wb mode """ + tensor = tensor.astype(np.uint8).flatten() + b = struct.pack(f'{len(tensor)}B', *tensor) + file.write(b) + return(len(b)) + +def _serialize_s32(file, tensor): + """ writes one uint32 tensor to file that is open in wb mode """ + tensor = tensor.astype(np.uint32).flatten() + b = struct.pack(f'{len(tensor)}l', *tensor) + file.write(b) + return(len(b)) + +def _serialize_s16(file, tensor): + """ writes one uint32 tensor to file that is open in wb mode """ + tensor = tensor.astype(np.uint16).flatten() + b = struct.pack(f'{len(tensor)}h', *tensor) + file.write(b) + return(len(b)) + +def _serialize_s8(file, tensor): + """ writes one f32 tensor to file that is open in wb mode """ + tensor = tensor.astype(np.uint8).flatten() + b = struct.pack(f'{len(tensor)}b', *tensor) + file.write(b) + return(len(b)) + +def _serialize_f64(file, tensor): + """ writes one f32 tensor to file that is open in wb mode """ + tensor = tensor.astype(np.double).flatten() + b = struct.pack(f'{len(tensor)}d', *tensor) + file.write(b) + return(len(b)) + +def _serialize_f32(file, tensor): + """ writes one f32 tensor to file that is open in wb mode """ + tensor = tensor.astype(float).flatten() + b = struct.pack(f'{len(tensor)}f', *tensor) + file.write(b) + return(len(b)) + +def _serialize_f16(file, tensor): + """ writes one f32 tensor to file that is open in wb mode """ + tensor = tensor.astype(np.float16).flatten() + b = struct.pack(f'{len(tensor)}e', *tensor) + file.write(b) + return(len(b)) + + +def _read_uint32_array(file,nb): + b = file.read(4*nb) + a = struct.unpack(f'{nb}L', b) + return(list(a)) + +def _read_uint16_array(file,nb): + b = file.read(2*nb) + a = struct.unpack(f'{nb}H', b) + return(list(a)) + +def _read_uint8_array(file,nb): + b = file.read(nb) + a = struct.unpack(f'{nb}B', b) + return(list(a)) + +def _read_sint32_array(file,nb): + b = file.read(4*nb) + a = struct.unpack(f'{nb}l', b) + return(list(a)) + +def _read_sint16_array(file,nb): + b = file.read(2*nb) + a = struct.unpack(f'{nb}h', b) + return(list(a)) + +def _read_sint8_array(file,nb): + b = file.read(nb) + a = struct.unpack(f'{nb}b', b) + return(list(a)) + +def _read_f64_array(file,nb): + b = file.read(8*nb) + a = struct.unpack(f'{nb}d', b) + return(list(a)) + +def _read_f32_array(file,nb): + b = file.read(4*nb) + a = struct.unpack(f'{nb}f', b) + return(list(a)) + +def _read_f16_array(file,nb): + b = file.read(2*nb) + a = struct.unpack(f'{nb}e', b) + return(list(a)) + +# This iw the general image type used for the test +# It can contain a Pillow RGB or GRAY8 image +# or a numpy tensor (shape must have at most 4 dimensions) +class AlgoImage: + IMG_RGB_TYPE = 0 + IMG_GRAY8_TYPE = 1 + IMG_NUMPY_TYPE_UINT8 = 2 + IMG_NUMPY_TYPE_UINT16 = 3 + IMG_NUMPY_TYPE_UINT32 = 4 + IMG_NUMPY_TYPE_SINT8 = 5 + IMG_NUMPY_TYPE_SINT16 = 6 + IMG_NUMPY_TYPE_SINT32 = 7 + IMG_NUMPY_TYPE_F16 = 8 + IMG_NUMPY_TYPE_F32 = 9 + IMG_NUMPY_TYPE_F64 = 10 + + @classmethod + def open(cls, path): + file_name, file_extension = os.path.splitext(path) + if file_extension == ".npy": + return AlgoImage(np.load(path)) + else: + return AlgoImage(PIL.Image.open(path)) + + def __init__(self,img): + self._img = img + + def save(self,path): + file_name, file_extension = os.path.splitext(path) + if self.is_image: + self.img.save(file_name + ".tiff") + else: + np.save(file_name + ".npy",self.tensor) + + + + @property + def is_image(self): + return not isinstance(self._img,np.ndarray) + + @property + def dtype(self): + if self.is_image: + if self._img.mode == "RGB": + return AlgoImage.IMG_RGB_TYPE + elif self._img.mode == "L": + return AlgoImage.IMG_GRAY8_TYPE + else: + raise NameError(f"Unsupported image mode {self._img.mode}") + elif isinstance(self._img,np.ndarray): + if self._img.dtype == np.uint8: + return AlgoImage.IMG_NUMPY_TYPE_UINT8 + if self._img.dtype == np.uint16: + return AlgoImage.IMG_NUMPY_TYPE_UINT16 + if self._img.dtype == np.uint32: + return AlgoImage.IMG_NUMPY_TYPE_UINT32 + if self._img.dtype == np.int8: + return AlgoImage.IMG_NUMPY_TYPE_SINT8 + if self._img.dtype == np.int16: + return AlgoImage.IMG_NUMPY_TYPE_SINT16 + if self._img.dtype == np.int32: + return AlgoImage.IMG_NUMPY_TYPE_SINT32 + if self._img.dtype == np.float16: + return AlgoImage.IMG_NUMPY_TYPE_F16 + if self._img.dtype == float: + return AlgoImage.IMG_NUMPY_TYPE_F32 + if self._img.dtype == np.double: + return AlgoImage.IMG_NUMPY_TYPE_F64 + + raise NameError(f"Unsupported datatype {self._img}") + + + @property + def dim(self): + t = list(self.tensor.shape) + r = len(t) + return ([r] + t + [0]*(4-r)) + + @property + def get_size(self): + return self.tensor.nbytes + + @property + def tensor(self): + if self.is_image: + buf = np.array(self._img) + return(buf) + else: + return(self._img) + + @property + def img(self): + return self._img + + + def serialize(self,file): + t = self.tensor + if t.dtype == np.uint8: + return _serialize_u8(file,t) + if t.dtype == np.uint16: + return _serialize_u16(file,t) + if t.dtype == np.uint32: + return _serialize_u32(file,t) + + if t.dtype == np.int8: + return _serialize_s8(file,t) + if t.dtype == np.int16: + return _serialize_s16(file,t) + if t.dtype == np.int32: + return _serialize_s32(file,t) + + if t.dtype == np.float16: + return _serialize_f16(file,t) + if t.dtype == float: + return _serialize_f32(file,t) + if t.dtype == np.double: + return _serialize_f64(file,t) + + raise NameError(f"Unsupported NumPy datatype for serialization {t.dtype}") + + +def unserialize(file,dt,nbbytes,dims): + a = bytes(_read_uint8_array(file,nbbytes)) + if dt == AlgoImage.IMG_NUMPY_TYPE_UINT8: + res = np.frombuffer(a,dtype=np.uint8).reshape(dims) + elif dt == AlgoImage.IMG_NUMPY_TYPE_UINT16: + res = np.frombuffer(a,dtype=np.uint16).reshape(dims) + elif dt == AlgoImage.IMG_NUMPY_TYPE_UINT32: + res = np.frombuffer(a,dtype=np.uint32).reshape(dims) + elif dt == AlgoImage.IMG_NUMPY_TYPE_SINT8: + res = np.frombuffer(a,dtype=np.int8).reshape(dims) + elif dt == AlgoImage.IMG_NUMPY_TYPE_SINT16: + res = np.frombuffer(a,dtype=np.int16).reshape(dims) + elif dt == AlgoImage.IMG_NUMPY_TYPE_SINT32: + res = np.frombuffer(a,dtype=np.int32).reshape(dims) + elif dt == AlgoImage.IMG_NUMPY_TYPE_F16: + res = np.frombuffer(a,dtype=np.float16).reshape(dims) + elif dt == AlgoImage.IMG_NUMPY_TYPE_F32: + res = np.frombuffer(a,dtype=float).reshape(dims) + elif dt == AlgoImage.IMG_NUMPY_TYPE_F64: + res = np.frombuffer(a,dtype=np.double).reshape(dims) + elif dt == AlgoImage.IMG_RGB_TYPE: + res = Image.frombytes('RGB',(dims[1],dims[0]),a) + elif dt == AlgoImage.IMG_GRAY8_TYPE: + res = Image.frombytes('L',(dims[1],dims[0]),a) + else: + raise NameError(f"Unsupported NumPy datatype for unserialization {dt}") + + return(AlgoImage(res)) + + +def _align(file,pos,alignment): + r = pos % alignment + if r != 0: + r = alignment - r + z = np.zeros(r,dtype=np.uint8) + #z = np.ones(r,dtype=np.uint8)*255 + res = struct.pack(f'{len(z)}B', *z) + file.write(res) + return(r) + + +def serialize_tensors(file,tensors,alignment=8): + """ + Serialize the tensors to a binary file with alignment. + + The format is as simple as possible and with enouhg information + to be able to read the samples back with Python. + + The shapes and strides are not saved. The C code using this data + has the knowledge of the shapes and strides. + + The format is: + Nb of tensors : uint32 + Array of uint32 lengths for each tensor. Length expressed in bytes. + Array of uint32 shape for each tensor. Shape is 5 word32 + Number of dimensions. The dimensions. Padded with 0 if less than 4 dimensions + Array of uint32 datatype (to be able to read back with Python) + Array of uint32 offset in the file where to find the tensor + Aligned tensor follows + """ + pos = 0 + + # Write number of tensors + pos += _serialize_u32(file,np.array([len(tensors)])) + + # Write lengths of the tensors + lengths_in_bytes=np.array([x.get_size for x in tensors],dtype=np.uint32) + pos += _serialize_u32(file,lengths_in_bytes) + #print(lengths_in_bytes) + + dims = [] + for x in tensors: + dims += x.dim + dims=np.array(dims,dtype=np.uint32) + #print(dims) + + # Write dimensions of the images + # 0,0 when it is not an image + pos += _serialize_u32(file,dims) + + # Write datatypes of tensors + dt=np.array([x.dtype for x in tensors],dtype=np.uint32) + pos += _serialize_u32(file,dt) + #print(dt) + + # Offsets of tensors in files + offset_pos = pos + offsets=np.zeros(len(tensors),dtype=np.uint32) + # Write offsets of the tensors + pos += _serialize_u32(file,offsets) + pos += _align(file,pos,alignment) + + # Write tensors + k = 0 + for t in tensors: + offsets[k] = pos + pos += t.serialize(file) + + k = k + 1 + if k != len(tensors): + pos += _align(file,pos,alignment) + + file.seek(offset_pos) + _serialize_u32(file,offsets) + #print(offsets) + +def _read_uint32(file): + b = file.read(4) + nb_tensors = struct.unpack(f'L', b) + return(nb_tensors[0]) + + +def format_shape(l): + nb = l[0] + return tuple(l[1:1+nb]) + +def read_tensors(file): + res = [] + nb=_read_uint32(file) + tensor_sizes = _read_uint32_array(file,nb) + shapes = np.array(_read_uint32_array(file,5*nb)) + shapes = shapes.reshape(nb,5) + tensor_dims = [format_shape(s) for s in shapes] + tensor_dt = _read_uint32_array(file,nb) + + #print(nb) + #print(tensor_sizes) + #print(tensor_dims) + #print(tensor_dt) + + tensor_offsets = _read_uint32_array(file,nb) + + #print(tensor_offsets) + + + for s,dims,dt,o in zip(tensor_sizes,tensor_dims,tensor_dt,tensor_offsets): + # Position at tensor offset + file.seek(o) + + a = unserialize(file,dt,s,dims) + + res.append(a) + + return(res) + + +if __name__ == "__main__": + from pathlib import Path + + Path("references").mkdir(parents=True, exist_ok=True) + + imga = Image.open("Patterns/Mandrill_cropped.tiff") + #NB = 50 + #imga = imga.crop((NB,0,512-NB,512)) + #imga.save("Patterns/Mandrill_cropped.tiff") + imgb = Image.open("Patterns/JellyBeans.tiff") + imgb = imgb.convert("L") + + imga.save("results/img/input_0.tiff") + imgb.save("results/img/input_1.tiff") + + tests = AlgoImage(np.array(range(10),dtype=np.uint32).reshape(2,5)) + + with open("test.dat","wb") as f: + serialize_tensors(f,[tests,AlgoImage(imga),AlgoImage(imgb)]) + + + with open("test.dat","rb") as f: + r = read_tensors(f) + + for i in r: + #print(i.dim) + if i.is_image: + i.img.show() \ No newline at end of file diff --git a/Testing/board/scripts/requirements.txt b/Testing/board/scripts/requirements.txt new file mode 100644 index 0000000..9832f1f --- /dev/null +++ b/Testing/board/scripts/requirements.txt @@ -0,0 +1,4 @@ +numpy == 1.26.4 +colorama == 0.4.6 +opencv-python == 4.9.0.80 +pillow == 10.2.0 diff --git a/Testing/board/scripts/test_details.py b/Testing/board/scripts/test_details.py new file mode 100644 index 0000000..0f71f1e --- /dev/null +++ b/Testing/board/scripts/test_details.py @@ -0,0 +1,102 @@ +from .test_utils import * +import cv2 as cv + +class GenTensor: + def __init__(self,a,b,c,the_type): + self._tensor = np.ones((a,b,c),dtype=the_type) + + def __call__(self): + return [AlgoImage(self._tensor)] + + @property + def nb_images(self): + return 1 + + +# Functions and classes used to describe details of the tests +# on the Python side like: +# How to generate reference for a given test +# How to validate a test +# + +class IdenticalTensor(Comparison): + def __call__(self,ref,result): + for s,d in zip(ref,result): + if not np.array_equal(s.tensor,d.tensor): + self.add_error("Different tensors") + return False + return(True) + + +class IdenticalImage(Comparison): + def __call__(self,ref,result): + return same_images(self,ref,result) + +class SimilarTensor(Comparison): + def __init__(self,r=1e-05,a=1e-08): + super().__init__() + + self._r = r + self._a = a + + def __call__(self,ref,result): + for s,d in zip(ref,result): + if not np.isclose(s.tensor,d.tensor,rtol=self._r,atol=self._a).all(): + diff = np.abs(s.tensor-d.tensor) + errorVal = np.max(diff) + self.add_error(f"Different tensors. Max error = {errorVal}") + return False + return(True) + +class SimilarTensorFixp(Comparison): + def __init__(self,t=0): + super().__init__() + + self._t = t + + def __call__(self,ref,result): + for s,d in zip(ref,result): + diff = np.abs(s.tensor-d.tensor) + errorVal = np.max(diff) + if errorVal > self._t: + self.add_error(f"Different tensors. Max error = {errorVal}") + return False + return(True) + +# Generation of references + +# Must return references for given inputs +# and number of references returned. +class CopyInput: + def __call__(self,args,group_id,test_id,srcs): + for image_id,img in enumerate(srcs): + record_reference_img(args,group_id,test_id,image_id,img) + + def nb_references(self,srcs): + return len(srcs) + +class GaussianFilter: + def __call__(self,args,group_id,test_id,srcs): + filtered = [] + for i in srcs: + # Extract the image from the AlgoImage and blur it + # OpenCv can work with NumPy array but not with Pillow image + blur = cv.GaussianBlur(i.tensor,(3,3),0,0,cv.BORDER_REPLICATE) + # Pack the image in an AlgoImage and add it to the reference patterns + # If we get the blur as it is, it will be recorded as an .npy file + # It would be simpler with a gray8 as tiff image + # So we need to convert back to Pillow + #pil = PIL.Image.fromarray(blur) + #filtered.append(AlgoImage(pil)) + # + # Our gaussian return a q15 so we can't use a Pillow picture. + # We convert the result and write is as .npy + blur= blur.astype(np.int16)*127 + filtered.append(AlgoImage(blur)) + + # Record the filtered images + for image_id,img in enumerate(filtered): + record_reference_img(args,group_id,test_id,image_id,img) + + def nb_references(self,srcs): + return len(srcs) \ No newline at end of file diff --git a/Testing/board/scripts/test_utils.py b/Testing/board/scripts/test_utils.py new file mode 100644 index 0000000..b9f9012 --- /dev/null +++ b/Testing/board/scripts/test_utils.py @@ -0,0 +1,342 @@ +from PIL import ImageOps +import PIL +import numpy as np +from pathlib import Path +import glob + +# Start of input tensors +TENSOR_START = 2 + +from .export import * +from .convert_to_c import convert + +class Format: + GRAY8 = 0 + RGB = 1 + +class Image: + def __init__(self,dims,format=Format.GRAY8,path=None): + self._path = path + self._dims = dims + self._format = format + + + def __call__(self): + res = [] + img = PIL.Image.open(self._path) + if self._format == Format.GRAY8: + img = img.convert("L") + elif self._format == Format.RGB: + img = img.convert("RGB") + + for d in self._dims: + img = ImageOps.pad(img, d, color="#fff") + + res.append(AlgoImage(img)) + + return res + + + @property + def nb_images(self): + return len(self._dims) + + + + +class Comparison: + + def __init__(self): + self._errors = "" + + @property + def errors(self): + return self._errors + + def add_error(self,err): + self._errors += err + "\n"; + + + def check(self,src,dst): + return True + +# Assume the AlgoImage is containing an image +# and not a numpy +# +def _same_img_type(self,src,dst): + if (src.img.mode != dst.img.mode): + self.add_error("Different image types") + return False + + if (src.img.width != dst.img.width): + self.add_error("Different image widths") + return False + + if (src.img.height != dst.img.height): + self.add_error("Different image heights") + return False + + return(True) + +# Assume AlgoImage aare containing PIL images +def same_images(self,src,dst): + if len(src) != len(dst): + self.add_error("Different image list lengths") + return False + + for s,d in zip(src,dst): + if not _same_img_type(self,s,d): + return False + if list(s.img.getdata()) != list(d.img.getdata()): + self.add_error("Different image content") + return False + + return True + +def check_tiff_or_npy(path): + if Path(path + ".tiff").is_file(): + path += ".tiff" + else: + path += ".npy" + return(path) + +# Management of input images +def get_input_img(args,group_id,image_id): + if args.dev: + path = f"inputs/dev/img_{image_id}" + else: + path = f"inputs/group_{group_id}/img_{image_id}" + + path = check_tiff_or_npy(path) + return (AlgoImage.open(path)) + +def clean_input_images(args,group_id): + if args.dev: + Path(f"inputs/dev").mkdir(parents=True, exist_ok=True) + path = f"inputs/dev/" + else: + Path(f"inputs/group_{group_id}").mkdir(parents=True, exist_ok=True) + path = f"inputs/group_{group_id}" + + g = glob.glob(f"{str(path)}/*.tiff") + for f in g: + if args.d: + print(f"Remove {f}") + os.remove(f) + + g = glob.glob(f"{str(path)}/*.npy") + for f in g: + if args.d: + print(f"Remove {f}") + os.remove(f) + +def record_input_img(args,group_id,image_id,image): + if args.dev: + Path(f"inputs/dev").mkdir(parents=True, exist_ok=True) + path = f"inputs/dev/img_{image_id}" + else: + Path(f"inputs/group_{group_id}").mkdir(parents=True, exist_ok=True) + path = f"inputs/group_{group_id}/img_{image_id}" + path = check_tiff_or_npy(path) + image.save(path) + +# References + +def clean_reference_images(args,group_id): + if args.dev: + Path(f"references/dev").mkdir(parents=True, exist_ok=True) + path = f"references/dev" + else: + Path(f"references/group_{group_id}").mkdir(parents=True, exist_ok=True) + path = f"references/group_{group_id}" + + g = glob.glob(f"{str(path)}/*.tiff") + for f in g: + if args.d: + print(f"Remove {f}") + os.remove(f) + + g = glob.glob(f"{str(path)}/*.npy") + for f in g: + if args.d: + print(f"Remove {f}") + os.remove(f) + + +def record_reference_img(args,group_id,test_id,image_id,image): + if args.dev: + Path(f"references/dev").mkdir(parents=True, exist_ok=True) + path = f"references/dev/test_{test_id}_img_{image_id}" + else: + Path(f"references/group_{group_id}").mkdir(parents=True, exist_ok=True) + path = f"references/group_{group_id}/test_{test_id}_img_{image_id}" + + path = check_tiff_or_npy(path) + image.save(path) + +def get_reference_img(args,group_id,test_id,image_id): + if args.dev: + path = f"references/dev/test_{test_id}_img_{image_id}" + else: + path = f"references/group_{group_id}/test_{test_id}_img_{image_id}" + + path = check_tiff_or_npy(path) + return (AlgoImage.open(path)) + +# Results +# Should depend on compiler and test suite +def record_result_img(args,compiler,target,group_id,test_id,image_id,image): + if args.dev: + Path(f"results/img/{compiler}/{target}/dev").mkdir(parents=True, exist_ok=True) + path = Path(f"results/img/{compiler}/{target}/dev/test_{test_id}_img_{image_id}") + else: + Path(f"results/img/{compiler}/{target}/group_{group_id}").mkdir(parents=True, exist_ok=True) + path = Path(f"results/img/{compiler}/{target}/group_{group_id}/test_{test_id}_img_{image_id}") + path = check_tiff_or_npy(str(path)) + image.save(path) + + + + +def generate_reference_images(args,group_id,test): + for test_id,t in enumerate(test["tests"]): + images = [get_input_img(args,group_id,x) for x in t["useimg"]] + # generate references for this group, test + t["reference"](args,group_id,test_id,images) + +def get_reference_imgs(args,group_id,test_id,test,inputs): + nb = test["reference"].nb_references(inputs) + refs = [] + for i in range(nb): + refs.append(get_reference_img(args,group_id,test_id,i)) + return(refs) + + +def generate_input_images(args,group_id,test): + inputs = test["inputs"] + + image_id = 0 + for i in inputs: + new_imgs = i() + for im in new_imgs: + record_input_img(args,group_id,image_id,im) + image_id = image_id + 1 + + +def _mk_group_input(args,group_id,test): + inputs = test["inputs"] + nb_tests = len(test["tests"]) + if (args.group is None) or (args.test is None): + enabled = np.ones(nb_tests,dtype=np.uint32) + else: + enabled = np.zeros(nb_tests,dtype=np.uint32) + enabled[args.test] = 1 + imgs = [] + + funcid = [] + for t in test["tests"]: + funcid.append(t["funcid"]) + + # Add list of funcid to run for the tests + imgs.append(AlgoImage(np.array(funcid,dtype=np.uint32))) + + # Add list of test to run + imgs.append(AlgoImage(enabled)) + + image_id = 0 + for i in inputs: + for _ in range(i.nb_images): + im = get_input_img(args,group_id,image_id) + image_id = image_id + 1 + imgs.append(im) + + + return(imgs) + +def _validate_test(refs,results,test): + return test["check"](refs,results) + +def prepare_tests_group(args,group_id,test): + ginput = _mk_group_input(args,group_id,test) + with open("test_config.h","w") as f: + print(f"""#ifndef TEST_CONFIG_H +#define TEST_CONFIG_H + +#define {test["define"]} + +#endif +""",file=f) + + with open("test.dat","wb") as f: + serialize_tensors(f,ginput) + + convert("cinput","cinput","test.dat") + + return(ginput[TENSOR_START:]) + +def save_results(args,compiler,target,group_id,test_id,results): + for image_id,img in enumerate(results): + record_result_img(args,compiler,target,group_id,test_id,image_id,img) + + + +def validate_test_group(args,compiler,target,group_id,test,imgs,report_file): + had_error = False + print(f'

{test["name"]}

',file=report_file) + resultsSaved = False + results = None + for test_id,t in enumerate(test["tests"]): + result_path = f"results/output_{test_id}.dat" + try: + with open(result_path,"rb") as f: + results = read_tensors(f) + + if args.results: + save_results(args,compiler,target,group_id,test_id,results) + resultsSaved = True + + refs = get_reference_imgs(args,group_id,test_id,t,t["useimg"]) + if not _validate_test(refs,results,t): + print(f'''

Error running {t["desc"]}

+{t["check"].errors}
+                
+''',file=report_file) + had_error = True + except Exception as e: + print(f'''

Exception running {t["desc"]}

Exception raised

+{str(e)}
+
+''',file=report_file) + had_error = True + + if had_error and not resultsSaved: + if not (results is None): + save_results(args,compiler,target,group_id,test_id,results) + return had_error + +def mk_test_suite_from_dev(d): + t = { + "name" : "Development", + "define": "TESTDEV", + "inputs": [], + "tests":[ + {"desc":"Kernel being developped", + "funcid": 0, + "useimg": [0], + "reference": None, + "check" : None + } + ] + } + + t["inputs"] = d["inputs"] + nb = 0 + for i in t["inputs"]: + nb = nb + i.nb_images + + # All images are input of the dev kernels + t["tests"][0]["useimg"]=[x for x in range(nb)] + t["tests"][0]["reference"] = d["reference"] + t["tests"][0]["check"] = d["check"] + + return([t]) diff --git a/Testing/board/src/common.c b/Testing/board/src/common.c new file mode 100644 index 0000000..c3b3e80 --- /dev/null +++ b/Testing/board/src/common.c @@ -0,0 +1,111 @@ +#include "common.h" +#include + +#define NB_BUFFERS (buffers[0]) + +#define BUFFER_OFFSET_POS(ID) \ + (1 + 7*NB_BUFFERS + (ID)) + +#define BUFFER_LENGTH_POS(ID) \ + (1 + (ID)) + +#define BUFFER_DIM_POS(ID) \ + (1 + NB_BUFFERS + (5*ID)) + +/** + * @brief Gets the buffer length in bytes + * + * @param[in] test The test description + * @param[in] buffer_nb The buffer number + * + * @return The buffer length in bytes. + */ +byte_length_t get_buffer_length(const unsigned char *test, + const int buffer_nb) +{ + const uint32_t *buffers = (const uint32_t *)test; + return(buffers[BUFFER_LENGTH_POS(buffer_nb)]); +} + + +void get_img_dims(const unsigned char *test, + const int buffer_nb, + uint32_t *width, + uint32_t *height) +{ + const uint32_t *buffers = (const uint32_t *)test; + *width = buffers[BUFFER_DIM_POS(buffer_nb)+2]; + *height = buffers[BUFFER_DIM_POS(buffer_nb)+1]; + +} + +void get_buffer_shape(const unsigned char *test, + const int buffer_nb, + uint32_t *nb, + uint32_t *dim0, + uint32_t *dim1, + uint32_t *dim2, + uint32_t *dim3) +{ + const uint32_t *buffers = (const uint32_t *)test; + + *nb = buffers[BUFFER_DIM_POS(buffer_nb)]; + *dim0 = buffers[BUFFER_DIM_POS(buffer_nb+1)]; + *dim1 = buffers[BUFFER_DIM_POS(buffer_nb+2)]; + *dim2 = buffers[BUFFER_DIM_POS(buffer_nb+3)]; + *dim3 = buffers[BUFFER_DIM_POS(buffer_nb+4)]; +} + +const unsigned char* get_read_buffer(const unsigned char *test, + const int buffer_nb) +{ + const uint32_t *buffers = (const uint32_t *)test; + const uint32_t offset = buffers[BUFFER_OFFSET_POS(buffer_nb)]; + return(test+offset); +} + +unsigned char* get_write_buffer(unsigned char *test, + const int buffer_nb) +{ + const uint32_t *buffers = (const uint32_t *)test; + const uint32_t offset = buffers[BUFFER_OFFSET_POS(buffer_nb)]; + return(test+offset); +} +/** + * @brief Memory allocation with alignment + * + * @param[in] size The size in bytes + * @param[in] alignment The alignment in bytes + * + * @return Pointer to the allocated buffer + */ +void* aligned_malloc(size_t size, + size_t alignment) +{ + void *ptr=malloc(size+alignment+sizeof(void*)); + void *aligned = (char*)(((size_t)(ptr)+sizeof(void*)+alignment) & ~(alignment-1)); + + *((void**)(aligned) - 1) = ptr; + return(aligned); +} + +/** + * @brief Free a buffer allocated with the aligned malloc + * + * @param ptr The pointer + */ +void aligned_free(void* ptr) +{ + if (ptr) { + free(*((void**)(ptr) - 1)); + } +}; + + + +#define SAFE_FREE(x)\ + if ((x)) \ + { \ + free((x)); \ + } + diff --git a/Testing/board/src/common.h b/Testing/board/src/common.h new file mode 100644 index 0000000..4c0203d --- /dev/null +++ b/Testing/board/src/common.h @@ -0,0 +1,69 @@ +#ifndef ML_HELIUM_COMMON_H +#define ML_HELIUM_COMMON_H + +#include +#include + + +#include "arm_math_types.h" +#include "arm_math_types_f16.h" + + +typedef uint32_t byte_index_t; +typedef uint32_t byte_length_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Where input tensor buffers are starting in the buffer set +// Before input tensors there are tensors used to describe +// the test +#define TENSOR_START 2 + +#ifndef BUFFER_ALIGNMENT +#define BUFFER_ALIGNMENT 16 +#endif + +#ifndef INPUT_ADDR +#define INPUT_ADDR 0x70000000 +#endif + +#ifndef OUTPUT_ADDR +#define OUTPUT_ADDR 0x90000000 +#endif + +extern byte_length_t get_buffer_length(const unsigned char *, + const int buffer_nb); + + +extern void get_img_dims(const unsigned char *test, + const int buffer_nb, + uint32_t *width, + uint32_t *height); + +extern void get_buffer_shape(const unsigned char *test, + const int buffer_nb, + uint32_t *nb, + uint32_t *dim0, + uint32_t *dim1, + uint32_t *dim2, + uint32_t *dim3); + +extern const unsigned char* get_read_buffer(const unsigned char *test, + const int buffer_nb); + +extern unsigned char* get_write_buffer(unsigned char *test, + const int buffer_nb); + +extern void* aligned_malloc(size_t size, + size_t alignment); +extern void aligned_free(void* ptr); + + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Testing/board/src/load.cpp b/Testing/board/src/load.cpp new file mode 100644 index 0000000..6bb67fa --- /dev/null +++ b/Testing/board/src/load.cpp @@ -0,0 +1,162 @@ +#include "load.hpp" + +extern "C" { +#include "common.h" +#include "cinput.h" +} + +#include +#include +#include + + +const unsigned char* load_test_mem(const char* filepath) +{ + const unsigned char *buf; + +#if defined(CINPUT) + //buf = (const unsigned char*)INPUT_ADDR; + (void)filepath; + buf = (const unsigned char*)cinput; +#else + std::ifstream fin(filepath, std::ios::binary); + if (!fin) + { + return(nullptr); + } + + std::streampos begin,end; + begin = fin.tellg(); + fin.seekg (0, std::ios::end); + end = fin.tellg(); + fin.seekg (0, std::ios::beg); + + printf("%s : %lld bytes (%llX)\r\n",filepath,end-begin,end-begin); + + + buf = (const unsigned char*)aligned_malloc(end-begin,BUFFER_ALIGNMENT); + + if (buf == nullptr) + { + printf("Not enough memory\r\n"); + return(nullptr); + } + + fin.read(reinterpret_cast(const_cast(buf)), end-begin); + +#endif + + return(buf); +} + +void save_mem(const char* filepath,const unsigned char*buf,std::size_t size) +{ +#if !defined(NOOUTPUT) + std::ofstream outfile (filepath,std::ofstream::binary); + outfile.write (reinterpret_cast(buf),size); + outfile.close(); +#endif + //FILE *f; + //f=fopen(filepath,"wb"); + //fwrite(buf,size,1,f); + //fclose(f); +} + +static uint32_t align(uint32_t pos) +{ + uint32_t r = pos % BUFFER_ALIGNMENT; + if (r != 0) + { + r = BUFFER_ALIGNMENT - r; + pos += r; + } + + return(pos); + +} + +unsigned char* create_write_buffer(const std::vector &bufs, + uint32_t &total_bytes) +{ + total_bytes = 0; + for(auto b:bufs) + { + total_bytes += b.bytes() + BUFFER_ALIGNMENT; + } + if (total_bytes == BUFFER_ALIGNMENT) + { + return nullptr; + } + + total_bytes += sizeof(uint32_t); + // b bytes + // dims + // dt + // offsets + total_bytes += bufs.size() * (1+5+1+1)*sizeof(uint32_t); + + uint32_t* buf; +#if defined(MPS3) + buf = (uint32_t*)OUTPUT_ADDR; +#else + buf = (uint32_t*)aligned_malloc(total_bytes,BUFFER_ALIGNMENT); + + if (buf == nullptr) + { + printf("Not enough memory\r\n"); + return(nullptr); + } +#endif + uint32_t pos=0; + buf[0] = bufs.size(); + pos += sizeof(uint32_t); + + // Tensor sizes + for(auto b:bufs) + { + buf[pos>>2] = b.bytes(); + pos += sizeof(uint32_t); + } + + // Tensor dims + for(auto b:bufs) + { + buf[pos>>2] = b.shape().nb; + buf[(pos>>2) + 1] = b.shape().dims[0]; + buf[(pos>>2) + 2] = b.shape().dims[1]; + buf[(pos>>2) + 3] = b.shape().dims[2]; + buf[(pos>>2) + 4] = b.shape().dims[3]; + pos += 5*sizeof(uint32_t); + } + + // Datatypes + for(auto b:bufs) + { + buf[pos>>2] = b.dt(); + pos += sizeof(uint32_t); + } + + uint32_t offset_pos = pos; + pos += sizeof(uint32_t)*bufs.size(); + std::vector offset(bufs.size(),0); + + pos = align(pos); + int k=0; + for(auto b:bufs) + { + offset[k] = pos; + pos += b.bytes(); + pos = align(pos); + k++; + } + + for(unsigned int i=0;i < bufs.size();i++) + { + buf[(offset_pos>>2)+i] = offset[i]; + } + + + return((unsigned char*)buf); + + +} \ No newline at end of file diff --git a/Testing/board/src/load.hpp b/Testing/board/src/load.hpp new file mode 100644 index 0000000..90e6508 --- /dev/null +++ b/Testing/board/src/load.hpp @@ -0,0 +1,132 @@ +#pragma once + +#include "common.h" + + +#include + +template +struct Buffer{ + static const T* read(const unsigned char *test, + const int buffer_nb) + { + return(reinterpret_cast(get_read_buffer(test,buffer_nb))); + } + + static T* write(unsigned char *test, + const int buffer_nb) + { + return(reinterpret_cast(get_write_buffer(test,buffer_nb))); + } +}; + +extern const unsigned char* load_test_mem(const char* filepath); + +extern void save_mem(const char* filepath,const unsigned char*,std::size_t); + +enum buffer_type { + kIMG_RGB_TYPE = 0, + kIMG_GRAY8_TYPE = 1, + kIMG_NUMPY_TYPE_UINT8 = 2, + kIMG_NUMPY_TYPE_UINT16 = 3, + kIMG_NUMPY_TYPE_UINT32 = 4, + kIMG_NUMPY_TYPE_SINT8 = 5, + kIMG_NUMPY_TYPE_SINT16 = 6, + kIMG_NUMPY_TYPE_SINT32 = 7, + kIMG_NUMPY_TYPE_F16 = 8, + kIMG_NUMPY_TYPE_F32 = 9, + kIMG_NUMPY_TYPE_F64 = 10, + +}; + +struct Shape +{ + + + constexpr explicit Shape(uint32_t h,uint32_t w,uint32_t c,uint32_t d): + nb(4),dims{h,w,c,d}{}; + + constexpr explicit Shape(uint32_t h,uint32_t w,uint32_t c): + nb(3),dims{h,w,c,0}{}; + + constexpr explicit Shape(uint32_t h,uint32_t w): + nb(2),dims{h,w,0,0}{}; + + constexpr explicit Shape(uint32_t l): + nb(1),dims{l,0,0,0}{}; + + constexpr uint32_t nb_elems() const + { + uint32_t r = 1; + for(uint32_t i=0;i &buf,uint32_t &total_bytes); \ No newline at end of file diff --git a/Testing/board/test_config.h b/Testing/board/test_config.h new file mode 100644 index 0000000..411671b --- /dev/null +++ b/Testing/board/test_config.h @@ -0,0 +1,7 @@ +#ifndef TEST_CONFIG_H +#define TEST_CONFIG_H + +#define TESTGROUP2 + +#endif + diff --git a/Testing/board/test_desc.py b/Testing/board/test_desc.py new file mode 100644 index 0000000..22aaf19 --- /dev/null +++ b/Testing/board/test_desc.py @@ -0,0 +1,69 @@ +from scripts.test_utils import * +from scripts.test_details import * + +# Use image ID is counting from 1 + +allSuites = [ + { + "name" : "Linear Filters", + "define": "TESTGROUP1", + "inputs": [Image([(16,16) + ,(32,32)], + format=Format.GRAY8, + path="Patterns/Mandrill.tiff"), + Image([(16,16) + ,(32,32)], + format=Format.RGB, + path="Patterns/Mandrill.tiff")], + "tests":[ + {"desc":"Copy gray8 image 16x16", + "funcid": 1, + "useimg": [0], + "reference": CopyInput(), + "check" : IdenticalImage() + }, + {"desc":"Copy gray8 image 32x32", + "funcid": 1, + "useimg": [1], + "reference": CopyInput(), + "check" : IdenticalImage() + }, + {"desc":"Copy RGB image 16x16", + "funcid": 0, + "useimg": [2], + "reference": CopyInput(), + "check" : IdenticalImage() + }, + {"desc":"Copy RGB image 32x32", + "funcid": 0, + "useimg": [3], + "reference": CopyInput(), + "check" : IdenticalImage() + }, + ] + }, + { + "name" : "Tensor tests", + "define": "TESTGROUP2", + "inputs": [GenTensor(20,10,4,np.int16)], + "tests":[ + {"desc":"Test tensor", + "funcid": 0, + "useimg": [0], + "reference": CopyInput(), + "check" : IdenticalTensor() + }, + ] + } +] + +# Only one test used for developping and debugging a new kernel +# If more than one image is passed, they are assumed to be all input of the test +# But generally the test will use only one input image +devTest = { + "inputs": [Image([(64,64)], + format=Format.GRAY8, + path="Patterns/Mandrill.tiff")], + "reference": GaussianFilter(), + "check" : SimilarTensorFixp() +} \ No newline at end of file diff --git a/Testing/board/tests/test_dev.cpp b/Testing/board/tests/test_dev.cpp new file mode 100644 index 0000000..a01cb48 --- /dev/null +++ b/Testing/board/tests/test_dev.cpp @@ -0,0 +1,53 @@ +#include "common.h" +#include "load.hpp" +#include "test_config.h" +#include + +extern "C" { + #include "cv/linear_filters.h" +} + +#if defined(TESTDEV) + + +void test_dev(const unsigned char* inputs, + unsigned char* &outputs, + uint32_t &total_bytes) +{ + uint32_t width,height; + int bufid = TENSOR_START + 0; + + get_img_dims(inputs,bufid,&width,&height); + std::vector desc = {BufferDescription(Shape(height,width) + ,kIMG_NUMPY_TYPE_SINT16) + }; + + outputs = create_write_buffer(desc,total_bytes); + + const uint8_t *src = Buffer::read(inputs,bufid); + int16_t *dst = Buffer::write(outputs,0); + + const arm_cv_image_gray8_t input={(uint16_t)width,(uint16_t)height,(uint8_t*)src}; + + arm_cv_image_q15_t output; + output.width=width; + output.height=height; + output.pData=dst; + + arm_gaussian_filter_3x3_fixp(&input,&output); +} + +void run_test(const unsigned char* inputs, + const uint32_t testid, + const uint32_t funcid, + unsigned char* &wbuf, + uint32_t &total_bytes) +{ + + wbuf = nullptr; + (void)testid; + (void)funcid; + test_dev(inputs,wbuf,total_bytes); +} + +#endif \ No newline at end of file diff --git a/Testing/board/tests/test_group1.cpp b/Testing/board/tests/test_group1.cpp new file mode 100644 index 0000000..c0fa3d5 --- /dev/null +++ b/Testing/board/tests/test_group1.cpp @@ -0,0 +1,70 @@ +#include "common.h" +#include "load.hpp" +#include "test_config.h" +#include + +#if defined(TESTGROUP1) + +void test_rgb(const unsigned char* inputs, + unsigned char* &outputs, + uint32_t &total_bytes, + uint32_t testid) +{ + uint32_t width,height; + int bufid = TENSOR_START + 2; + if (testid == 3) + bufid = TENSOR_START + 3 ; + + get_img_dims(inputs,bufid,&width,&height); + std::vector desc = {BufferDescription(Shape(height,width))}; + + outputs = create_write_buffer(desc,total_bytes); + + const uint8_t *src = Buffer::read(inputs,bufid); + uint8_t *dst = Buffer::write(outputs,0); + memcpy(dst,src,get_buffer_length(inputs,bufid)); +} + +void test_gray8(const unsigned char* inputs, + unsigned char* &outputs, + uint32_t &total_bytes, + uint32_t testid) +{ + uint32_t nb_dims,dim0,dim1,dim2,dim3;; + int bufid = TENSOR_START + 0; + if (testid == 1) + bufid = TENSOR_START + 1 ; + + get_buffer_shape(inputs,bufid,&nb_dims,&dim0,&dim1,&dim2,&dim3); + std::vector desc = {BufferDescription(Shape(dim0,dim1) + ,kIMG_GRAY8_TYPE) + }; + + outputs = create_write_buffer(desc,total_bytes); + + const uint8_t *src = Buffer::read(inputs,bufid); + uint8_t *dst = Buffer::write(outputs,0); + memcpy(dst,src,get_buffer_length(inputs,bufid)); +} + +void run_test(const unsigned char* inputs, + const uint32_t testid, + const uint32_t funcid, + unsigned char* &wbuf, + uint32_t &total_bytes) +{ + + wbuf = nullptr; + switch(funcid) + { + case 0: + test_rgb(inputs,wbuf,total_bytes,testid); + break; + case 1: + test_gray8(inputs,wbuf,total_bytes,testid); + break; + } + +} + +#endif \ No newline at end of file diff --git a/Testing/board/tests/test_group2.cpp b/Testing/board/tests/test_group2.cpp new file mode 100644 index 0000000..c335400 --- /dev/null +++ b/Testing/board/tests/test_group2.cpp @@ -0,0 +1,39 @@ +#include "common.h" +#include "load.hpp" +#include "test_config.h" +#include + +#if defined(TESTGROUP2) + +void test1(const unsigned char* inputs, + unsigned char* &outputs, + uint32_t &total_bytes) +{ + std::vector desc = {BufferDescription(Shape(20,10,4) + ,kIMG_NUMPY_TYPE_SINT16) + }; + outputs = create_write_buffer(desc,total_bytes); + + const uint8_t *src = Buffer::read(inputs,TENSOR_START + 0); + uint8_t *dst = Buffer::write(outputs,0); + memcpy(dst,src,get_buffer_length(inputs,TENSOR_START + 0)); +} + + + +void run_test(const unsigned char* inputs, + const uint32_t testid, + const uint32_t funcid, + unsigned char* &wbuf, + uint32_t &total_bytes) +{ + (void)testid; + switch(funcid) + { + case 0: + test1(inputs,wbuf,total_bytes); + } + +} + +#endif \ No newline at end of file