BeagleBoard/GSoC/2021 Proposal/simpPRU Improvements

=Proposal for Improvements to simpPRU =

About
Student: Archisman Dey Mentors: Abhishek, Pratim Ugale, Andrew Henderson Code: https://github.com/VedantParanjape/simpPRU Wiki: https://elinux.org/index.php?title=BeagleBoard/GSoC/2021_Proposal/simpPRU_Improvements GSoC: https://summerofcode.withgoogle.com/projects/#4991291718369280

=Status= This project has been selected for GSoC 2021.

=Proposal= I have completed all the requirements listed on the ideas page. The code for the cross-compilation task can be found here, submitted through the pull request #146

About you
IRC: archismandey (@archismandey:matrix.org) GitHub: GitHub Account School: Indian Institute of Technology Guwahati Country: India Primary language: English, Bengali, Hindi Typical work hours: 10:30 AM - 8:30 PM Indian Standard Time Previous GSoC participation: This is the first time I am participating in GSoC.

About your project
Project name: Improvements to simpPRU Deliverables: Code, including tests, documentation and examples pushed to the repository for simpPRU.

Description
This project aims to add tests, features, and more compatibility for simpPRU, the simple python-like language developed during GSoC 2020 to make programming the PRU easier. The following things are to be done:

Add suport for BeagleBone Blue Currently, simpPRU supports the following boards: PocketBeagle, BeagleBone Black, BeagleBone Black Wireless and BeagleBone AI. This project will add support for the BeagleBone Blue (solving issue#4) by adding the pin mappings for the Blue. Adding support for other boards in the BeagleBone family like the SeedStudio boards can also be done depending upon availability.

Add unit tests Currently, simpPRU lacks any testing apart from making sure the examples work. This project will add unit tests for every feature present in simpPRU. This will help in making sure there are no regressions while adding new features to simpPRU. There are two possible ways of adding unit tests: End-to-end unit testing: For example, a test case for digital read, digital write, and if statement would look like: int ERROR := 1; init_message_channel; digital_write(P1_29, true); /*Pin numbers can be changed depending on which board tests are running*/ if : not digital_read(P1_29) { send_message(ERROR); } We would build and run this on the PRU and check that 1 (ERROR) never gets sent to the host.

Unit testing with stubs and mocks: For example, a test case for variable assignment, equality checking, and if statement would look like: int a := 5; if : a != 5 { error; } return 0; Then we would build and run using the host C compiler and make sure that error never gets called.

For the PRU specific functions, a stub function will have to be provided to satisfy the linker, for example: void digital_write(pin_number, value) { printf("Digital Write called"); }

For both kinds of tests, running the unit tests would be automated into the CI pipeline.

Add the ability to use hexadecimal numbers to initialize ints Currently, only decimal numbers are supported. This will be helpful for writing drivers for I2C devices, for example. Syntax: int a := 0xF; /* 15 */

Add support for the modulo operator and the bitshift operators Currently, four arithmetic operators are supported: +, -, *, /. This project will add support for the modulo (%) operator. int a := 17 % 4; /* 1 */ Also, three bitwise operators are supported right now: ~, &, and |. This project will add support for two more: left shift (<<) and right shift (>>). int a := 128; int b := a << 1; /* 256 */ int c := a >> 1; /* 64 */

Update the grammar so that control statements (break/continue) can only be called inside loops Currently, break and continue can be called inside any compound statement such as conditionals, which will throw an error while compiling the generated C code. After this project, they can be called inside loops only: loop_for | loop_while { statement_list; conditional_statement {   /* if / elif / else */ statement_list; break | continue; }    statement_list; } For example, after updating the grammar: /* this code will work */ int a := 10; while: true { if: a < 0 { break; }    a := a - 1; } /* and this would give an error in the bison parser itself */ int a := 10; if: a <= 10 { break; }

Update the grammar so that return statements can be called anywhere in the function Currently they can be called only at the end of a function, which is less flexible. For example, a function like this will now work: def func: int: int a { if: a < 22 { return 1; } else { return 0; } } Earlier, this had to be written as: def func: int: int a { int b;    if: a < 22 { b := 1; } else { b := 0; return b; }

Add support for char/uint8 data type Currently, simpPRU has support for two data types - int (32 bit) and bool. This project would add a char data type, which can also be used as an unsigned 8-bit integer. This would be helpful in two ways:
 * Having a 8-bit unsigned integer data type would reduce memory usage, which is helpful since PRU has limited memory.
 * char can be used in arrays to implement strings.

Declaration and Assignment: char c; /* declaration without assignment */ c := 'A'; /* assignment from single quoted character */ c := 65; /* assignment from numeric */ int a := 65; c := a; /* 0 <= 65 <= 255, so works correctly */ int a := 282982; c := a; /* 282982 > 255, so does not work correctly */ Arithmetic and Comparison operators: char i := 65; int j := 65; if: i == j { ... } /* true */ char c1 := 45; int c2 := 62; char c3 := c1 + c2; /* 107 */ char c3 := c1 * c2; /* value will get altered */
 * char can be assigned from either a numeric or a single quoted character.
 * char can also be initialised from other chars and ints but it's value might get altered when assigning from int.
 * All comparison operators (>, <, ==, !=, >=, <=) will work correctly between char/char, char/int and int/char.
 * Arithmetic operators (+, -, *, /, %) will work with chars and ints, but the char will get automatically converted to an int. If the result is assigned to a char, rules for assigning to char from int applies.
 * Bitwise operators (~, &, |, <<. >>) will also work on chars.

Add support for C style static arrays Right now, simpPRU does not have any support for arrays. This project will add support for C-style arrays:
 * Arrays are static - their size has to be known at compile time and this size cannot be changed later.
 * Arrays can be used with bool, int and char.
 * Arrays do not support any arithmetic / logical / comparison / bitwise operators.

Declaration and Assignment: int[16] a; /* array of 16 integers */ char[20] string1 := "I love BeagleBoards"; Indexing: int a := arr[4]; /* Copy the 5th element of arr to a */ arr[4] := 5; /* The 5th element of arr is now 5 */ int i := 4; arr[i] := 6; /* The 5th element of arr is now 6 */ char j := 4; arr[j] := 7; /* The 5th element of arr is now 7 */ arr[i+j] := 1; /* The 9th element of arr is now 1 */ /* Declaring and initializing an array with all zeros */ int[16] arr; for: i in 0:16 { arr[i] := 0; }
 * The data type has to be specified as data_type[size].
 * Array of char can be initialized from a double quoted string, where the length of the array would be at least the length of the string plus 1.
 * Arrays are zero-indexed.
 * The index can be either a char or an int or an expression involving chars and ints.
 * Accessing elements of an array:
 * Changing elements of an array:

Add ability to send more complex data through rpmsg Currently, simpPRU only has the ability to send integers through rpmsg using send_message. This project will add the ability to send other data types through rpmsg, including adding support for sending arrays. This will be done by implementing six functions: All these functions will convert the data into a string representation (for example, an int array to "2 4 5 2 1 98") and send it via rpmsg. This project will also add support for receiving strings in simppru-console, which can currently receive only ints.
 * send_int (same as send_message now)
 * send_ints (for int arrays)
 * send_bool
 * send_bools (for bool arrays)
 * send_char
 * send_string (for strings aka char arrays).

Add a more flexible for loop Currently the for loop in simpPRU can only handle loops of the form for : var in range_1:range_2 {...} /* range_2 > range_1 */

This project will add support for more flexible for loops of the form for : var in range_1:range_2:increment {...} /* range_1, range_2, and increment can be any integers */

Better error handling in the parser simpPRU has some error handling in the bison parser, but it is not comprehensive. This project will add more comprehensive error handling.

Experience and approach
I have some experience with building stuff using arduinos and other controllers before (github) and have programming experience with C, C++, and Python. I got interested in how parsers and compilers work while trying to build a symbolic differentiator (github) as a personal project. I am doing a minor in Computer Science, and had a course where I learned about context free grammars, turing machines, etc. I have learned the basics of how flex and bison work and looked at the repository for simpPRU and I understand how it works. I also fixed an issue in simpPRU with the documentation generator: #5. So I think I am qualified to work on this project.

Contingency
BeagleBoard is a very active community and it is unlikely that none of the mentors would be willing to help. That said, everything I am going to be working on is an open source project with good documentation, so I will use all the resources available to help myself.

Benefit
This project will make simpPRU more complete and robust, which will help with beginners learning to use the PRU or experienced users prototyping something on the PRU. Quotes: "simpPRU will simplify programming the PRU, and probably make it easy even for a kid to program the PRU, which is a big plus point of this project." - Vedant Paranjape (@vedant16)

Misc
Link to pull request: #146