From 82609517f51d9b5b044975ade30e683a7202fe15 Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 10 Jul 2023 00:54:26 -0300 Subject: [PATCH 001/117] refactor(Documentation): Moved LICENSE to root, and moved function infos to Wiki --- Documentation/info | 123 ------------------------------- Documentation/LICENSE => LICENSE | 0 2 files changed, 123 deletions(-) delete mode 100644 Documentation/info rename Documentation/LICENSE => LICENSE (100%) diff --git a/Documentation/info b/Documentation/info deleted file mode 100644 index 393d4da..0000000 --- a/Documentation/info +++ /dev/null @@ -1,123 +0,0 @@ -ArrayElements - ArrayElements(); - vector elements - append (ArrayElement& e) - - getArraySize () - getStructSize () - getElementCount (int position) - getStructElement (int position) - getArrayType() - -AttachInterrupt - AttachInterrupt(int port, string name, int event) - -BinaryOp - BinaryOp (Node *l, int op, Node *r) - accept (Visitor &v) - getOperator () - -Capsule - Capsule (Node *n) - -CmpOp - CmpOp (Node *l, int op, Node *r) - accept (Visitor &v) - getOperator () - -Coercion - Convert (Value *v, Type *destty, BasicBlock *block, bool unsig = false) - -Delay - Delay (Node *mseg) - accept (Visitor &v) - -Float - Float (float n) - -FunctionCall - FunctionCall (string name) - -FunctionDecl - FunctionDecl (string name, Node *stmts) - - bool isFunctionDecl() - -If - If (Node *e, Node *tst, Node *est) - accept (Visitor& v) - -InPort - InPort (const char *p) - -Int8 - Int8 (char n) - getNumber () - accept (Visitor &v) - -Int16 - Int16 (short n) - getNumber () - accept (Visitor &v) - -Int32 - Int32 (int n) - getNumber ( ) - accept (Visitor &v); - -Load - Load (const char *i) - getIdent () - accept (Visitor& v) - -LoadMatrix - LoadMatrix (const char *i, int pos_1, int pos_2) - -LoadVector - LoadVector (const char *i, int pos) - -Matrix - Matrix (const char *n, MatrixElements *me) - -Node - isFunctionDecl() - Node () - vector const& children() - acceot (visitor &) - -OutPort - OutPort (const char *p, Node *e) - -Print - Print (Node *e) - -Program - Program (Stmts *stmts) - declara_auxiliary_c_funcs () - -Return - Return (Node *n) - -Scalar - Scalar (const char *n, Node *e) - getIdent () - accept (Visitor& v) - -Semantic - Verification () - -Stmts - Stmts (Node *s) - vector const& children() - append (Node *s) - prepend (Node *s) - -String - String (const char *s) - -Vector - Vector (const char *n, ArrayElements *aes) - -While - While (Node *e, Node *stms) - accept (Visitor& v) diff --git a/Documentation/LICENSE b/LICENSE similarity index 100% rename from Documentation/LICENSE rename to LICENSE From fba2900fbc57124d54cf8378372f9d14648c8cfd Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 10 Jul 2023 01:01:08 -0300 Subject: [PATCH 002/117] delete(Unecessary): Removed unnecessary test files from root directory --- Ex1.txt | 18 ------ Teste_Matrix.txt | 10 ---- new_rob.txt | 86 --------------------------- recursive.txt | 12 ---- rob.txt | 152 ----------------------------------------------- 5 files changed, 278 deletions(-) delete mode 100644 Ex1.txt delete mode 100644 Teste_Matrix.txt delete mode 100644 new_rob.txt delete mode 100644 recursive.txt delete mode 100644 rob.txt diff --git a/Ex1.txt b/Ex1.txt deleted file mode 100644 index dab5a70..0000000 --- a/Ex1.txt +++ /dev/null @@ -1,18 +0,0 @@ - -c1 = 1; -c2 = 0; -z = c1 + c2; - -print z; - -i = 1; -while (i <= c1){ - x = c1 + i; - i++; -} -b = func_name(2, 2, 2); -print b; - -int func_name(int a, int b, int c){ - return (a*b)+c; -} diff --git a/Teste_Matrix.txt b/Teste_Matrix.txt deleted file mode 100644 index c4f36a5..0000000 --- a/Teste_Matrix.txt +++ /dev/null @@ -1,10 +0,0 @@ -vector_name = {{0:3, 2:3, 1}:2}; - -i = 0; -j = 0; - -while (i < 7){ - b = vector_name[i][j]; - print b; - i = i+1; -} diff --git a/new_rob.txt b/new_rob.txt deleted file mode 100644 index 52b4ccd..0000000 --- a/new_rob.txt +++ /dev/null @@ -1,86 +0,0 @@ -/*void motor_shutdown() { - out PIN1 = 0.0; - out PIN2 = 0.0; - out PIN3 = 0.0; - out PIN4 = 0.0; -}*/ - -int read_ir(){ - return 1; -} - -void step_up_down(){ - print "oi"; -} - -void step_right_left(){ - print "oi"; -} - -void step_front_back(){ - print "oi"; -} - -void blink(float time) { - out13 = 255.0; - delay time; - out13 = 0.0; - delay time; -} - -curr_dir = 1.0; -blink(500.0); -blink(500.0); -PARA_FRENTE = 1.0; -PARA_TRAS = 1.0; - -void SERVO_POS_INC(){ - print "Abre"; -} - -void SERVO_POS_DEC(){ - print "Fecha"; -} - -void open_grip (bool open){ - if (open == true){ - SERVO_POS_INC(); - } - else{ - SERVO_POS_DEC(); - } -} - -while (true == true) { - F = read_ir(); - if (F == 3041526525.0) { // UP - SENTIDO = 1.0; - step_up_down(); - } - else if (F == 3041559165.0) { // DOWN - SENTIDO = -1.0; - step_up_down(); - } - else if (F == 3041542845.0) { // LEFT - SENTIDO = 1.0; - step_right_left(); - } - else if (F == 3041575485.0) { // RIGHT - SENTIDO = -1.0; - step_right_left(); - } - else if (F == 4111076595.0) { // AUDIO - SENTIDO = 1.0; - step_front_back(); - } - else if (F == 3041570895.0) { // RIGHT - SENTIDO = -1.0; - step_front_back(); - } - else if (F == 3041546415.0) { // OPEN GRIP - open_grip(true); - } - else if (F == 3041579055.0) { // CLOSE GRIP - open_grip(false); - } -} diff --git a/recursive.txt b/recursive.txt deleted file mode 100644 index 06c24f5..0000000 --- a/recursive.txt +++ /dev/null @@ -1,12 +0,0 @@ -int fibonacci (int a){ - if (a == 1){ - return 1; - } - else{ - a = a - 1; - c = fibonacci(a); - return c; - } -} - -b = fibonacci(9); diff --git a/rob.txt b/rob.txt deleted file mode 100644 index 809a8e6..0000000 --- a/rob.txt +++ /dev/null @@ -1,152 +0,0 @@ -PARA_FRENTE = 1.0; -PARA_TRAS = -1.0; -STEPS_PER_CLICK = 50; - -PIN1 = 0.0; -PIN2 = 0.0; -PIN3 = 0.0; -PIN4 = 0.0; -curr_step = 0.0; -CURR_DIR = PARA_FRENTE; - -void step_motor(float curr_step) { - if (curr_step == 0.0) { - OUTPIN1 = 255.0; - OUTPIN2 = 0.0; - OUTPIN3 = 255.0; - OUTPIN4 = 0.0; - } - else if (curr_step == 1.0) { - OUTPIN1 = 0.0; - OUTPIN2 = 255.0; - OUTPIN3 = 255.0; - OUTPIN4 = 0.0; - } - else if (curr_step == 2.0) { - OUTPIN1 = 0.0; - OUTPIN2 = 255.0; - OUTPIN3 = 0.0; - OUTPIN4 = 255.0; - } - else if (curr_step == 3.0) { - OUTPIN1 = 255.0; - OUTPIN2 = 0.0; - OUTPIN3 = 0.0; - OUTPIN4 = 255.0; - } - - RPM = (60.0 * 1000.0) / 4096.0 / 4.0; - DELAY RPM; - - curr_step = curr_step + curr_dir; - if (curr_step == 4.0) { - curr_step = 0.0; - } - else if (curr_step == -1.0) { - curr_step = 3.0; - } -} - -void MOTOR_SHUTDOWN() { - OUTPIN1 = 0.0; - OUTPIN2 = 0.0; - OUTPIN3 = 0.0; - OUTPIN4 = 0.0; -} - -void LOOP_STEPS() { - I = 0.0; - WHILE (I < STEPS_PER_CLICK) { - step_motor(curr_step); - I = I + 1.0; - } - MOTOR_SHUTDOWN(); -} - -STEP_DE = 0.0; -void STEP_RIGHT_LEFT() { - - CURR_STEP = STEP_DE; - PIN1 = 14.0; // A0 - PIN2 = 4.0; - PIN3 = 3.0; - PIN4 = 5.0; - - LOOP_STEPS(); - STEP_DE = CURR_STEP; -} - -STEP_UD = 0.0; -void STEP_UP_DOWN() { - - CURR_STEP = STEP_UD; - PIN1 = 10.0; - PIN2 = 12.0; - PIN3 = 11.0; - PIN4 = 13.0; - - LOOP_STEPS(); - STEP_UD = CURR_STEP; -} - -STEP_FB = 0.0; -void STEP_FRONT_BACK(float direcao) { - - direcao = STEP_FB; - PIN1 = 6.0; - PIN2 = 8.0; - PIN3 = 7.0; - PIN4 = 9.0; - - LOOP_STEPS(); - STEP_FB = direcao; -} - -void OPEN_GRIP() { - Z = SERVO_POS_INC(); -} - -void CLOSE_GRIP() { - Y = SERVO_POS_DEC(); -} - -void blink(float time){ - out 13 = 255.0; - delay time; - out 13 = 0.0; - delay time; -} - -// BLINK_FAST = blink(100.0); -// MAIN LOOP -blink(500.0); -blink(500.0); -var = 1.0; - -while (var >= 1.0) { - F = READ_IR(); - IF (F == 3041526525.0) { // UP - STEP_UP_DOWN(PARA_FRENTE); - } - ELSE IF (F == 3041559165.0) { // DOWN - STEP_UP_DOWN(PARA_TRAS); - } - ELSE IF (F == 3041542845.0) { // LEFT - STEP_RIGHT_LEFT(PARA_FRENTE); - } - ELSE IF (F == 3041575485.0) { // RIGHT - STEP_RIGHT_LEFT(PARA_TRAS); - } - ELSE IF (F == 4111076595.0) { // AUDIO - STEP_FRONT_BACK(PARA_FRENTE); - } - ELSE IF (F == 3041570895.0) { // RIGHT - STEP_FRONT_BACK(PARA_TRAS); - } - ELSE IF (F == 3041546415.0) { // OPEN GRIP - OPEN_GRIP(); - } - ELSE IF (F == 3041579055.0) { // CLOSE GRIP - CLOSE_GRIP(); - } -} From 50c62c9f2f8961cc5e8791e18e9a733ac629d7fc Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 10 Jul 2023 01:02:02 -0300 Subject: [PATCH 003/117] delete(Unecessary): Removed unnecessary test files from gcc_llvm folder --- gcc_llvm/function_parameters.c | 8 -------- gcc_llvm/matrix.c | 9 --------- 2 files changed, 17 deletions(-) delete mode 100644 gcc_llvm/function_parameters.c delete mode 100644 gcc_llvm/matrix.c diff --git a/gcc_llvm/function_parameters.c b/gcc_llvm/function_parameters.c deleted file mode 100644 index 338579f..0000000 --- a/gcc_llvm/function_parameters.c +++ /dev/null @@ -1,8 +0,0 @@ -int func(int var){ - return var; -} - -int main(){ - int var = 2; - func(var); -} diff --git a/gcc_llvm/matrix.c b/gcc_llvm/matrix.c deleted file mode 100644 index 0391857..0000000 --- a/gcc_llvm/matrix.c +++ /dev/null @@ -1,9 +0,0 @@ - -int main () -{ - int a[3][2]; - - a[2][1] = 2; - -} - From aaef1f3370a6bb110091d00a525b0493885aa17e Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 10 Jul 2023 01:04:35 -0300 Subject: [PATCH 004/117] feat(gitkeep): Added .gitkeep file to keep test/out directory empty --- test/out/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/out/.gitkeep diff --git a/test/out/.gitkeep b/test/out/.gitkeep new file mode 100644 index 0000000..e69de29 From cc034ab3295ce3383c5b384de97783ddc50a5757 Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 10 Jul 2023 01:07:43 -0300 Subject: [PATCH 005/117] delete(Unecessary): Removed unnecessary test files from compare directory --- compare/Ex1.c | 16 ----- compare/Ex1.txt | 18 ----- compare/Ex2.c | 19 ----- compare/Makefile | 27 ------- compare/Remember | 1 - compare/debug.c | 179 ----------------------------------------------- 6 files changed, 260 deletions(-) delete mode 100644 compare/Ex1.c delete mode 100644 compare/Ex1.txt delete mode 100644 compare/Ex2.c delete mode 100644 compare/Makefile delete mode 100644 compare/Remember delete mode 100644 compare/debug.c diff --git a/compare/Ex1.c b/compare/Ex1.c deleted file mode 100644 index 581f8d1..0000000 --- a/compare/Ex1.c +++ /dev/null @@ -1,16 +0,0 @@ -#include - -int func_name (int a, int b, int c){ - return (a * b) + c; -} - -void main (){ - int c1 = 1, c2 = 0, int x; - int z = c1 + c2; - - printf ("%d", z); - - for (i = 1; i <= c1; i++){ - x = c1 + i; - } -} diff --git a/compare/Ex1.txt b/compare/Ex1.txt deleted file mode 100644 index 2f144e5..0000000 --- a/compare/Ex1.txt +++ /dev/null @@ -1,18 +0,0 @@ -int func_name(int a, int b, int c){ - return (a * b) + c; -} - -c1 = 1; -c2 = 0; -z = c1 + c2; - -print z; - -i = 1; -while (i <= c1){ - x = c1 + i; - i++; -} -b = func_name(2, 2, 2); -print b; - diff --git a/compare/Ex2.c b/compare/Ex2.c deleted file mode 100644 index 16d223a..0000000 --- a/compare/Ex2.c +++ /dev/null @@ -1,19 +0,0 @@ -#include - -void funct(int a){ - printf ("%d", a); -} - -void main(){ - int x = 5; - printf ("%d\n", x); - funct(x); - - printf ("%d\n", x); - int y; - funct(y); - - - -} - diff --git a/compare/Makefile b/compare/Makefile deleted file mode 100644 index cd37668..0000000 --- a/compare/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -ALL_LL=$(patsubst %.txt,out/%.ll,$(wildcard *.txt)) -ALLOBJS=$(patsubst %.ll,%.o,${ALL_LL}) -ALLASM=$(patsubst %.ll,%.s,${ALL_LL}) -ALLBIN=$(patsubst %.ll,%,${ALL_LL}) - -COMPILER_NAME=../robcmp - -all: ${ALL_LL} ${ALLASM} ${ALLOBJS} ${ALLBIN} - -clean: - rm -f ${ALLBIN} ${ALLASM} ${ALLOBJS} ${ALL_LL} - -out/%.ll : %.txt ${COMPILER_NAME} - ${COMPILER_NAME} $< > $@ - -%.o : %.ll - llc-9 $< -o $@ -filetype=obj - -%.s : %.ll - llc-9 $< -o $@ -filetype=asm - -core.o : debug.c - gcc debug.c -o core.o -c - -% : %.s core.o - gcc core.o $< -o $@ -lncurses - diff --git a/compare/Remember b/compare/Remember deleted file mode 100644 index c66600a..0000000 --- a/compare/Remember +++ /dev/null @@ -1 +0,0 @@ -gcc -O2 debug.o nome.c -o exec -lncurses diff --git a/compare/debug.c b/compare/debug.c deleted file mode 100644 index de38122..0000000 --- a/compare/debug.c +++ /dev/null @@ -1,179 +0,0 @@ - -#include -#include -#include -#include - -void onexit(void) __attribute__ ((destructor)); - -#define ARDUINO_PORTS 14 -int arduino_out_ports[ARDUINO_PORTS]; -int steppers_pos[3] = {0}; - -#define LCD_ROWS 6 -#define LCD_COLS 14 -#define LCD_CHARS (LCD_ROWS*LCD_COLS) -char display[LCD_CHARS]; -int display_pos = 0; -char last_msg[1000]; - -char *port_names[ARDUINO_PORTS] = { - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "14", -}; - -void refresh_screen() { - - mvprintw(1, 1, "Simulador de E/S para Robcmp"); - mvprintw(2, 1, "----------------------------"); - - mvprintw(6, 1, "Ultima msg: "); - attron(COLOR_PAIR(3)); - mvprintw(6, 14, "%s ", last_msg); - attroff(COLOR_PAIR(3)); - - int currow = 10; - mvprintw(currow++, 1, "[ Mensagens print ]"); - mvprintw(currow++, 1, "---------------"); - attron(COLOR_PAIR(2)); - for(int r=0; r ARDUINO_PORTS) { - attron(COLOR_PAIR(3)); - sprintf(last_msg, "Erro: porta %d nao existe.", - port); - attroff(COLOR_PAIR(3)); - } else { - arduino_out_ports[port] = value; - } - - refresh_screen(); -} - -void delay(int milis) { - attron(COLOR_PAIR(3)); - sprintf(last_msg, "Delay %d milis", milis); - attroff(COLOR_PAIR(3)); - refresh_screen(); - - usleep(milis*1000); -} - -void stepper_goto(int stepper, int pos) { - attron(COLOR_PAIR(3)); - sprintf(last_msg, "Motor %d move para posicao %d.", stepper, pos); - attroff(COLOR_PAIR(3)); - refresh_screen(); - usleep(1e6); -} - -void servo_goto(int pos) { - attron(COLOR_PAIR(3)); - if (pos >= 0 && pos <= 30) { - sprintf(last_msg, "Servo move para posicao %d.", pos); - } else { - sprintf(last_msg, "Servo nao pode se mover para posicao %d (0-30).", pos); - } - attroff(COLOR_PAIR(3)); - refresh_screen(); - usleep(1e6); -} - -void onexit(void) { - getchar(); - curs_set(1); - clear(); - endwin(); -} - -/*int main() { - - int r = 10; - float d = 100.903; - - print(1, &d); - print(0, &r); -} -*/ From 116c4fa910b3f037315745053e810305f62e5676 Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 10 Jul 2023 01:37:42 -0300 Subject: [PATCH 006/117] feat(Malloc): Initial commit of dynamic allocation --- src/Header.h | 1 + src/Malloc.cpp | 13 +++++++++++++ src/Malloc.h | 14 ++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 src/Malloc.cpp create mode 100644 src/Malloc.h diff --git a/src/Header.h b/src/Header.h index d68056d..7f926e2 100644 --- a/src/Header.h +++ b/src/Header.h @@ -178,6 +178,7 @@ static RobSymbol *search_symbol(const string& ident, BasicBlock *firstb = NULL, #include "Load.h" #include "LoadArray.h" #include "LoadMatrix.h" +#include "Malloc.h" #include "Matrix.h" #include "MatrixElements.h" #include "OutPort.h" diff --git a/src/Malloc.cpp b/src/Malloc.cpp new file mode 100644 index 0000000..f979b5d --- /dev/null +++ b/src/Malloc.cpp @@ -0,0 +1,13 @@ + +#include "Header.h" + +Malloc::Malloc(Node *e) : expr(e) { + node_children.reserve(1); + node_children.push_back(e); +} + Value *Malloc::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + Value *exprv = expr->generate(func, block, allocblock); + Type *leftvty = exprv->getType(); + Value *m_size = ConstantInt::get(Type::getInt8Ty(global_context), 0); + return CallInst::CreateMalloc(block, Type::getInt32Ty(global_context), leftvty, m_size, m_size, func, ""); + } diff --git a/src/Malloc.h b/src/Malloc.h new file mode 100644 index 0000000..481c7df --- /dev/null +++ b/src/Malloc.h @@ -0,0 +1,14 @@ +#ifndef __MALLOC_H__ +#define __MALLOC_H__ +#include "Node.h" + +class Malloc: public Node { +private: + Node *expr; +public: + Malloc(Node *e); + virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); +}; + +#endif + From 5f9f38eba04ca6a332da5172b99865b522a0443e Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 10 Jul 2023 11:11:16 -0300 Subject: [PATCH 007/117] feat(Tests): Updated tests to reach main adjustments --- test/Fibonacci.rob | 20 +++++++++++++ test/Fibonacci.txt | 18 ------------ test/Float_Vector.txt | 7 ----- test/Float_Vector_R.txt | 7 ----- test/Funcionando.txt | 7 ----- test/Function_Call.rob | 10 +++++++ test/Function_Sort.rob | 22 +++++++++++++++ test/Function_w_Conditional.rob | 15 ++++++++++ ...{Falhando.txt => Function_w_Params_00.rob} | 7 +++-- test/Function_w_Params_01.rob | 7 +++++ test/Int_Function.txt | 5 ---- test/Int_Vector.txt | 7 ----- test/Int_Vector_R.txt | 7 ----- test/{Falhando2.txt => Main_w_Condition.rob} | 4 +-- test/NewNew.txt | 2 -- test/NewSort.txt | 20 ------------- test/New_Teste.txt | 18 ++++++------ test/Print.rob | 4 +++ test/Sort.txt | 28 ++++++++++--------- test/Vector_Float.rob | 9 ++++++ test/Vector_Float_R.rob | 9 ++++++ test/Vector_Int.rob | 9 ++++++ test/Vector_Int_R.rob | 9 ++++++ test/abc.txt | 7 ----- 24 files changed, 145 insertions(+), 113 deletions(-) create mode 100644 test/Fibonacci.rob delete mode 100644 test/Fibonacci.txt delete mode 100644 test/Float_Vector.txt delete mode 100644 test/Float_Vector_R.txt delete mode 100644 test/Funcionando.txt create mode 100644 test/Function_Call.rob create mode 100644 test/Function_Sort.rob create mode 100644 test/Function_w_Conditional.rob rename test/{Falhando.txt => Function_w_Params_00.rob} (50%) create mode 100644 test/Function_w_Params_01.rob delete mode 100644 test/Int_Function.txt delete mode 100644 test/Int_Vector.txt delete mode 100644 test/Int_Vector_R.txt rename test/{Falhando2.txt => Main_w_Condition.rob} (74%) delete mode 100644 test/NewNew.txt delete mode 100644 test/NewSort.txt create mode 100644 test/Print.rob create mode 100644 test/Vector_Float.rob create mode 100644 test/Vector_Float_R.rob create mode 100644 test/Vector_Int.rob create mode 100644 test/Vector_Int_R.rob delete mode 100644 test/abc.txt diff --git a/test/Fibonacci.rob b/test/Fibonacci.rob new file mode 100644 index 0000000..a0fd391 --- /dev/null +++ b/test/Fibonacci.rob @@ -0,0 +1,20 @@ +int16 fibonacci (int16 n){ + if (n == 1) + return 1; + else + if (n == 2) + return 1; + else + { + return fibonacci(n - 1) + fibonacci(n - 2); + } + return 1; +} + +int16 main(){ + print fibonacci(1); + print fibonacci(2); + print fibonacci(3); + print fibonacci(4); + print fibonacci(5); +} diff --git a/test/Fibonacci.txt b/test/Fibonacci.txt deleted file mode 100644 index c6c4cc5..0000000 --- a/test/Fibonacci.txt +++ /dev/null @@ -1,18 +0,0 @@ -int fibonacci (int n){ - if (n == 1) - return 1; - else - if (n == 2) - return 1; - else - { - return fibonacci(n - 1) + fibonacci(n - 2); - } - return 1; -} - -print (fibonacci(1)); -print (fibonacci(2)); -print (fibonacci(3)); -print (fibonacci(4)); -print (fibonacci(5)); diff --git a/test/Float_Vector.txt b/test/Float_Vector.txt deleted file mode 100644 index 2ab385d..0000000 --- a/test/Float_Vector.txt +++ /dev/null @@ -1,7 +0,0 @@ -vector = {3, 2, 5, 2, 1, 4.2, 5, 6, 8, 2, 1}; - -i = 0; -while (i < 10){ - print vector[i]; - i = i + 1; -} diff --git a/test/Float_Vector_R.txt b/test/Float_Vector_R.txt deleted file mode 100644 index 2634682..0000000 --- a/test/Float_Vector_R.txt +++ /dev/null @@ -1,7 +0,0 @@ -vector = {3:3, 4.2}; - -i = 0; -while (i < 4){ - print vector[i]; - i = i + 1; -} diff --git a/test/Funcionando.txt b/test/Funcionando.txt deleted file mode 100644 index 579dd8e..0000000 --- a/test/Funcionando.txt +++ /dev/null @@ -1,7 +0,0 @@ -a = true; - if (a == true){ - print 1; - } - else { - print 2; - } diff --git a/test/Function_Call.rob b/test/Function_Call.rob new file mode 100644 index 0000000..cc99c70 --- /dev/null +++ b/test/Function_Call.rob @@ -0,0 +1,10 @@ +int16 b(){ + t = 0; + print t; + return 0; +} + +int16 main(){ + b(); + return 0; +} diff --git a/test/Function_Sort.rob b/test/Function_Sort.rob new file mode 100644 index 0000000..0d1116b --- /dev/null +++ b/test/Function_Sort.rob @@ -0,0 +1,22 @@ +int16 Sort(int16 n){ + return 0; +} + +int16 main(){ + a = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; + + Sort(16); + i = 0; + while (i < 16){ + c = a[i]; + print c; + i++; + } + + Sort(16); + i = 0; + while (i < 16){ + print c; + i++; + } +} diff --git a/test/Function_w_Conditional.rob b/test/Function_w_Conditional.rob new file mode 100644 index 0000000..c722558 --- /dev/null +++ b/test/Function_w_Conditional.rob @@ -0,0 +1,15 @@ +int16 func (){ + a = true; + if (a == true){ + print 1; + } + else { + print 2; + } + return 0; +} + +int16 main(){ + b = func(); + return 0; +} diff --git a/test/Falhando.txt b/test/Function_w_Params_00.rob similarity index 50% rename from test/Falhando.txt rename to test/Function_w_Params_00.rob index 0561a43..60c00a1 100644 --- a/test/Falhando.txt +++ b/test/Function_w_Params_00.rob @@ -1,4 +1,4 @@ -int func (bool a){ +int16 func (bool a){ if (a == true){ print 1; } @@ -8,4 +8,7 @@ int func (bool a){ return 0; } -b = func(true); +int16 main(){ + b = func(true); + return 0; +} diff --git a/test/Function_w_Params_01.rob b/test/Function_w_Params_01.rob new file mode 100644 index 0000000..4af7fb1 --- /dev/null +++ b/test/Function_w_Params_01.rob @@ -0,0 +1,7 @@ +int16 quadrado(int16 a){ + return a * a; +} + +int16 main(){ + print quadrado(3); +} diff --git a/test/Int_Function.txt b/test/Int_Function.txt deleted file mode 100644 index 4fb19ee..0000000 --- a/test/Int_Function.txt +++ /dev/null @@ -1,5 +0,0 @@ -int quadrado(int a){ - return a * a; -} - -print quadrado(3); diff --git a/test/Int_Vector.txt b/test/Int_Vector.txt deleted file mode 100644 index d46d6fe..0000000 --- a/test/Int_Vector.txt +++ /dev/null @@ -1,7 +0,0 @@ -vector = {3, 2, 5, 2, 1, 4, 5, 6, 8, 2, 1}; - -i = 0; -while (i < 10){ - print vector[i]; - i = i + 1; -} diff --git a/test/Int_Vector_R.txt b/test/Int_Vector_R.txt deleted file mode 100644 index 7f765d9..0000000 --- a/test/Int_Vector_R.txt +++ /dev/null @@ -1,7 +0,0 @@ -vector = {3:3, 2:3, 1:3, 2}; - -i = 0; -while (i < 10){ - print vector[i]; - i = i + 1; -} diff --git a/test/Falhando2.txt b/test/Main_w_Condition.rob similarity index 74% rename from test/Falhando2.txt rename to test/Main_w_Condition.rob index 8db9f23..3dc7ba9 100644 --- a/test/Falhando2.txt +++ b/test/Main_w_Condition.rob @@ -1,4 +1,4 @@ -int func (){ +int16 main(){ a = true; if (a == true){ print 1; @@ -8,5 +8,3 @@ int func (){ } return 0; } - -b = func(); diff --git a/test/NewNew.txt b/test/NewNew.txt deleted file mode 100644 index 364429b..0000000 --- a/test/NewNew.txt +++ /dev/null @@ -1,2 +0,0 @@ -var = 3; -print (var); diff --git a/test/NewSort.txt b/test/NewSort.txt deleted file mode 100644 index b56078c..0000000 --- a/test/NewSort.txt +++ /dev/null @@ -1,20 +0,0 @@ -a = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; -int Sort(int n){ - - return 0; -} - -Sort(16); -i = 0; -while (i < 16){ - c = a[i]; - print c; - i++; -} - -Sort(16); -i = 0; -while (i < 16){ - print c; - i++; -} diff --git a/test/New_Teste.txt b/test/New_Teste.txt index 2252290..c4101f0 100644 --- a/test/New_Teste.txt +++ b/test/New_Teste.txt @@ -1,4 +1,4 @@ -int function_name (int b){ +int16 function_name (int16 b){ if (b >= 3) print (b * 2); else{ @@ -7,12 +7,14 @@ int function_name (int b){ return b + 1; } -c = {3:5, 24:3}; -a = function_name(3); -print (a); +int16 main(){ + c = {3:5, 24:3}; + a = function_name(3); + print (a); -i = 0; -while (i < 8){ - print (c[i]); - i = i+1; + i = 0; + while (i < 8){ + print (c[i]); + i = i+1; + } } diff --git a/test/Print.rob b/test/Print.rob new file mode 100644 index 0000000..128ca4b --- /dev/null +++ b/test/Print.rob @@ -0,0 +1,4 @@ +int16 main(){ + var = 3; + print (var); +} diff --git a/test/Sort.txt b/test/Sort.txt index b63f768..ea8f825 100644 --- a/test/Sort.txt +++ b/test/Sort.txt @@ -1,5 +1,5 @@ a = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; -int sort (int n) +int16 sort (int16 n) { t = 0; s = 0; @@ -22,17 +22,19 @@ int sort (int n) return 0; } +int16 main() +{ + i = 0; + while (i < 16){ + print a[i]; + i++; + } + print "\n"; -i = 0; -while (i < 16){ - print a[i]; - i++; -} -print "\n"; - -sort (16); -i = 0; -while(i < 16){ - print a[i]; - i++; + sort (16); + i = 0; + while(i < 16){ + print a[i]; + i++; + } } diff --git a/test/Vector_Float.rob b/test/Vector_Float.rob new file mode 100644 index 0000000..f2050fa --- /dev/null +++ b/test/Vector_Float.rob @@ -0,0 +1,9 @@ +int16 main(){ + vector = {3, 2, 5, 2, 1, 4.2, 5, 6, 8, 2, 1}; + + i = 0; + while (i < 10){ + print vector[i]; + i = i + 1; + } +} diff --git a/test/Vector_Float_R.rob b/test/Vector_Float_R.rob new file mode 100644 index 0000000..a6fb7c5 --- /dev/null +++ b/test/Vector_Float_R.rob @@ -0,0 +1,9 @@ +int16 main(){ + vector = {3:3, 4.2}; + + i = 0; + while (i < 4){ + print vector[i]; + i = i + 1; + } +} diff --git a/test/Vector_Int.rob b/test/Vector_Int.rob new file mode 100644 index 0000000..4524cc8 --- /dev/null +++ b/test/Vector_Int.rob @@ -0,0 +1,9 @@ +int16 main(){ + vector = {3, 2, 5, 2, 1, 4, 5, 6, 8, 2, 1}; + + i = 0; + while (i < 10){ + print vector[i]; + i = i + 1; + } +} diff --git a/test/Vector_Int_R.rob b/test/Vector_Int_R.rob new file mode 100644 index 0000000..8376f0b --- /dev/null +++ b/test/Vector_Int_R.rob @@ -0,0 +1,9 @@ +int16 main(){ + vector = {3:3, 2:3, 1:3, 2}; + + i = 0; + while (i < 10){ + print vector[i]; + i = i + 1; + } +} diff --git a/test/abc.txt b/test/abc.txt deleted file mode 100644 index ad1274f..0000000 --- a/test/abc.txt +++ /dev/null @@ -1,7 +0,0 @@ -int b (){ - t = 0; - print t; - return 0; -} - -b(); From 17b3111a8d73feba837e2d690c35c6c1c683d39f Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 10 Jul 2023 11:25:04 -0300 Subject: [PATCH 008/117] doc(src): Added folder to .o files and a .gitkeep --- src/out/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/out/.gitkeep diff --git a/src/out/.gitkeep b/src/out/.gitkeep new file mode 100644 index 0000000..e69de29 From af1b9c0a52f9c7658d30bbd8a4ed30589666b3a5 Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 10 Jul 2023 11:35:57 -0300 Subject: [PATCH 009/117] remove(OLD): Deleted old main, and node files. They're no longer necessary, it's being defined in BackLLVM and Header --- main.cpp | 73 -------- node.h | 553 ------------------------------------------------------- 2 files changed, 626 deletions(-) delete mode 100644 main.cpp delete mode 100644 node.h diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 7cee12d..0000000 --- a/main.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "node.h" - -extern int yyparse(); -extern FILE *yyin; - -// Program main module -Module *mainmodule; - -// symbol table -map tabelasym; -map symexists; - -// file name -char *build_filename; - -// arduino functions -Function *analogWrite; -Function *analogRead; -Function *delay; -Function *delayMicroseconds; -Function *init; -Function *print; -Function *i16div; - - -int main(int argc, char *argv[]) { - - // Compila o arquivo passado como parâmetro - if (argc > 1) { - build_filename = argv[1]; - yyin = fopen(build_filename, "r"); - if (yyin == NULL) { - fprintf(stderr, "Could not open file %s.\n", build_filename); - exit(1); - } - } - yyparse(); - if (yyin) - fclose(yyin); - - llvm::legacy::PassManager pm; - - /*pm.add(createPromoteMemoryToRegisterPass()); - pm.add(createInstructionCombiningPass()); - pm.add(createReassociatePass()); - pm.add(createCFGSimplificationPass()); - pm.add(createLICMPass()); - pm.add(createGVNPass()); - pm.add(createSCCPPass()); - pm.add(createCFGSimplificationPass()); - pm.add(createAggressiveDCEPass()); - pm.add(createDeadStoreEliminationPass()); - pm.add(createCFGSimplificationPass());*/ - - // imprime o código intermediário gerado - pm.add(createPrintModulePass(outs())); - - pm.run(*mainmodule); - - return 0; -} - diff --git a/node.h b/node.h deleted file mode 100644 index fadc002..0000000 --- a/node.h +++ /dev/null @@ -1,553 +0,0 @@ -#ifndef NODE_H -#define NODE_H - -#define ENABLE_ARDUINO -#define ENABLE_PRINT - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace llvm; - -class Node; -class Stmts; -#include "bison.hpp" - -extern int yyerror(const char *s); -extern int yylex(); - -// Program main module -extern Module *mainmodule; -extern char* build_filename; -static LLVMContext global_context; - -// symbol table -extern map tabelasym; -extern map symexists; - -// arduino functions -extern Function *analogWrite; -extern Function *analogRead; -extern Function *delay; -extern Function *delayMicroseconds; - -extern Function *init; -extern Function *print; -extern Function *i16div; - -class Node { -public: - virtual Value *generate(Function *func, BasicBlock *block) = 0; - virtual ~Node() {} -}; - -class Int8: public Node { -private: - char number; -public: - Int8(char n): number(n) {} - Value *generate(Function *func, BasicBlock *block) { - return ConstantInt::get(Type::getInt8Ty(global_context), number); - } -}; - -class Int16: public Node { -private: - short number; -public: - Int16(short n): number(n) {} - Value *generate(Function *func, BasicBlock *block) { - return ConstantInt::get(Type::getInt16Ty(global_context), number); - } -}; - -class Int32: public Node { -private: - int number; -public: - Int32(int n): number(n) {} - Value *generate(Function *func, BasicBlock *block) { - return ConstantInt::get(Type::getInt32Ty(global_context), number); - } -}; - -class Float: public Node { -private: - float number; -public: - Float(float n): number(n) {} - Value *generate(Function *func, BasicBlock *block) { - return ConstantFP::get(Type::getFloatTy(global_context), number); - } -}; - -class String: public Node { -private: - string str; -public: - String(const char *s): str(s) {} - Value *generate(Function *func, BasicBlock *block) { - return ConstantDataArray::getString(global_context, str, true);; - } -}; - -class Load: public Node { -private: - string ident; -public: - Load(const char *i): ident(i) { - auto var = symexists.find(ident); - if (var == symexists.end()) - yyerror("Variable not declared:"); - } - - Value *generate(Function *func, BasicBlock *block) { - LoadInst *ret = new LoadInst(tabelasym[ident]->getAllocatedType(), tabelasym[ident], ident, false, block); - return ret; - } -}; - -class Variable: public Node { -private: - string name; - Node *expr; -public: - Variable(const char *n, Node *e) : name(n), expr(e) { - symexists[n] = 1; // variable exists! - } - - Value *generate(Function *func, BasicBlock *block) { - auto left = tabelasym.find(name); - Value *leftv; - Value *exprv = expr->generate(func, block); - if (left == tabelasym.end()) { - tabelasym[name] = new AllocaInst(exprv->getType(), 0, name, block); - leftv = tabelasym[name]; - } - else - leftv = left->second; - - StoreInst *ret = new StoreInst(exprv, leftv, false, block); - return ret; - - } -}; - -class InPort: public Node { -private: - string port; -public: - InPort(const char *p): port(p) {} - Value *generate(Function *func, BasicBlock *block) { - vector args; - - Int8 prt(atoi(port.c_str())); - args.push_back(prt.generate(func, block)); - - ArrayRef argsRef(args); - return CallInst::Create(analogRead, argsRef, "", block); - } -}; - -class OutPort: public Node { -private: - string port; - Node *expr; -public: - OutPort (const char *p, Node *e) : port(p), expr(e) {} - Value *generate(Function *func, BasicBlock *block) { - vector args; - - Int8 prt(atoi(port.c_str())); - args.push_back(prt.generate(func, block)); - - Value *value = expr->generate(func, block); - Value *nvalue = value; - if (value->getType()->isFloatTy()) - nvalue = new FPToSIInst(value, Type::getInt16Ty(global_context), "trunci", block); - - //args.push_back(nvalue); - Value *int8v = new TruncInst(value, Type::getInt8Ty(global_context), "", block); - args.push_back(int8v); - - ArrayRef argsRef(args); - return CallInst::Create(analogWrite, argsRef, "", block); - } -}; - -class Delay: public Node { -private: - Node *ms; -public: - Delay (Node *mseg) : ms(mseg) {} - Value *generate(Function *func, BasicBlock *block) { - Value *msv = ms->generate(func, block); - Value *msv32 = new SExtInst(msv, Type::getInt32Ty(global_context), "conv", block); - - vector args; - args.push_back(msv32); - ArrayRef argsRef(args); - return CallInst::Create(delay, argsRef, "", block); - } -}; - -class BinaryOp: public Node { -private: - char op; - Node *lhsn; - Node *rhsn; -public: - BinaryOp (Node *l, char op, Node *r) : lhsn(l), rhsn(r) { - this->op =op; - } - Instruction *binary_operator(enum Instruction::BinaryOps opint, - enum Instruction::BinaryOps opflt, Function *func, BasicBlock *block) { - - Value *lhs = lhsn->generate(func, block); - Value *rhs = rhsn->generate(func, block); - - Type *Ty1 = lhs->getType(); - Type *Ty2 = rhs->getType(); - - if (Ty1->isIntegerTy() && Ty2->isIntegerTy()) { - /*fallback SDiv disabled - if (opint == Instruction::SDiv) { - vector args; - args.push_back(lhs); - args.push_back(rhs); - ArrayRef argsRef(args); - return CallInst::Create(i16div, argsRef, "", block); - }*/ - return BinaryOperator::Create(opint, lhs, rhs, "", block); - } - else { - Value *flhs = lhs, *frhs = rhs; - if (Ty1->isIntegerTy()) - flhs = new SIToFPInst(lhs, Type::getFloatTy(global_context), "castitof", block); - if (Ty2->isIntegerTy()) - frhs = new SIToFPInst(rhs, Type::getFloatTy(global_context), "castitof", block); - return BinaryOperator::Create(opflt, flhs, frhs, "binop", block); - } - } - - Value *generate(Function *func, BasicBlock *block) { - switch (op) { - case '+' : return binary_operator(Instruction::Add, Instruction::FAdd, func, block); - case '-' : return binary_operator(Instruction::Sub, Instruction::FSub, func, block); - case '*' : return binary_operator(Instruction::Mul, Instruction::FMul, func, block); - case '/' : return binary_operator(Instruction::SDiv, Instruction::FDiv, func, block); - default: return NULL; - } - } -}; - -class CmpOp: public Node { -private: - Node *lexpn; - Node *rexpn; - int op; -public: - CmpOp (Node *l, int op, Node *r) : lexpn(l), rexpn(r) { - this->op = op; - } - Value *generate(Function *func, BasicBlock *block) { - CmpInst::Predicate predicate; - - Value *lexp = lexpn->generate(func, block); - Value *rexp = rexpn->generate(func, block); - - Type *Ty1 = lexp->getType(); - Type *Ty2 = rexp->getType(); - int isFCmp = !Ty1->isIntegerTy() || !Ty2->isIntegerTy(); - if (isFCmp) { - if (Ty1->isIntegerTy()) - lexp = new SIToFPInst(lexp, Type::getFloatTy(global_context), "", block); - if (Ty2->isIntegerTy()) - rexp = new SIToFPInst(rexp, Type::getFloatTy(global_context), "", block); - } - - if (op == EQ_OP) predicate = isFCmp ? FCmpInst::FCMP_OEQ : ICmpInst::ICMP_EQ; - else if (op == NE_OP) predicate = isFCmp ? FCmpInst::FCMP_UNE : ICmpInst::ICMP_NE; - else if (op == GE_OP) predicate = isFCmp ? FCmpInst::FCMP_OGE : ICmpInst::ICMP_SGE; - else if (op == LE_OP) predicate = isFCmp ? FCmpInst::FCMP_OLE : ICmpInst::ICMP_SLE; - else if (op == GT_OP) predicate = isFCmp ? FCmpInst::FCMP_OGT : ICmpInst::ICMP_SGT; - else if (op == LT_OP) predicate = isFCmp ? FCmpInst::FCMP_OLT : ICmpInst::ICMP_SLT; - else { - cerr << "Invalid logical operator" << op << endl; - return NULL; - } - - if (isFCmp) - return new FCmpInst(*block, predicate, lexp, rexp, "cmpf"); - else { - return new ICmpInst(*block, predicate, lexp, rexp, "cmpi"); - } - } -}; - -class Capsule: public Node { -private: - Node *node; -public: - Capsule (Node *n) : node(n) {} - Value *generate(Function *func, BasicBlock *block) { - return node->generate(func, block); - } -}; - -class If: public Node { -private: - Node *expr; - Node *thenst; - Node *elsest; -public: - If (Node *e, Node *tst, Node *est) : expr(e), thenst(tst), elsest(est) {} - Value *generate(Function *func, BasicBlock *block) { - Value *exprv = expr->generate(func, block); - - BasicBlock *thenb = BasicBlock::Create(global_context, "if_then", func, 0); - Value *thennewb = thenst->generate(func, thenb); - - Value *elsenewb = NULL; - BasicBlock *elseb = BasicBlock::Create(global_context, "if_else", func, 0); - if (elsest != 0) { - elsenewb = elsest->generate(func, elseb); - } - - BranchInst::Create(thenb, elseb, exprv, block); - - BasicBlock *mergb = BasicBlock::Create(global_context, "if_cont", func, 0); - - if (thennewb->getValueID() == Value::BasicBlockVal) - BranchInst::Create(mergb, (BasicBlock*)thennewb); - else - BranchInst::Create(mergb, thenb); - - if (elsenewb && elsenewb->getValueID() == Value::BasicBlockVal) - BranchInst::Create(mergb, (BasicBlock*)elsenewb); - else - BranchInst::Create(mergb, elseb); - - return mergb; - } -}; - -class While: public Node { -private: - Node *expr; - Node *stmts; -public: - While(Node *e, Node *stms) : expr(e), stmts(stms) {} - Value *generate(Function *func, BasicBlock *block) { - BasicBlock *condwhile = BasicBlock::Create(global_context, "while_cond", func, 0); - Value *exprv = expr->generate(func, condwhile); - - BasicBlock *bodywhile = BasicBlock::Create(global_context, "while_body", func, 0); - Value *newb = stmts->generate(func, bodywhile); - - BasicBlock *endwhile = BasicBlock::Create(global_context, "while_end", func, 0); - - BranchInst::Create(condwhile, block); - BranchInst::Create(bodywhile, endwhile, exprv, condwhile); - - if (newb->getValueID() == Value::BasicBlockVal) - BranchInst::Create(condwhile, (BasicBlock*)newb); - else - BranchInst::Create(condwhile, bodywhile); - - return endwhile; - } -}; - -class Stmts: public Node { -private: - std::vector stmts; -public: - Stmts(Node *s) { - this->stmts.push_back(s); - } - - void append(Node *s) { - stmts.push_back(s); - } - - Value *generate(Function *func, BasicBlock *block) { - for(Node *n: stmts) { - Value *b = n->generate(func, block); - if (b->getValueID() == Value::BasicBlockVal) - block = (BasicBlock*)b; - } - return block; - } -}; - -class Print: public Node { -private: - Node *expr; -public: - Print(Node *e) : expr(e) {} - Value *generate(Function *func, BasicBlock *block) { - vector args; - - Value *lexp = expr->generate(func, block); - Type *ty1 = lexp->getType(); - char cty1 = 0; - if (ty1->isIntegerTy()) - cty1 = 0; - else if (ty1->isFloatTy()) - cty1 = 1; - else if (ty1->isArrayTy()) - cty1 = 2; - else - yyerror("Type not supported by print."); - - Int8 prt(cty1); - args.push_back(prt.generate(func, block)); - - AllocaInst *ptr_aux = new AllocaInst(lexp->getType(), 0, "", block); - StoreInst *st = new StoreInst(lexp, ptr_aux, false, block); - CastInst *cinst = new BitCastInst(ptr_aux, PointerType::get(IntegerType::get(global_context, 8), 0), "", block); - args.push_back(cinst); - - ArrayRef argsRef(args); - return CallInst::Create(print, argsRef, "", block); - } -}; - -class Program { -public: - Program() {} - - void declara_auxiliary_c_funcs() { - std::vector arg_types; - FunctionType *ftype; - - #ifdef ENABLE_ARDUINO - // analogRead - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - ftype = FunctionType::get(Type::getInt16Ty(global_context), - ArrayRef(arg_types), false); - analogRead = Function::Create(ftype, Function::ExternalLinkage, "analogRead", mainmodule); - analogRead->setCallingConv(CallingConv::C); - - // analogWrite - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - //arg_types.push_back(Type::getInt16Ty(global_context)); - arg_types.push_back(Type::getInt8Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); -// analogWrite = Function::Create(ftype, Function::ExternalLinkage, "analogWrite", mainmodule); - analogWrite = Function::Create(ftype, Function::ExternalLinkage, "digitalWrite", mainmodule); - - analogWrite->setCallingConv(CallingConv::C); - - // delay - arg_types.clear(); - arg_types.push_back(Type::getInt32Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - delay = Function::Create(ftype, Function::ExternalLinkage, "delay", mainmodule); - delay->setCallingConv(CallingConv::C); - - - // delayMicroseconds - arg_types.clear(); - arg_types.push_back(Type::getInt32Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - delayMicroseconds = Function::Create(ftype, Function::ExternalLinkage, "delayMicroseconds", mainmodule); - delayMicroseconds->setCallingConv(CallingConv::C); - - // init - ftype = FunctionType::get(Type::getVoidTy(global_context), false); - init = Function::Create(ftype, Function::ExternalLinkage, "init", mainmodule); - init->setCallingConv(CallingConv::C); - #endif - - #ifdef ENABLE_PRINT - // print - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - arg_types.push_back(PointerType::get(IntegerType::get(global_context, 8), 0)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - print = Function::Create(ftype, Function::ExternalLinkage, "print", mainmodule); - print->setCallingConv(CallingConv::C); - #endif - - /* Not necessary anymore. Stay as an example - AttributeSet print_func_attrs; - print_func_attrs = - print_func_attrs.addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::NoUnwind) - .addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::StackProtect) - .addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::UWTable) - .addAttribute(global_context, 1, Attribute::ZExt); - print->setAttributes(print_func_attrs); */ - - // i16divse) - /*arg_types.clear(); - arg_types.push_back(Type::getInt16Ty(global_context)); - arg_types.push_back(Type::getInt16Ty(global_context)); - ftype = FunctionType::get(Type::getInt16Ty(global_context), - ArrayRef(arg_types), false); - i16div = Function::Create(ftype, Function::ExternalLinkage, "i16div", mainmodule); - i16div->setCallingConv(CallingConv::C);*/ - } - - void generate(Node *n) { - mainmodule = new Module(build_filename, global_context); - - FunctionType *ftype = FunctionType::get(Type::getInt16Ty(global_context), - ArrayRef(), false); - Function *mainfunc = Function::Create(ftype,GlobalValue::ExternalLinkage, "main", mainmodule); - - BasicBlock *mainblock = BasicBlock::Create(global_context, "entry", mainfunc, 0); - - declara_auxiliary_c_funcs(); - - // call Arduino init - #ifdef ENABLE_ARDUINO - std::vector args; - ArrayRef argsRef(args); - CallInst *call = CallInst::Create(init, argsRef, "", mainblock); - #endif - - // generate the program! - Value *b = n->generate(mainfunc, mainblock); - if (b->getValueID() == Value::BasicBlockVal) { - mainblock = (BasicBlock*)b; - } - - Int16 ret(0); - Value *retv = ret.generate(mainfunc, mainblock); - ReturnInst::Create(global_context, retv, mainblock); - } -}; - -/* -class _: public Node { -private: -public: - _ () {} - Value *generate(Function *func, BasicBlock *block) { - } -}; -*/ - -#endif - From 25c2e39c5f213514fe780a8b6d0dfb7a65f55127 Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 10 Jul 2023 12:03:46 -0300 Subject: [PATCH 010/117] update(Test): Adjusted remaining tests --- test/Compare_Lobal_Global_01.rob | 12 ++++++++++++ test/Compare_Local_Global_00.rob | 11 +++++++++++ test/{New_Teste.txt => Function_Call_00.rob} | 0 test/Function_Return.rob | 16 ++++++++++++++++ test/Operations.rob | 13 +++++++++++++ test/Operations_00.rob | 8 ++++++++ ...este_while_return.txt => Return_in_While.rob} | 11 ++++++----- test/{Sort.txt => Sort_01.rob} | 0 test/Var_Vector_R.txt | 8 -------- test/Vector_MatrixValue.rob | 11 +++++++++++ test/Vector_R.rob | 10 ++++++++++ test/Vector_Update.rob | 6 ++++++ test/Vector_VectorValue.rob | 6 ++++++ test/Vector_VectorValue_01.rob | 8 ++++++++ test/test2.txt | 4 ---- test/testando.txt | 6 ------ test/teste.txt | 11 ----------- test/teste23.txt | 11 ----------- test/testeHalf.txt | 1 - test/teste_func_matrix.txt | 10 ---------- test/teste_func_vector.txt | 10 ---------- test/teste_function_returns.txt | 15 --------------- test/teste_idx_matrix.txt | 11 ----------- test/teste_idx_vector.txt | 8 -------- test/updateteste.txt | 4 ---- test/varpp.txt | 6 ------ 26 files changed, 107 insertions(+), 110 deletions(-) create mode 100644 test/Compare_Lobal_Global_01.rob create mode 100644 test/Compare_Local_Global_00.rob rename test/{New_Teste.txt => Function_Call_00.rob} (100%) create mode 100644 test/Function_Return.rob create mode 100644 test/Operations.rob create mode 100644 test/Operations_00.rob rename test/{teste_while_return.txt => Return_in_While.rob} (56%) rename test/{Sort.txt => Sort_01.rob} (100%) delete mode 100644 test/Var_Vector_R.txt create mode 100644 test/Vector_MatrixValue.rob create mode 100644 test/Vector_R.rob create mode 100644 test/Vector_Update.rob create mode 100644 test/Vector_VectorValue.rob create mode 100644 test/Vector_VectorValue_01.rob delete mode 100644 test/test2.txt delete mode 100644 test/testando.txt delete mode 100644 test/teste.txt delete mode 100644 test/teste23.txt delete mode 100644 test/testeHalf.txt delete mode 100644 test/teste_func_matrix.txt delete mode 100644 test/teste_func_vector.txt delete mode 100644 test/teste_function_returns.txt delete mode 100644 test/teste_idx_matrix.txt delete mode 100644 test/teste_idx_vector.txt delete mode 100644 test/updateteste.txt delete mode 100644 test/varpp.txt diff --git a/test/Compare_Lobal_Global_01.rob b/test/Compare_Lobal_Global_01.rob new file mode 100644 index 0000000..b813263 --- /dev/null +++ b/test/Compare_Lobal_Global_01.rob @@ -0,0 +1,12 @@ +matriz = {{7, 8}, {9,10}}; + +int16 fa(int16 i, int16 j) { + localmatriz = {{1,2},{3,4},{5,6}}; + return localmatriz[i][j]; +} + +int16 main() +{ + print matriz[1][1]; // print 10 + print fa(2,1); // print 6 +} diff --git a/test/Compare_Local_Global_00.rob b/test/Compare_Local_Global_00.rob new file mode 100644 index 0000000..59b66bf --- /dev/null +++ b/test/Compare_Local_Global_00.rob @@ -0,0 +1,11 @@ +vector = {7, 8, 9, 10}; + +int16 fa(int16 i) { + localvector = {1,2,3,4,5,6}; + return localvector[i]; +} + +int16 main(){ + print vector[1]; // print 8 + print fa(2); // print 3 +} diff --git a/test/New_Teste.txt b/test/Function_Call_00.rob similarity index 100% rename from test/New_Teste.txt rename to test/Function_Call_00.rob diff --git a/test/Function_Return.rob b/test/Function_Return.rob new file mode 100644 index 0000000..015631a --- /dev/null +++ b/test/Function_Return.rob @@ -0,0 +1,16 @@ + +void fa(int16 a) { + a = a + 1; +} + +int16 fb(int16 b) { + b = b + 1; + if (b == 2) + return b; + return 0; +} + +int16 main(){ + fa(1); + print fb(2); +} diff --git a/test/Operations.rob b/test/Operations.rob new file mode 100644 index 0000000..d22ca5b --- /dev/null +++ b/test/Operations.rob @@ -0,0 +1,13 @@ +int16 main(){ + a = 1; + + print -1; + print -a; + print a-a; + print a-1; + print 1--a; + + if (a > a-1){ + print 2; + } +} diff --git a/test/Operations_00.rob b/test/Operations_00.rob new file mode 100644 index 0000000..134be21 --- /dev/null +++ b/test/Operations_00.rob @@ -0,0 +1,8 @@ +int16 main(){ + i = 1.2; + i++; + i+=7; + print i; + i*=2; + print i; +} diff --git a/test/teste_while_return.txt b/test/Return_in_While.rob similarity index 56% rename from test/teste_while_return.txt rename to test/Return_in_While.rob index 5a22b5d..a8c2497 100644 --- a/test/teste_while_return.txt +++ b/test/Return_in_While.rob @@ -1,12 +1,11 @@ - -void fb(int a) { +void fb(int16 a) { b = a; while(b > 3) { b = b - 1; } } -double fa(int a) { +double fa(int16 a) { b = a; while(b > 3) { b = b - 1; @@ -14,5 +13,7 @@ double fa(int a) { } } -fa(10); - +int16 main (){ + fa(10); + fb(10); +} diff --git a/test/Sort.txt b/test/Sort_01.rob similarity index 100% rename from test/Sort.txt rename to test/Sort_01.rob diff --git a/test/Var_Vector_R.txt b/test/Var_Vector_R.txt deleted file mode 100644 index 83a074a..0000000 --- a/test/Var_Vector_R.txt +++ /dev/null @@ -1,8 +0,0 @@ -b = 3; -a = {b:4, 2}; - -i = 0; -while (i < 5){ - print (a[i]); - i = i + 1; -} diff --git a/test/Vector_MatrixValue.rob b/test/Vector_MatrixValue.rob new file mode 100644 index 0000000..50a71a0 --- /dev/null +++ b/test/Vector_MatrixValue.rob @@ -0,0 +1,11 @@ +int16 main(){ + matriz = {{1, 2, 3}:2, {1:2,2}}; + + b = {5, 6, 7, 8}; + + c = matriz[2][2]; + + print c; // print 2 + print b[c]; // print 7 + print b[matriz[0][2]]; // print 8 +} diff --git a/test/Vector_R.rob b/test/Vector_R.rob new file mode 100644 index 0000000..13cb251 --- /dev/null +++ b/test/Vector_R.rob @@ -0,0 +1,10 @@ +int16 main(){ + b = 3; + a = {b:4, 2}; + + i = 0; + while (i < 5){ + i = i + 1; + } + +} diff --git a/test/Vector_Update.rob b/test/Vector_Update.rob new file mode 100644 index 0000000..5cee824 --- /dev/null +++ b/test/Vector_Update.rob @@ -0,0 +1,6 @@ +int16 main(){ + a = {3, 3, 3, 3, 3}; + print a[2]; + a[2] = 1; + print a[2]; +} diff --git a/test/Vector_VectorValue.rob b/test/Vector_VectorValue.rob new file mode 100644 index 0000000..5bb7a51 --- /dev/null +++ b/test/Vector_VectorValue.rob @@ -0,0 +1,6 @@ +int16 main(){ + a = {3, 2, 1}; + print a[1]; + b = {2, 2, 4}; + print b[a[1]]; +} diff --git a/test/Vector_VectorValue_01.rob b/test/Vector_VectorValue_01.rob new file mode 100644 index 0000000..2bbd729 --- /dev/null +++ b/test/Vector_VectorValue_01.rob @@ -0,0 +1,8 @@ +int16 main(){ + a = 1; + b = {1, 2, 3}; + c = {5, 6, 7, 8}; + print b[a]; // print 2 + print c[b[1]]; // print 7 + print c[b[a+1]]; // print 8 +} diff --git a/test/test2.txt b/test/test2.txt deleted file mode 100644 index 928e44b..0000000 --- a/test/test2.txt +++ /dev/null @@ -1,4 +0,0 @@ -a = {3, 2, 1}; -print a[1]; -b = {2, 2, 4}; -print b[a[1]]; diff --git a/test/testando.txt b/test/testando.txt deleted file mode 100644 index 0218052..0000000 --- a/test/testando.txt +++ /dev/null @@ -1,6 +0,0 @@ -if (true == true){ - print 1; -} -else{ - print 2; -} diff --git a/test/teste.txt b/test/teste.txt deleted file mode 100644 index 1e0b1e0..0000000 --- a/test/teste.txt +++ /dev/null @@ -1,11 +0,0 @@ -int a (int b){ - if (b == 1){ - return (b + 1); - } - else{ - return b; - } - return 1; -} - -print a(2); diff --git a/test/teste23.txt b/test/teste23.txt deleted file mode 100644 index 34859a2..0000000 --- a/test/teste23.txt +++ /dev/null @@ -1,11 +0,0 @@ -a = 1; - -print -1; -print -a; -print a-a; -print a-1; -print 1--a; - -if (a > a-1){ - print 2; -} diff --git a/test/testeHalf.txt b/test/testeHalf.txt deleted file mode 100644 index ede09e3..0000000 --- a/test/testeHalf.txt +++ /dev/null @@ -1 +0,0 @@ -var = ( short float ) 3.0; diff --git a/test/teste_func_matrix.txt b/test/teste_func_matrix.txt deleted file mode 100644 index e3dc27e..0000000 --- a/test/teste_func_matrix.txt +++ /dev/null @@ -1,10 +0,0 @@ - -matriz = {{7, 8}, {9,10}}; - -int fa(int i, int j) { - localmatriz = {{1,2},{3,4},{5,6}}; - return localmatriz[i][j]; -} - -print matriz[1][1]; // print 10 -print fa(2,1); // print 6 diff --git a/test/teste_func_vector.txt b/test/teste_func_vector.txt deleted file mode 100644 index ab21353..0000000 --- a/test/teste_func_vector.txt +++ /dev/null @@ -1,10 +0,0 @@ - -vector = {7, 8, 9, 10}; - -int fa(int i) { - localvector = {1,2,3,4,5,6}; - return localvector[i]; -} - -print vector[1]; // print 8 -print fa(2); // print 3 diff --git a/test/teste_function_returns.txt b/test/teste_function_returns.txt deleted file mode 100644 index d999724..0000000 --- a/test/teste_function_returns.txt +++ /dev/null @@ -1,15 +0,0 @@ - -void fa(int a) { - a = a + 1; -} - -int fb(int b) { - b = b + 1; - if (b == 2) - return b; - return 0; -} - -fa(1); -print fb(2); - diff --git a/test/teste_idx_matrix.txt b/test/teste_idx_matrix.txt deleted file mode 100644 index 0b1431b..0000000 --- a/test/teste_idx_matrix.txt +++ /dev/null @@ -1,11 +0,0 @@ - -matriz = {{1, 2, 3}:2, {1:2,2}}; - -b = {5, 6, 7, 8}; - -c = matriz[2][2]; - -print c; // print 2 -print b[c]; // print 7 -print b[matriz[0][2]]; // print 8 - diff --git a/test/teste_idx_vector.txt b/test/teste_idx_vector.txt deleted file mode 100644 index ca9d82b..0000000 --- a/test/teste_idx_vector.txt +++ /dev/null @@ -1,8 +0,0 @@ - -a = 1; -b = {1, 2, 3}; -c = {5, 6, 7, 8}; -print b[a]; // print 2 -print c[b[1]]; // print 7 -print c[b[a+1]]; // print 8 - diff --git a/test/updateteste.txt b/test/updateteste.txt deleted file mode 100644 index a8e1fe4..0000000 --- a/test/updateteste.txt +++ /dev/null @@ -1,4 +0,0 @@ -a = {3, 3, 3, 3, 3}; -print a[2]; -a[2] = 1; -print a[2]; diff --git a/test/varpp.txt b/test/varpp.txt deleted file mode 100644 index 51cfcb4..0000000 --- a/test/varpp.txt +++ /dev/null @@ -1,6 +0,0 @@ -i = 1.2; -i++; -i+=7; -print i; -i*=2; -print i; From 41f8a3090ed08d2eb028e8af776b65448822dc7d Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Tue, 11 Jul 2023 14:51:59 -0300 Subject: [PATCH 011/117] fix(Tests): Renamed Test, and removed print --- ...pare_Lobal_Global_01.rob => Compare_Local_Global_01.rob} | 0 test/Function_w_Conditional.rob | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename test/{Compare_Lobal_Global_01.rob => Compare_Local_Global_01.rob} (100%) diff --git a/test/Compare_Lobal_Global_01.rob b/test/Compare_Local_Global_01.rob similarity index 100% rename from test/Compare_Lobal_Global_01.rob rename to test/Compare_Local_Global_01.rob diff --git a/test/Function_w_Conditional.rob b/test/Function_w_Conditional.rob index c722558..fe8081e 100644 --- a/test/Function_w_Conditional.rob +++ b/test/Function_w_Conditional.rob @@ -1,10 +1,10 @@ -int16 func (){ +int16 func(){ a = true; if (a == true){ - print 1; + return 1; } else { - print 2; + return 2; } return 0; } From 5e7548a8e42061be7bea6cba62b7dc76ca23e3cf Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Tue, 11 Jul 2023 16:24:37 -0300 Subject: [PATCH 012/117] feat(ExternDeclaration): Added feature to call Extern Function Declaration --- src/ExternDeclaration.cpp | 21 +++++++++++++++++++++ src/Header.h | 1 + src/Language.l | 3 +-- src/Language.y | 11 ++++------- 4 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 src/ExternDeclaration.cpp diff --git a/src/ExternDeclaration.cpp b/src/ExternDeclaration.cpp new file mode 100644 index 0000000..8c7f253 --- /dev/null +++ b/src/ExternDeclaration.cpp @@ -0,0 +1,21 @@ +#include "Header.h" + +Value *ExternDeclaration::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + auto sym = search_symbol(name); + if (sym != NULL) { + yyerrorcpp("Function/symbol " + name + " already defined.", this); + yyerrorcpp(name + " was first defined here.", sym); + return NULL; + } + + + std::vector arg_types; + int i; + for (i = 0; i < parameters->getNumParams(); i++) + arg_types.push_back(parameters->getParamType(i)); + FunctionType *ftype = FunctionType::get(Type::getInt32Ty(global_context), ArrayRef(arg_types), false); + Function *function = Function::Create(ftype, GlobalValue::ExternalLinkage, name.c_str(), mainmodule); + tabelasym[allocblock][name] = new RobSymbol(function); + return function; +} + diff --git a/src/Header.h b/src/Header.h index 7f926e2..810661b 100644 --- a/src/Header.h +++ b/src/Header.h @@ -162,6 +162,7 @@ static RobSymbol *search_symbol(const string& ident, BasicBlock *firstb = NULL, #include "Coercion.h" #include "Delay.h" #include "Double.h" +#include "ExternDeclaration.h" #include "Float.h" #include "Float128.h" #include "FunctionCall.h" diff --git a/src/Language.l b/src/Language.l index cc633ad..85d7df6 100644 --- a/src/Language.l +++ b/src/Language.l @@ -25,6 +25,7 @@ extern int yycolnew; "//".*$ { /* line comment */} +"extern" { return TOK_EXTERN; } "register" { return TOK_REGISTER; } "volatile" { return TOK_VOLATILE; } "const" { return TOK_CONST; } @@ -50,8 +51,6 @@ extern int yycolnew; "while" { return TOK_WHILE; } "loop" { return TOK_LOOP; } -"print" { return TOK_PRINT; } - "in"[0-9]+ { yylval.port = strndup(yytext+2, yyleng-2); return TOK_IN; } diff --git a/src/Language.y b/src/Language.y index 30ed9e4..a09a529 100644 --- a/src/Language.y +++ b/src/Language.y @@ -17,10 +17,9 @@ extern int errorsfound; %define parse.error verbose -%token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST +%token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST TOK_EXTERN %token TOK_IF TOK_ELSE %token TOK_LOOP TOK_WHILE -%token TOK_PRINT %token TOK_IN TOK_OUT TOK_STEPPER TOK_SERVO %token TOK_DELAY TOK_AND TOK_OR %token TOK_IDENTIFIER TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE @@ -51,7 +50,7 @@ extern int errorsfound; } %type term term2 expr factor stmt gstmt condblock elseblock whileblock logicexpr -%type logicterm logicfactor TOK_AND TOK_OR printstmt fe eventblock unary +%type logicterm logicfactor TOK_AND TOK_OR fe eventblock unary %type funcblock returnblock registerstmt cast %type element %type elements relements @@ -97,6 +96,7 @@ gstmts : gstmts gstmt { $1->append($2); } ; gstmt : TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($1, $3, qnone); } + | TOK_EXTERN TOK_IDENTIFIER '(' funcparams ')' ';' { $$ = new ExternDeclaration($2, $4); } | TOK_CONST TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qconst); } | TOK_VOLATILE TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qvolatile); } | TOK_IDENTIFIER '=' relements ';' { $$ = new Array($1, $3); } @@ -149,7 +149,6 @@ stmt : gstmt { $$ = $1; } | condblock { $$ = $1; } | whileblock { $$ = $1; } | returnblock ';' { $$ = $1; } - | printstmt ';' { $$ = $1; } | TOK_STEPPER expr ';' { $$ = new StepperGoto($1, $2); } | TOK_SERVO expr ';' { $$ = new ServoGoto($2); } | TOK_IDENTIFIER '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6);} @@ -299,6 +298,7 @@ factor : '(' expr ')' { $$ = $2; } | TOK_DOUBLE { $$ = new Double($1); } | TOK_LDOUBLE { $$ = new Float128($1); } | TOK_IN { $$ = new InPort($1); } + | TOK_STRING { $$ = new String($1); } | TOK_IDENTIFIER '(' paramscall ')' { $$ = new FunctionCall($1, $3); } | unary { $$ = $1; } ; @@ -311,9 +311,6 @@ unary : '-' factor { $$ = new BinaryOp($2, '*', getNodeForIntConst(-1)); } cast : '(' type_f ')' factor { $$ = new Cast($2, $4); } ; -printstmt : TOK_PRINT TOK_STRING { $$ = new Print(new String($2)); } - | TOK_PRINT expr { $$ = new Print($2); } - registerstmt : TOK_REGISTER registertype TOK_IDENTIFIER TOK_AT expr { $$ = new Pointer($3, $2, $5, true); } From d674e74bd5b3b95ab434e6685753aa05dde7395e Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Tue, 11 Jul 2023 16:25:08 -0300 Subject: [PATCH 013/117] fix(ExternDeclaration): Added missing Header to Extern Function Declaration --- src/ExternDeclaration.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/ExternDeclaration.h diff --git a/src/ExternDeclaration.h b/src/ExternDeclaration.h new file mode 100644 index 0000000..6591ab0 --- /dev/null +++ b/src/ExternDeclaration.h @@ -0,0 +1,18 @@ +#ifndef __EXTERNDECLARATION_H__ +#define __EXTERNDECLARATION_H__ +#include "Node.h" + +class ExternDeclaration: public Node { +private: + string name; + FunctionParams *parameters; +public: + ExternDeclaration(string name, FunctionParams *fp) { + this->name = name; + this->parameters = fp; + } + + virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; +}; + +#endif From c674495ec09aa699b233c49928e60ebc87a3bd7d Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Tue, 11 Jul 2023 16:26:03 -0300 Subject: [PATCH 014/117] test(Bellmanford): Added sample to extern function call --- test/bellmanford.rob | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/bellmanford.rob b/test/bellmanford.rob index 44d4467..be3abb4 100644 --- a/test/bellmanford.rob +++ b/test/bellmanford.rob @@ -1,4 +1,4 @@ - +extern print(char value); INT_MAX = 9999; // edges (u,v,w) @@ -40,16 +40,16 @@ int16 bellmanford(int16 V, int16 E, int16 src) { y = graph[i][1]; weight = graph[i][2]; if (dis[x] != INT_MAX and dis[x] + weight < dis[y]) - print "Graph contains negative weight cycle\n"; + print ("Graph contains negative weight cycle\n"); i++; } - print "Vertex Distance from Source\n"; + print ("Vertex Distance from Source\n"); i = 0; while (i < V) { - print i; - print dis[i]; - print "\n"; + print (i); + print (dis[i]); + print ("\n"); i++; } From da144be60ac67d199f265cf1bf70c6ff7fd98846 Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Tue, 11 Jul 2023 18:06:50 -0300 Subject: [PATCH 015/117] feat(Extern): Adjusted Extern to config extern function type --- src/ExternDeclaration.cpp | 12 +++++++----- src/ExternDeclaration.h | 4 +++- src/Language.y | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/ExternDeclaration.cpp b/src/ExternDeclaration.cpp index 8c7f253..8746c95 100644 --- a/src/ExternDeclaration.cpp +++ b/src/ExternDeclaration.cpp @@ -8,12 +8,14 @@ Value *ExternDeclaration::generate(Function *func, BasicBlock *block, BasicBlock return NULL; } - std::vector arg_types; - int i; - for (i = 0; i < parameters->getNumParams(); i++) - arg_types.push_back(parameters->getParamType(i)); - FunctionType *ftype = FunctionType::get(Type::getInt32Ty(global_context), ArrayRef(arg_types), false); + if (parameters->getNumParams() != 0) + for (int i = 0; i < parameters->getNumParams(); i++) + arg_types.push_back(parameters->getParamType(i)); + + Type *xtype = robTollvmDataType[tipo]; + FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); + Function *function = Function::Create(ftype, GlobalValue::ExternalLinkage, name.c_str(), mainmodule); tabelasym[allocblock][name] = new RobSymbol(function); return function; diff --git a/src/ExternDeclaration.h b/src/ExternDeclaration.h index 6591ab0..b39b836 100644 --- a/src/ExternDeclaration.h +++ b/src/ExternDeclaration.h @@ -4,10 +4,12 @@ class ExternDeclaration: public Node { private: + LanguageDataType tipo; string name; FunctionParams *parameters; public: - ExternDeclaration(string name, FunctionParams *fp) { + ExternDeclaration(LanguageDataType tipo, string name, FunctionParams *fp) { + this->tipo = tipo; this->name = name; this->parameters = fp; } diff --git a/src/Language.y b/src/Language.y index a09a529..665b211 100644 --- a/src/Language.y +++ b/src/Language.y @@ -96,7 +96,7 @@ gstmts : gstmts gstmt { $1->append($2); } ; gstmt : TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($1, $3, qnone); } - | TOK_EXTERN TOK_IDENTIFIER '(' funcparams ')' ';' { $$ = new ExternDeclaration($2, $4); } + | TOK_EXTERN type_f TOK_IDENTIFIER '(' funcparams ')' ';' { $$ = new ExternDeclaration($2, $3, $5); } | TOK_CONST TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qconst); } | TOK_VOLATILE TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qvolatile); } | TOK_IDENTIFIER '=' relements ';' { $$ = new Array($1, $3); } From 81f17dd126babc0d7612463444ae78d4b24f74af Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Tue, 11 Jul 2023 18:36:39 -0300 Subject: [PATCH 016/117] feat(test): Adjusted test files, with print extern --- test/Compare_Local_Global_00.rob | 6 ++-- test/Compare_Local_Global_01.rob | 6 ++-- test/Fibonacci.rob | 12 ++++---- test/Function_Call.rob | 4 ++- test/Function_Call_00.rob | 4 ++- test/Function_Return.rob | 3 +- test/Function_Sort.rob | 6 ++-- test/Function_w_Params_00.rob | 6 ++-- test/Function_w_Params_01.rob | 4 ++- test/Main_w_Condition.rob | 6 ++-- test/Operations.rob | 14 ++++++---- test/Operations_00.rob | 6 ++-- test/Print.rob | 2 ++ test/Sort_01.rob | 10 ++++--- test/Vector_Float.rob | 4 ++- test/Vector_Float_R.rob | 4 ++- test/Vector_Int.rob | 4 ++- test/Vector_Int_R.rob | 4 ++- test/Vector_MatrixValue.rob | 8 ++++-- test/Vector_Update.rob | 6 ++-- test/Vector_VectorValue.rob | 6 ++-- test/Vector_VectorValue_01.rob | 8 ++++-- test/bellmanford.rob | 4 +-- test/simple_array.rob | 19 +++++++------ test/sort.rob | 47 -------------------------------- test/vector-global.rob | 11 -------- 26 files changed, 101 insertions(+), 113 deletions(-) delete mode 100644 test/sort.rob delete mode 100644 test/vector-global.rob diff --git a/test/Compare_Local_Global_00.rob b/test/Compare_Local_Global_00.rob index 59b66bf..4500f4a 100644 --- a/test/Compare_Local_Global_00.rob +++ b/test/Compare_Local_Global_00.rob @@ -1,3 +1,5 @@ +extern void print(); + vector = {7, 8, 9, 10}; int16 fa(int16 i) { @@ -6,6 +8,6 @@ int16 fa(int16 i) { } int16 main(){ - print vector[1]; // print 8 - print fa(2); // print 3 + print (vector[1]); // print 8 + print (fa(2)); // print 3 } diff --git a/test/Compare_Local_Global_01.rob b/test/Compare_Local_Global_01.rob index b813263..7d75fb1 100644 --- a/test/Compare_Local_Global_01.rob +++ b/test/Compare_Local_Global_01.rob @@ -1,3 +1,5 @@ +extern void print(); + matriz = {{7, 8}, {9,10}}; int16 fa(int16 i, int16 j) { @@ -7,6 +9,6 @@ int16 fa(int16 i, int16 j) { int16 main() { - print matriz[1][1]; // print 10 - print fa(2,1); // print 6 + print (matriz[1][1]); // print 10 + print (fa(2,1)); // print 6 } diff --git a/test/Fibonacci.rob b/test/Fibonacci.rob index a0fd391..483766d 100644 --- a/test/Fibonacci.rob +++ b/test/Fibonacci.rob @@ -1,3 +1,5 @@ +extern void print(); + int16 fibonacci (int16 n){ if (n == 1) return 1; @@ -12,9 +14,9 @@ int16 fibonacci (int16 n){ } int16 main(){ - print fibonacci(1); - print fibonacci(2); - print fibonacci(3); - print fibonacci(4); - print fibonacci(5); + print (fibonacci(1)); + print (fibonacci(2)); + print (fibonacci(3)); + print (fibonacci(4)); + print (fibonacci(5)); } diff --git a/test/Function_Call.rob b/test/Function_Call.rob index cc99c70..24496c6 100644 --- a/test/Function_Call.rob +++ b/test/Function_Call.rob @@ -1,6 +1,8 @@ +extern void print(); + int16 b(){ t = 0; - print t; + print (t); return 0; } diff --git a/test/Function_Call_00.rob b/test/Function_Call_00.rob index c4101f0..1928b22 100644 --- a/test/Function_Call_00.rob +++ b/test/Function_Call_00.rob @@ -1,8 +1,10 @@ +extern void print(); + int16 function_name (int16 b){ if (b >= 3) print (b * 2); else{ - print 1; + print (1); } return b + 1; } diff --git a/test/Function_Return.rob b/test/Function_Return.rob index 015631a..c3aa56a 100644 --- a/test/Function_Return.rob +++ b/test/Function_Return.rob @@ -1,3 +1,4 @@ +extern void print(); void fa(int16 a) { a = a + 1; @@ -12,5 +13,5 @@ int16 fb(int16 b) { int16 main(){ fa(1); - print fb(2); + print (fb(2)); } diff --git a/test/Function_Sort.rob b/test/Function_Sort.rob index 0d1116b..388bc2e 100644 --- a/test/Function_Sort.rob +++ b/test/Function_Sort.rob @@ -1,3 +1,5 @@ +extern void print(); + int16 Sort(int16 n){ return 0; } @@ -9,14 +11,14 @@ int16 main(){ i = 0; while (i < 16){ c = a[i]; - print c; + print (c); i++; } Sort(16); i = 0; while (i < 16){ - print c; + print (c); i++; } } diff --git a/test/Function_w_Params_00.rob b/test/Function_w_Params_00.rob index 60c00a1..6555594 100644 --- a/test/Function_w_Params_00.rob +++ b/test/Function_w_Params_00.rob @@ -1,9 +1,11 @@ +extern void print(); + int16 func (bool a){ if (a == true){ - print 1; + print (1); } else { - print 2; + print (2); } return 0; } diff --git a/test/Function_w_Params_01.rob b/test/Function_w_Params_01.rob index 4af7fb1..afaf9d0 100644 --- a/test/Function_w_Params_01.rob +++ b/test/Function_w_Params_01.rob @@ -1,7 +1,9 @@ +extern void print(); + int16 quadrado(int16 a){ return a * a; } int16 main(){ - print quadrado(3); + print (quadrado(3)); } diff --git a/test/Main_w_Condition.rob b/test/Main_w_Condition.rob index 3dc7ba9..517c4d8 100644 --- a/test/Main_w_Condition.rob +++ b/test/Main_w_Condition.rob @@ -1,10 +1,12 @@ +extern void print(); + int16 main(){ a = true; if (a == true){ - print 1; + print (1); } else { - print 2; + print (2); } return 0; } diff --git a/test/Operations.rob b/test/Operations.rob index d22ca5b..bddfc4a 100644 --- a/test/Operations.rob +++ b/test/Operations.rob @@ -1,13 +1,15 @@ +extern void print(); + int16 main(){ a = 1; - print -1; - print -a; - print a-a; - print a-1; - print 1--a; + print (-1); + print (-a); + print (a-a); + print (a-1); + print (1--a); if (a > a-1){ - print 2; + print (2); } } diff --git a/test/Operations_00.rob b/test/Operations_00.rob index 134be21..2dda9a1 100644 --- a/test/Operations_00.rob +++ b/test/Operations_00.rob @@ -1,8 +1,10 @@ +extern void print(); + int16 main(){ i = 1.2; i++; i+=7; - print i; + print (i); i*=2; - print i; + print (i); } diff --git a/test/Print.rob b/test/Print.rob index 128ca4b..c1f60d7 100644 --- a/test/Print.rob +++ b/test/Print.rob @@ -1,3 +1,5 @@ +extern void print(); + int16 main(){ var = 3; print (var); diff --git a/test/Sort_01.rob b/test/Sort_01.rob index ea8f825..4a927c9 100644 --- a/test/Sort_01.rob +++ b/test/Sort_01.rob @@ -1,3 +1,5 @@ +extern void print(); + a = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; int16 sort (int16 n) { @@ -17,7 +19,7 @@ int16 sort (int16 n) s++; } t++; - //print t; + //print (t); } return 0; } @@ -26,15 +28,15 @@ int16 main() { i = 0; while (i < 16){ - print a[i]; + print (a[i]); i++; } - print "\n"; + print ("\n"); sort (16); i = 0; while(i < 16){ - print a[i]; + print (a[i]); i++; } } diff --git a/test/Vector_Float.rob b/test/Vector_Float.rob index f2050fa..03f6152 100644 --- a/test/Vector_Float.rob +++ b/test/Vector_Float.rob @@ -1,9 +1,11 @@ +extern void print(); + int16 main(){ vector = {3, 2, 5, 2, 1, 4.2, 5, 6, 8, 2, 1}; i = 0; while (i < 10){ - print vector[i]; + print (vector[i]); i = i + 1; } } diff --git a/test/Vector_Float_R.rob b/test/Vector_Float_R.rob index a6fb7c5..2f9165e 100644 --- a/test/Vector_Float_R.rob +++ b/test/Vector_Float_R.rob @@ -1,9 +1,11 @@ +extern void print(); + int16 main(){ vector = {3:3, 4.2}; i = 0; while (i < 4){ - print vector[i]; + print (vector[i]); i = i + 1; } } diff --git a/test/Vector_Int.rob b/test/Vector_Int.rob index 4524cc8..5eecf2f 100644 --- a/test/Vector_Int.rob +++ b/test/Vector_Int.rob @@ -1,9 +1,11 @@ +extern void print(); + int16 main(){ vector = {3, 2, 5, 2, 1, 4, 5, 6, 8, 2, 1}; i = 0; while (i < 10){ - print vector[i]; + print (vector[i]); i = i + 1; } } diff --git a/test/Vector_Int_R.rob b/test/Vector_Int_R.rob index 8376f0b..5017dc5 100644 --- a/test/Vector_Int_R.rob +++ b/test/Vector_Int_R.rob @@ -1,9 +1,11 @@ +extern void print(); + int16 main(){ vector = {3:3, 2:3, 1:3, 2}; i = 0; while (i < 10){ - print vector[i]; + print (vector[i]); i = i + 1; } } diff --git a/test/Vector_MatrixValue.rob b/test/Vector_MatrixValue.rob index 50a71a0..733b58e 100644 --- a/test/Vector_MatrixValue.rob +++ b/test/Vector_MatrixValue.rob @@ -1,3 +1,5 @@ +extern void print(); + int16 main(){ matriz = {{1, 2, 3}:2, {1:2,2}}; @@ -5,7 +7,7 @@ int16 main(){ c = matriz[2][2]; - print c; // print 2 - print b[c]; // print 7 - print b[matriz[0][2]]; // print 8 + print (c); // print 2 + print (b[c]); // print 7 + print (b[matriz[0][2]]); // print 8 } diff --git a/test/Vector_Update.rob b/test/Vector_Update.rob index 5cee824..1e1f5df 100644 --- a/test/Vector_Update.rob +++ b/test/Vector_Update.rob @@ -1,6 +1,8 @@ +extern void print(); + int16 main(){ a = {3, 3, 3, 3, 3}; - print a[2]; + print (a[2]); a[2] = 1; - print a[2]; + print (a[2]); } diff --git a/test/Vector_VectorValue.rob b/test/Vector_VectorValue.rob index 5bb7a51..ab05409 100644 --- a/test/Vector_VectorValue.rob +++ b/test/Vector_VectorValue.rob @@ -1,6 +1,8 @@ +extern void print(); + int16 main(){ a = {3, 2, 1}; - print a[1]; + print (a[1]); b = {2, 2, 4}; - print b[a[1]]; + print (b[a[1]]); } diff --git a/test/Vector_VectorValue_01.rob b/test/Vector_VectorValue_01.rob index 2bbd729..4ff135d 100644 --- a/test/Vector_VectorValue_01.rob +++ b/test/Vector_VectorValue_01.rob @@ -1,8 +1,10 @@ +extern void print(); + int16 main(){ a = 1; b = {1, 2, 3}; c = {5, 6, 7, 8}; - print b[a]; // print 2 - print c[b[1]]; // print 7 - print c[b[a+1]]; // print 8 + print (b[a]); // print 2 + print (c[b[1]]); // print 7 + print (c[b[a+1]]); // print 8 } diff --git a/test/bellmanford.rob b/test/bellmanford.rob index be3abb4..469f7fc 100644 --- a/test/bellmanford.rob +++ b/test/bellmanford.rob @@ -1,5 +1,5 @@ -extern print(char value); -INT_MAX = 9999; +extern void print(char value); +INT_MAX = 0; // edges (u,v,w) graph = diff --git a/test/simple_array.rob b/test/simple_array.rob index 8634635..9d331f6 100644 --- a/test/simple_array.rob +++ b/test/simple_array.rob @@ -1,11 +1,14 @@ +extern void print(); -a = {1, 2, 3, 4, 5, 6}; +int16 main () +{ + a = {1, 2, 3, 4, 5, 6}; -i = 0; -while (i < 16) { - c = a[i]; - print c; - i++; + i = 0; + while (i < 16) { + c = a[i]; + print (c); + i++; + } + print ("\n"); } -print "\n"; - diff --git a/test/sort.rob b/test/sort.rob deleted file mode 100644 index b433bdd..0000000 --- a/test/sort.rob +++ /dev/null @@ -1,47 +0,0 @@ -/* - * sample file for robcmp compiler - * this code sorts and print the vector a - */ - -a = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; - -long double sqrtl(long double n); -double sqrt(double n); -float sqrtf(float n); -long int teste(int n); - -int sort (int n) { - t = 0; - s = 0; - temp = 0; - while (t < n - 1) { - s = t + 1; - while (s < n) { - if ( a[t] > a[s] ) { - temp = a[t]; - a[t] = a[s]; - a[s] = temp; - } - s++; - } - t++; - //print t; - } - return 0; -} - -i = 0; -while (i < 16 and 1 == 1) { - print sqrtf(a[i]); - i++; -} - -print "\n"; - -sort(16); - -i = 0; -while (i < 16) { - print a[i]; - i++; -} diff --git a/test/vector-global.rob b/test/vector-global.rob deleted file mode 100644 index 2ef25b0..0000000 --- a/test/vector-global.rob +++ /dev/null @@ -1,11 +0,0 @@ - -const d = 1; -a = {1, 2, 3:3, 100:2, d}; - -int16 main() { - b = a[10]; - c = {5:10, 9.9, 10.7D, a[2], b}; - e = c[6] + b; - return e; -} - From ec41697d38a042c8fb18a3fec31f1f7589e3f6e3 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Mon, 17 Jul 2023 14:43:38 -0300 Subject: [PATCH 017/117] Partial implementation of register fields (missing load impl) and start of debuging using simavr. --- platformio/platform/boards/avr328p.json | 34 +++++++++ platformio/platform/boards/stm32f1.json | 48 +++++++++++++ platformio/platform/builder/main.py | 18 +++-- platformio/platform/platform.py | 25 +++++++ .../samples/avr328p-blink/platformio.ini | 3 +- platformio/samples/avr328p-blink/src/main.rob | 27 +++++-- .../vscode-syntax/robcmpsyntax-0.0.1.vsix | Bin 3016 -> 0 bytes .../vscode-syntax/robcmpsyntax-0.1.0.vsix | Bin 0 -> 3020 bytes src/BackLLVM.cpp | 8 +-- src/BinaryOp.cpp | 10 +-- src/Coercion.cpp | 4 +- src/Field.h | 22 ++++++ src/FlipOp.cpp | 2 +- src/Header.h | 17 +++++ src/Language.l | 1 + src/Language.y | 60 ++++++++++++++-- src/Load.h | 4 +- src/Pointer.cpp | 6 +- src/Pointer.h | 9 +++ src/RobSymbol.h | 2 + src/Scalar.cpp | 66 ++++++++++++++++-- src/Scalar.h | 2 + 22 files changed, 331 insertions(+), 37 deletions(-) create mode 100644 platformio/platform/boards/avr328p.json create mode 100644 platformio/platform/boards/stm32f1.json delete mode 100644 platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix create mode 100644 platformio/vscode-syntax/robcmpsyntax-0.1.0.vsix create mode 100644 src/Field.h diff --git a/platformio/platform/boards/avr328p.json b/platformio/platform/boards/avr328p.json new file mode 100644 index 0000000..53a9486 --- /dev/null +++ b/platformio/platform/boards/avr328p.json @@ -0,0 +1,34 @@ +{ + "build": { + "f_cpu": "16000000L", + "mcu": "atmega328p", + "variant": "standard" + }, + "debug": { + "target_mcu": "atmega328p", + "tools": { + "robcmp": { + "init_cmds": [ + "target remote $DEBUG_PORT", + "$INIT_BREAK", + "$LOAD_CMDS" + ], + "port": ":1234", + "server": { + "package": "toolchain-robcmp", + "executable": "bin/robcmp-simavr-debug" + } + } + } + }, + "name": "ATmega328P/PA", + "upload": { + "maximum_ram_size": 2048, + "maximum_size": 32768, + "protocol": "arduino", + "require_upload_port": true, + "speed": 115200 + }, + "url": "https://www.microchip.com/wwwproducts/en/ATmega328P", + "vendor": "Microchip" +} diff --git a/platformio/platform/boards/stm32f1.json b/platformio/platform/boards/stm32f1.json new file mode 100644 index 0000000..0c98976 --- /dev/null +++ b/platformio/platform/boards/stm32f1.json @@ -0,0 +1,48 @@ +{ + "build": { + "cpu": "cortex-m3", + "f_cpu": "72000000L", + "hwids": [ + [ + "0x1EAF", + "0x0003" + ], + [ + "0x1EAF", + "0x0004" + ] + ], + "mcu": "stm32f103c8t6", + "product_line": "STM32F103xB", + "variant": "PILL_F103XX" + }, + "debug": { + "default_tools": [ + "stlink" + ], + "jlink_device": "STM32F103C8", + "openocd_extra_args": [ + "-c", + "reset_config none" + ], + "openocd_target": "stm32f1x", + "svd_path": "STM32F103xx.svd" + }, + "frameworks": [ + ], + "name": "BluePill F103C8 (128k)", + "upload": { + "maximum_ram_size": 20480, + "maximum_size": 131072, + "protocol": "stlink", + "protocols": [ + "jlink", + "cmsis-dap", + "stlink", + "blackmagic", + "dfu" + ] + }, + "url": "http://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32f1-series/stm32f103/stm32f103c8.html", + "vendor": "Generic" +} diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 71202ad..89cd8a5 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -2,6 +2,7 @@ Build script for robcmp platform """ +import os import sys from os.path import join from SCons.Script import AlwaysBuild, Builder, Default, DefaultEnvironment, Glob @@ -10,11 +11,19 @@ platform = env.PioPlatform() ldscripts_folder = platform.get_package_dir("toolchain-robcmp") -mcu = env.GetProjectOption("custom_mcu") +os.environ['LD_LIBRARY_PATH'] = join(ldscripts_folder, "lib") + +# Needed by debug +env.Replace( + PROGNAME="firmware.elf" +) + +board = env.subst("$BOARD") +mcu = env.subst("$BOARD_MCU") if mcu == "stm32f1": ld = "ld.lld" ldflags = ["-nostdlib", "-entry=main", "-T" + ldscripts_folder + "/share/stm32f1.lld.ld", "-Bstatic"] -elif mcu == "avr328p": +elif mcu == "atmega328p": ld = "avr-ld" ldflags = ["--gc-sections", "-Tdata=0x800100"] else: @@ -33,7 +42,7 @@ suffix=".elf" ), Rob=Builder( - action = ' '.join(["robcmp", "-a", mcu, "-o", "$TARGET", "$SOURCE"]), + action = ' '.join(["robcmp", "-a", board, "-o", "$TARGET", "$SOURCE"]), suffix = '.o', src_suffix = '.rob', ) @@ -51,7 +60,6 @@ target_elf = env.Linker(join("$BUILD_DIR", "firmware"), target_objs) target_bin = env.ElfToBin(join("$BUILD_DIR", "firmware"), target_elf) - # UPLOAD upload_protocol = env.subst("$UPLOAD_PROTOCOL") upload_actions = [] @@ -67,7 +75,7 @@ UPLOADCMD='$UPLOADER $UPLOADERFLAGS "$SOURCE" $UPLOAD_PORT' ) - elif mcu == "avr328p": + elif mcu == "atmega328p": avrdude_bin = join(platform.get_package_dir("tool-avrdude"), "avrdude") avrdude_cfg = join(platform.get_package_dir("tool-avrdude"), "avrdude.conf") env.Replace( diff --git a/platformio/platform/platform.py b/platformio/platform/platform.py index 6f7aa47..296bedc 100644 --- a/platformio/platform/platform.py +++ b/platformio/platform/platform.py @@ -24,3 +24,28 @@ def configure_default_packages(self, variables, targets): self.packages[required_tool]['optional'] = False return super().configure_default_packages(variables, targets) + + def get_boards(self, id_=None): + result = super().get_boards(id_) + if not result: + return result + if id_: + return self._add_default_debug_tools(result) + else: + for key, value in result.items(): + result[key] = self._add_default_debug_tools(result[key]) + return result + + def _add_default_debug_tools(self, board): + debug = board.manifest.get("debug", {}) + if "tools" not in debug: + debug["tools"] = {} + + if debug.get("target_mcu", ""): + debug["tools"]["robcmp"]["server"]["arguments"] = [ + "-m", debug["target_mcu"], + "-hw", "led" + ] + + board.manifest["debug"] = debug + return board \ No newline at end of file diff --git a/platformio/samples/avr328p-blink/platformio.ini b/platformio/samples/avr328p-blink/platformio.ini index 5c83071..f7a59fb 100644 --- a/platformio/samples/avr328p-blink/platformio.ini +++ b/platformio/samples/avr328p-blink/platformio.ini @@ -1,5 +1,6 @@ [env:arduino-pro-micro] platform = robcmp -custom_mcu = avr328p +board = avr328p upload_protocol = serial +debug_tool = robcmp diff --git a/platformio/samples/avr328p-blink/src/main.rob b/platformio/samples/avr328p-blink/src/main.rob index 13e94e9..b2d49dd 100644 --- a/platformio/samples/avr328p-blink/src/main.rob +++ b/platformio/samples/avr328p-blink/src/main.rob @@ -3,9 +3,23 @@ * Blinks the led on PIN13 */ -register int8 PORTB at 0x25; // pins 8-13 -register int8 DDRB at 0x24; -register int8 PINB at 0x23; +register int8 portb at 0x25 { + bool pin8; + bool pin9; + bool pin10; + bool pin11; + bool pin12; + bool pin13; +} + +register int8 ddrb at 0x24 { + bool pin8; + bool pin9; + bool pin10; + bool pin11; + bool pin12; + bool pin13; +} void wait(); @@ -17,15 +31,16 @@ int16 main() { */ // set pin 13 as output - DDRB |= 0b00100000; + ddrb.pin13 = true; loop { // set bit 5 high - PORTB |= 0b00100000; + portb.pin13 = true; wait(); // set bit 5 low - PORTB &= ~(0b00100000); + portb.pin13 = false; wait(); } } + diff --git a/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix b/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix deleted file mode 100644 index 8ad9bf315b3755abf6136253ac423d1f70b972ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3016 zcmaKuc|25mAIHaxtu9i8>>4z7S1H$0+4nKXPKYt~!HgwYn;|<*hzYrjXzYxTExWkZ zgpiUgWQpw2GkUJleLc_pof=H3I>F zep)polR{m^iCloQfj+y~|4=Vt5fx|zaMdw zU^L4Awq&(@b8fX@Yce7}%rb&ft?A>r%u~yk#V_=G&Z|gL*G!J@eNFs55!FGdmYUp? zmA<1f8Y5(?IoSDUj<4eu4V@- z!BQUsD?P7uT{ugJsJT!fl!=zz!df}_M^z^UZ)BP}1XE^3A8XRoEVDG`{gA#U0AMvPW? zY$tRyf|QBh|D^J`K9Mz!i;kqZ3-scZjwLvYc>pokD)H`LfXDU@L7h2r#%~2)R z0sS0vG&Yd1*a*Gm@q=1gUnN#!?H7)D-N5Wfv9xibp^t>Yp5SP2bk%~{wfI7?gK?#~ ziuyfxS-T%Scby0KU`?6xw~B~&4?GQ~tGy2ZT2D?#8+^D@!k{RF0?et?D8W}}$8HQi z3~w8dg@GqoIwz2z&qX07v#%?|pLeO-to?%Rms}Ab zg*HmdYgLz6kk8o|c=R?4Q5g5zj*y6Sc%KCZ2S|Z$yK!ZwbC$UYb(&!N_!FRe2=8tQ zO!MT#_M9c{`qb+M`u~0+ExEJTp3fMQzv@Q`kXJuCTf)`W9pP<@fQ#87-5s0|-d?uo z!-jW8A>Gpr6p$E6#`H-Om0>MPY*U7S@)K8m6J_RhPO+1vB4c@=?S?HnEMy-xD4w#l zJW+G1<~I=If|sHbeF3W#8)e_%nM$xav;8?j##L#pG^BjC25=sTqhnEJlhL~SVD>`{ z<}8>V(}R$K3{dps1~I9)lQm4J#CHypxw-V9A`&-_3~6V6hLsi0fPq zhzTvlJ71rykMOE8j9o1ieQv0FEh?amRNbVzjyHCB-MRK|z3i##F4PagZPhQi={bQE z(!OULW_?Gb<%0>SahRgV+RIlFMTj&Cux1M_BStN&c@ZyB}Ln9GY zYZHab)OXhPEj|x%xWY#24W8#xk($~tina42jWdi~(b(GLPmJ-rLEMi`BO5AkbF+#U z<64U}Ow(96PPWEC%hD&{IqVH{iyf>*y?MnPnfWD_W7W{)ot0N=QzA=If8Cn}UN;Ns z;#*EuGecL4qaVYxX=s7t0(lUKqKk|Z%>|++{Xez5h4OPY6>_Oyv zXvpve0LT>oUOzQP|Do{<;3Yh4?Oezy`0l$muF<`jmo9uIFbXmkN6K}o+mzLP<&!2G z35%Dciix>cLEK#i%RFV*mAmzgCxA^npGd@P!d8g*66vc?P&R?YVY|7H2A?)|;3sQs zYqmb`Uj@8Oi2fw0Lt&2~D(rsr&s;F0k#qbl>3VfPxY{P{fI^F@TA!mLNm#LEnr&YG zvg~Y%kFFh;uW~-!Zg>sLOC@I&QwZ%4mBzX1>6xnAQhuVNk1aN~375T#thI+6sUIn5 zeO3NYj7=tOnJqh{t4;ILQVR|<1O%%Dcg?sFlJl2k=*uILaLeh?Gkd{m8|Hb<^cW^( zwhR0ObD#2ohvlI8+q=ZnFm4uwjdZU}o8c41T~^X!-H5O8!Q61{4l6%rM~FFP)-05H zdaq*&vbjFP!Z4*=P?T@|-LxEjLou>xf#hBPx#3K;zxJIV*^r-ohq~>Kw)KOfB)pKf z#L;d#f4AXx1Cnl7AYVx`2SI~X?Kexbr(8n>Q?SGnEw5TY@t69iW!!Jgjx_q1caDGS z@f3HvGC-7XiHvVR)%VWf<}^ck=)}xa`>Z0gTwGAB?f3$ZMz=Tiv9@?&r&Ll3QMf4L znWeLM^oa4@jx0VZP=2Y-irK1OHa}hottmXK9Bh(WmKOfl$OzSl-tJSjxS=abnLwSe zuE{9h%)~4H)NyTSkKV&1vyoTkjgC5>o@^17rMLd_>L*3R(xu?fRIA_c+;mjHG zz-$?q_u#p<-Ag{F1r--wWttVzRcaMeOe*wkPS_&0FBk<*^U^6NmfqFok&6p7z9aIW zx-xw!H9YG}f9ZSNq@{GK&Hd9YiB+&XRpgU9oQ>SdILl26Oftn6zLHjpDVI1M$Sx^* zaafY84D+m&qsF1VK6b>ebVa+6a!7d5OkY)0OkYGm&N`{j5ehMqtM~YW$$rVXquLw) zMoruA?D&-;@Q_#%@6goPsC7uN2)g{ih;;9XT{`Bz-Vk3Ii2GB&Wk*dCNRj8O7iw|X z7rF1h$Bpi4k{(!9DjOHW0`FTzT0Ti+Gu$Qy>LrYxKXD`1R{?TGb1k30@nA!8PYQL= zZ1pX}TAfFeR25(Uq@>&C&V!q=nq%~T37v3VFn5Zk$;A+7`FBw~`+homr(o+TH#2&# z3cTEDO^I8vh)pKQ*?3kA@LBNM@0xtr#deA6Q#!$4$%ob*5ilhJSsxy388$?B9 zi(?l~_HsDo482*>2=C}UN`20IuIG>YexA?g`91f2UBBylKPWRGNC*Jn<_0vGf3VH> zH@B!~2LQUc0RRyI0N@!&_9T!nM1smC5+)GuPQZA1lE}|&CyB3N0$~fA*A;`KMVXZ) z>Ndg~Y8r*Te=>DuMuw-7Mv{7dEpG_RC;*whDxq7u3B)eeFD{&%bXj|+WJZzK85~+} zA`J2XVf{+@WLNvOC#!QG=v&iNWRx=%)Y|mtiBr;J1n2lW7Vpl$ID@Ch*1trlrIOk~ zMp^0I`OlV;=m)LKqXuWEMg;8`uVW-H*Nt<1IfTODk5i{11-3HjWUb~tk{!eC~fz?fiD|6~x964~XSbJa(d4{Lth zqy%ih9dZLrnWTc&g`DOc5{Gb{5Pb;V>rpVZ^DxYlmW`ee?miW0LIsuU`)T>fc2djP z47x8VDz-z%Uhedd{-z&l9!HPO8CRb@^bKjsd|obT-+A>@>%g$0O7g-;&^@?1Zu?) zeh!Afi^D0{Ga+KLt8?(j)^+8M>_%X`i0E1T^o(szWk6Dpc3+rlGx`Pd3Qkh(QC+C) z@#D%VdaaNTe?~9mO{AgM%iv#f;|64VN|v}#>No9E1sfs*KuuXd9sT11N)+wMdv*01 z8tFrkVtZ>)t6}2Q%N$SD%OW)gT~5+;pqO0E#EgB14vN+hd zdq`Sar;gxAugOh47&R@->`Gli*st<3-KqKbXjzL-Gl4t<2h^lGR#VANqjN`&`3TC_ zN`56Oszya3iWJn~iJWqDBx#H_da#0Dy;{p=Q_BFwH&wR?3 z?Z~YwKgGTB2tatw@o*3t*%~Wm-NE2t>}%}L)joR35?N{o=IaYmSyAY$lGUoO7)xWy zFoMeFv1n)4$b3`fHY+!H6WbvgAy9e?_CnV_wx~mW=yXWB^i+ExrUd#lOs`yKhj|r)hm~1vF;tvrAm1* zJ+U_D%)RvX)qB4GZIPSR)X`b*Y+1Yd7V@mwx29Ibxf8qt+`T=a7l;HejCX*)J9)d; zu_PiP$4ZY#feGYH+npIU1w}RG${XIpS=t#2wMjttR6s@xfolz)c%u|IP=hL&pB5&b z@IToL6nO7%fZ==ii;F0zcTlhfY%Jt)upsxOrfD`&_l^nsJN9H=5xA(1>D83kH*pkU zFdwDcTSu{+`DP)b1@8f5y~D-gHUPi^ z_}BPug8~-Y|9<#&_<`-JzU~)%ST6Wl_kd&r*Y^y0cOx(7UNL3OE>jhdpyqGxe}4)4t63j|jD8=CbZV*P>AJ zG-C+R2jevOm=Xy(yJDhpj^9}iL*&B$s)P~@I=@`qJNevCRvY_3>#kT#b=wHrmX{K{ zVIK8#h*+A1T(ir7eJbH%n#{1tu%HvQ3(7H(e=ReS#FThqWOz-tr_FX;zo5D(?4|1+ z4&0th#$wB6lZV5J3@f*`Sa78(_Z4>>S1rEJE%crC-SpzXOofg{f5fN43l$p;PlH?v zH-ss7BBbr?OsZ_G3y^f+{AcCjEZ{g)V?{Vc=0XNf+0sK=#!K%n$W3|&U}=e}QO;Hc z13_J4Q4{E6@q*g?HSI8|^8pSUUo&4?*3+)Vs$M!P{ogbHa|0@{^8dX7NmmGD_drjQ zsz33(3K?(ycRzluM4F8gaR4S1W)TkeSS>eui;Gamj4I}79%u$8X!OnK5YEqzG+uJ- z7~AUhQ^9NZ7wb01CNz-hd*+ho5E0$HPzQLg3)R%ehxAJu?V)cY{&$a??ldJ#7Cp0A zsgzpnj8(ZYVtchcUxowtpu&97;REuH9PKn2p)_k4ZkJV=9djFvCN+}RdJUay&MJcv zITM!<0=h2_98xK|_;F~R&(|)m@sQ5%=EgEe+%v1=`kWQ>G|3YgXInJx?;jhH_`^{n z*>PVXSTvV11)ghVYFyf{VDNq*&!L33#aNvu4)0r2WmQk5Pqi;=N#rMk&K&=T$aJI@_{Ld5hCqpLlac zCjG|zFif(NQr#l{#H+3T=E#MLMY9snkkY(^C0rS536VeHmezaGLJ@tU-uKu64+gfq zHh}iKky)Vdn06_62%2_i=daA;%km9+$Q@rC-`3Wc{{S4 zYQnkgRyKBh;Q#*%+#v@&a(nj8y+8aD{;cuyx%yq>BkQaGaLVoo>>zJ947X3MohXQW z#lqvaMf}?t_Os-+#10#`DY_E{k(nI3CBHLux573B knct?tP83Aia_wHlzp(*j#=)u^0Kmz*Dp||{?b*KjFa2}>2mk;8 literal 0 HcmV?d00001 diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 7f4a0ed..b3f79c5 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -99,11 +99,9 @@ void print_llvm_ir(const char *target, char opt_level) { default : ol = OptimizationLevel::Oz; break; } - if (opt_level != '0') { - ModulePassManager modulePassManager = - passBuilder.buildPerModuleDefaultPipeline(ol); - modulePassManager.run(*mainmodule, moduleAnalysisManager); - } + ModulePassManager modulePassManager = + passBuilder.buildPerModuleDefaultPipeline(ol); + modulePassManager.run(*mainmodule, moduleAnalysisManager); if (build_outputfilename) { std::error_code ec; diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index c70a0e5..39997ad 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -42,7 +42,7 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, }*/ if (opint == Instruction::Shl || opint == Instruction::LShr) { - // sext the left operator if we know the rside bitwidth + // zext the left operator if we know the rside bitwidth Constant *c = NULL; if (rhsn->isConstExpr(block, allocblock)) { Value *v = rhsn->generate(NULL, block, allocblock); @@ -52,11 +52,11 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, int64_t v = c->getUniqueInteger().getZExtValue(); if (Ty1->getIntegerBitWidth() < v) { if (v >= 8 && v <= 15) - lhs = new SExtInst(lhs, Type::getInt16Ty(global_context), "sext16", block); + lhs = new ZExtInst(lhs, Type::getInt16Ty(global_context), "zext16", block); else if (v >= 16 && v <= 31) - lhs = new SExtInst(lhs, Type::getInt32Ty(global_context), "sext32", block); + lhs = new ZExtInst(lhs, Type::getInt32Ty(global_context), "zext32", block); else if (v >= 32 && v <= 63) - lhs = new SExtInst(lhs, Type::getInt64Ty(global_context), "sext64", block); + lhs = new ZExtInst(lhs, Type::getInt64Ty(global_context), "zext64", block); else yyerrorcpp("Number of shift bits exceeds the max int precision for left side.", this); Ty1 = lhs->getType(); @@ -109,7 +109,7 @@ Type *BinaryOp::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { Type *rty = rhsn->getLLVMResultType(block, allocblock); if (lty->isIntegerTy() && rty->isIntegerTy()) { if (op == TOK_LSHIFT || op == TOK_RSHIFT) { - // sext the left operator if we know the rside bitwidth + // zext the left operator if we know the rside bitwidth Constant *c = NULL; if (rhsn->isConstExpr(block, allocblock)) { Value *v = rhsn->generate(NULL, block, allocblock); diff --git a/src/Coercion.cpp b/src/Coercion.cpp index 7c645ab..9a28497 100644 --- a/src/Coercion.cpp +++ b/src/Coercion.cpp @@ -67,9 +67,9 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati } else if (wty < wdestty) { if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getSExt(c, destty); + r = ConstantExpr::getZExt(c, destty); else - r = new SExtInst(v, destty, "sext", block); + r = new ZExtInst(v, destty, "zext", block); } } else if (!destty->isPointerTy()) { diff --git a/src/Field.h b/src/Field.h new file mode 100644 index 0000000..4de3ff4 --- /dev/null +++ b/src/Field.h @@ -0,0 +1,22 @@ + +#pragma once + +#include "Header.h" + +typedef struct { + LanguageDataType fieldDataType; + char *fieldName; + unsigned startBit; + unsigned bitWidth; +} Field; + +class Structure { +public: + int nextBit; + map fields; +}; + +class ComplexIdentifier { +public: + vector names; +}; diff --git a/src/FlipOp.cpp b/src/FlipOp.cpp index 6651185..704ebb4 100644 --- a/src/FlipOp.cpp +++ b/src/FlipOp.cpp @@ -12,7 +12,7 @@ Value *FlipOp::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc if (exprv == NULL) return NULL; if (Constant *c = dyn_cast(exprv)) - return ConstantExpr::getNeg(c); + return ConstantExpr::getNot(c); else return BinaryOperator::Create(Instruction::Xor, exprv, Constant::getAllOnesValue(exprv->getType()), "neg", block); diff --git a/src/Header.h b/src/Header.h index d68056d..a1c9f59 100644 --- a/src/Header.h +++ b/src/Header.h @@ -43,6 +43,9 @@ static const char *LanguageDataTypeNames[__ldt_last] = {"void", "boolean", "char "unsigned int32", "unsigned int64", "float", "double", "long double"}; +static const unsigned LanguageDataTypeBitWidth[__ldt_last] = {0, 1, 8, 8, + 16, 32, 64, 8, 16, 32, 64, 32, 64, 128}; + enum DataQualifier {qnone, qconst, qvolatile}; extern Type* robTollvmDataType[]; @@ -69,6 +72,8 @@ typedef struct { unsigned count; } MatrixElement; +#include "Field.h" + #include "bison.hpp" extern int yyerror(const char *s); @@ -153,6 +158,18 @@ static RobSymbol *search_symbol(const string& ident, BasicBlock *firstb = NULL, return NULL; } +template +string string_format(const char *format, Args ... args) { + int size_s = std::snprintf(nullptr, 0, format, args ...) + 1; + if( size_s <= 0 ) { + return ""; + } + auto size = static_cast(size_s); + unique_ptr buf(new char[ size ]); + snprintf(buf.get(), size, format, args ...); + return string(buf.get(), buf.get() + size - 1); +} + #include "Node.h" #include "ArrayElements.h" #include "AttachInterrupt.h" diff --git a/src/Language.l b/src/Language.l index cc633ad..9ff7304 100644 --- a/src/Language.l +++ b/src/Language.l @@ -102,6 +102,7 @@ extern int yycolnew; ">>" { return TOK_RSHIFT; } ":" { return ':'; } +"." { return '.'; } "," { return ','; } ";" { return ';'; } diff --git a/src/Language.y b/src/Language.y index 30ed9e4..adc6add 100644 --- a/src/Language.y +++ b/src/Language.y @@ -5,9 +5,6 @@ #include "Header.h" #include "2018arm/nodeh_ext.h" -class Node; -class Stmts; - Node* getNodeForIntConst(int64_t i); std::vector vectorglobal; @@ -48,6 +45,9 @@ extern int errorsfound; FunctionParams *fps; ParamsCall *pc; LanguageDataType dt; + Field field; + Structure *structure; + ComplexIdentifier *complexIdent; } %type term term2 expr factor stmt gstmt condblock elseblock whileblock logicexpr @@ -70,6 +70,9 @@ extern int errorsfound; %type TOK_STRING %type TOK_STEPPER %type
type_f registertype +%type struct_field +%type struct_fields +%type complex_identifier %precedence IFX %precedence TOK_ELSE @@ -97,11 +100,12 @@ gstmts : gstmts gstmt { $1->append($2); } ; gstmt : TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($1, $3, qnone); } + | complex_identifier '=' expr ';' { $$ = new Scalar($1, $3, qnone); } | TOK_CONST TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qconst); } | TOK_VOLATILE TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qvolatile); } | TOK_IDENTIFIER '=' relements ';' { $$ = new Array($1, $3); } | TOK_IDENTIFIER '=' rmatrix ';' { $$ = new Matrix($1, $3);} - | registerstmt ';' { $$ = $1; } + | registerstmt { $$ = $1; } | fe { $$ = $1; } | error ';' { /* error recovery until next ';' */ $$ = new Int8(0); // evita falha de segmentacao @@ -291,7 +295,8 @@ term2 : term2 '&' factor { $$ = new BinaryOp($1, '&', $3); } factor : '(' expr ')' { $$ = $2; } | TOK_IDENTIFIER { $$ = new Load($1); } | TOK_IDENTIFIER '[' expr ']' { $$ = new LoadArray($1, $3);} - | TOK_IDENTIFIER '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6);} + | TOK_IDENTIFIER '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6);} + | complex_identifier { $$ = new Load($1); } | TOK_TRUE { $$ = new Int1(1); } | TOK_FALSE { $$ = new Int1(0); } | TOK_INTEGER { $$ = getNodeForIntConst($1); } @@ -303,6 +308,18 @@ factor : '(' expr ')' { $$ = $2; } | unary { $$ = $1; } ; +complex_identifier : complex_identifier '.' TOK_IDENTIFIER { + $1->names.push_back($3); + $$ = $1; + } + | TOK_IDENTIFIER '.' TOK_IDENTIFIER { + ComplexIdentifier *complexIdent = new ComplexIdentifier(); + complexIdent->names.push_back($1); + complexIdent->names.push_back($3); + $$ = complexIdent; + } + ; + unary : '-' factor { $$ = new BinaryOp($2, '*', getNodeForIntConst(-1)); } | '~' factor { $$ = new FlipOp($2); } | cast { $$ = $1; } @@ -314,9 +331,12 @@ cast : '(' type_f ')' factor { $$ = new Cast($2, $4); } printstmt : TOK_PRINT TOK_STRING { $$ = new Print(new String($2)); } | TOK_PRINT expr { $$ = new Print($2); } -registerstmt : TOK_REGISTER registertype TOK_IDENTIFIER TOK_AT expr { +registerstmt : TOK_REGISTER registertype TOK_IDENTIFIER TOK_AT expr ';' { $$ = new Pointer($3, $2, $5, true); } + | TOK_REGISTER registertype TOK_IDENTIFIER TOK_AT expr '{' struct_fields '}' { + $$ = new Pointer($3, $2, $5, $7, true); + } ; registertype : TOK_FINT8 { $$ = tint8; } @@ -324,6 +344,34 @@ registertype : TOK_FINT8 { $$ = tint8; } | TOK_FINT32 { $$ = tint32; } | TOK_FINT64 { $$ = tint64; } ; + +struct_fields : struct_fields struct_field { + $2.startBit = $1->nextBit; + $1->fields[$2.fieldName] = $2; + $1->nextBit += $2.bitWidth; + $$ = $1; + } + | struct_field { + Structure *s = new Structure(); + $1.startBit = 0; + s->fields[$1.fieldName] = $1; + s->nextBit = $1.bitWidth; + $$ = s; + } + ; + +struct_field : type_f TOK_IDENTIFIER ';' { + $$.fieldDataType = $1; + $$.fieldName = $2; + $$.bitWidth = LanguageDataTypeBitWidth[$1]; + } + | type_f TOK_IDENTIFIER ':' TOK_INTEGER ';' { + $$.fieldDataType = $1; + $$.fieldName = $2; + $$.bitWidth = (unsigned)$4; + } + ; + %% extern int yylineno; diff --git a/src/Load.h b/src/Load.h index 1ff2e8f..b51c4b0 100644 --- a/src/Load.h +++ b/src/Load.h @@ -5,8 +5,10 @@ class Load: public Node { private: string ident; + ComplexIdentifier *complexIdent; public: - Load(const char *i): ident(i) {} + Load(const string i): ident(i), complexIdent(nullptr) {} + Load(ComplexIdentifier *ci): complexIdent(ci) {} virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; diff --git a/src/Pointer.cpp b/src/Pointer.cpp index 2b79559..a68c7cc 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -25,7 +25,11 @@ Value *Pointer::generate(Function *func, BasicBlock *block, BasicBlock *allocblo Type *ty = robTollvmDataType[type]; DataQualifier vol = isVolatile ? qvolatile : qnone; - tabelasym[allocblock][name] = new RobSymbol(addrp, vol, ty); + + RobSymbol *rs = new RobSymbol(addrp, vol, ty); + rs->structure = structure; + tabelasym[allocblock][name] = rs; + return addrp; } diff --git a/src/Pointer.h b/src/Pointer.h index e00c7e1..bebfc27 100644 --- a/src/Pointer.h +++ b/src/Pointer.h @@ -9,9 +9,18 @@ class Pointer: public Node { Node *address; string name; bool isVolatile; + Structure *structure; public: Pointer(const char *name, LanguageDataType type, Node *address, bool isVolatile = false): name(name), type(type), address(address), isVolatile(isVolatile) {} + Pointer(const char *name, LanguageDataType type, Node *address, Structure *structure, + bool isVolatile = false): + name(name), type(type), address(address), structure(structure), isVolatile(isVolatile) { + if (structure->nextBit > LanguageDataTypeBitWidth[type]) { + const char *emsg = "The sum of field sizes for %s (%d) is larger than its type size (%d)."; + yyerrorcpp(string_format(emsg, name, structure->nextBit, LanguageDataTypeBitWidth[type]), this); + } + } virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; virtual void accept(Visitor &v) override; }; diff --git a/src/RobSymbol.h b/src/RobSymbol.h index be9beef..d273889 100644 --- a/src/RobSymbol.h +++ b/src/RobSymbol.h @@ -8,10 +8,12 @@ class RobSymbol: public SourceLocation { DataQualifier qualifier; unsigned int matrixLines; unsigned int matrixCols; + Structure *structure; RobSymbol(Value *v, DataQualifier qualifier = qnone, Type *pointerType = NULL): value(v), qualifier(qualifier), pointerType(pointerType) { matrixLines = matrixCols = 0; + structure = nullptr; } }; diff --git a/src/Scalar.cpp b/src/Scalar.cpp index d32cad2..552ce68 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -1,14 +1,37 @@ #include "Header.h" Scalar::Scalar(const char *n, Node *e, DataQualifier qualifier) : - name(n), expr(e), qualifier(qualifier) { + name(n), expr(e), qualifier(qualifier), complexIdent(nullptr) { + node_children.reserve(1); + node_children.push_back(e); +} + +Scalar::Scalar(ComplexIdentifier *ci, Node *e, DataQualifier qualifier) : + complexIdent(ci), expr(e), qualifier(qualifier) { node_children.reserve(1); node_children.push_back(e); } Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - auto symbol = search_symbol(name, allocblock, block); + string id = complexIdent ? complexIdent->names[0] : name; + auto symbol = search_symbol(id, allocblock, block); + Field field; + + if (complexIdent) { + string idfield = complexIdent->names[1]; + auto fieldit = symbol->structure->fields.find(idfield); + + if (symbol == NULL) { + yyerrorcpp("Symbol " + id + " must be defined first.", this); + return NULL; + } else if (fieldit == symbol->structure->fields.end()) { + yyerrorcpp("Symbol " + id + "." + idfield + " not declared.", this); + return NULL; + } else { + field = fieldit->second; + } + } // variable doesn't exists if (symbol == NULL) { @@ -38,17 +61,52 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc return ret; } else { + // variable already exists if (symbol->qualifier == qconst) { yyerrorcpp("Constant '" + name + "' can not be changed.", this); return NULL; } - // variable already exists + Type *leftvty = symbol->value->getType(); qualifier = symbol->qualifier; if (symbol->pointerType) leftvty = symbol->pointerType; Value *exprv = expr->generate(func, block, allocblock); - auto nvalue = Coercion::Convert(exprv, leftvty, block, expr); + Value *nvalue; + + if (complexIdent) { + /* this code does: + * symbol->value &= ~(0x11... << field.startBit) + * symbol->value |= (exprv << field.startBit) + */ + + // Coerce the left side to the field size + exprv = Coercion::Convert(exprv, robTollvmDataType[field.fieldDataType], block, expr); + // Expand to the left side size + exprv = Coercion::Convert(exprv, leftvty, block, expr); + + // Prepare the mask + Constant *allone = Constant::getAllOnesValue(Type::getIntNTy(global_context, field.bitWidth)); + Constant *ones = ConstantExpr::getZExt(allone, leftvty); + + if (field.startBit > 0) { + Constant *shiftl = ConstantInt::get(leftvty, field.startBit); + ones = ConstantExpr::getShl(ones, shiftl); + exprv = BinaryOperator::CreateShl(exprv, shiftl, "shift", block); + } + Constant *mask = ConstantExpr::getNot(ones); + + // Load pointer value + Load ld(id); + Value *leftv = ld.generate(func, block, allocblock); + + // Apply mask, than or + Value *vaftermask = BinaryOperator::CreateAnd(leftv, mask, "mask", block); + nvalue = BinaryOperator::CreateOr(vaftermask, exprv, "setbits", block); + } else { + nvalue = Coercion::Convert(exprv, leftvty, block, expr); + } + return new StoreInst(nvalue, symbol->value, qualifier == qvolatile, block); } } diff --git a/src/Scalar.h b/src/Scalar.h index 641820b..674e9ec 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -8,8 +8,10 @@ class Scalar: public Node { string name; Node *expr; DataQualifier qualifier; + ComplexIdentifier *complexIdent; public: Scalar(const char *n, Node *e, DataQualifier qualifier = qnone); + Scalar(ComplexIdentifier *ci, Node *e, DataQualifier qualifier = qnone); virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; From 9f013981fbdbf839846eec70132efc9d872a2194 Mon Sep 17 00:00:00 2001 From: Thiago Borges Date: Wed, 12 Jul 2023 21:37:46 -0300 Subject: [PATCH 018/117] Fix linux packaging of platformio. --- platformio/platform/builder/main.py | 2 +- platformio/toolchain-robcmp/Makefile | 2 +- platformio/toolchain-robcmp/libllvmpath | 1 - platformio/toolchain-robcmp/libllvmpath.sh | 6 ++++++ 4 files changed, 8 insertions(+), 3 deletions(-) delete mode 100755 platformio/toolchain-robcmp/libllvmpath create mode 100755 platformio/toolchain-robcmp/libllvmpath.sh diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 89cd8a5..4827a75 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -112,4 +112,4 @@ upload = env.Alias(["upload"], target_bin, upload_actions) AlwaysBuild(upload) -Default(target_bin) \ No newline at end of file +Default(target_bin) diff --git a/platformio/toolchain-robcmp/Makefile b/platformio/toolchain-robcmp/Makefile index 7cecedf..eadbb65 100644 --- a/platformio/toolchain-robcmp/Makefile +++ b/platformio/toolchain-robcmp/Makefile @@ -36,7 +36,7 @@ endif ifeq ($(uname_S), Linux) suffix=linux_x86_64 SED=sed - LIBS=$(shell ./libllvmpath ${LLVM_LD}) + LIBS=$(shell ./libllvmpath.sh ${LLVM_LD}) endif version=$(shell cat version) diff --git a/platformio/toolchain-robcmp/libllvmpath b/platformio/toolchain-robcmp/libllvmpath deleted file mode 100755 index 32bc7db..0000000 --- a/platformio/toolchain-robcmp/libllvmpath +++ /dev/null @@ -1 +0,0 @@ -ldd $1|grep libLLVM|sed "s/.*=> \([^( ]*\).*/\1/" diff --git a/platformio/toolchain-robcmp/libllvmpath.sh b/platformio/toolchain-robcmp/libllvmpath.sh new file mode 100755 index 0000000..ee1721c --- /dev/null +++ b/platformio/toolchain-robcmp/libllvmpath.sh @@ -0,0 +1,6 @@ +#find libLLVM and some of its dependencies +libLLVM=`ldd $1|grep libLLVM|sed "s/.*=> \([^( ]*\).*/\1/"` +libz3=`ldd $libLLVM|grep libz3|sed "s/.*=> \([^( ]*\).*/\1/"` +libedit=`ldd $libLLVM|grep libedit|sed "s/.*=> \([^( ]*\).*/\1/"` +libbsd=`ldd $libLLVM|grep libbsd|sed "s/.*=> \([^( ]*\).*/\1/"` +echo $libLLVM $libz3 $libedit $libbsd From 4df957a790ae75eefd5ce5e36c556613c84f6e46 Mon Sep 17 00:00:00 2001 From: Thiago Borges Date: Tue, 18 Jul 2023 02:13:30 -0300 Subject: [PATCH 019/117] Add dwarf debug information --- Makefile | 4 +- hack/avr/Makefile | 4 +- platformio/platform/builder/main.py | 12 +++- platformio/platform/platform.py | 1 + .../samples/avr328p-blink/platformio.ini | 8 ++- platformio/samples/avr328p-blink/src/main.rob | 2 - src/Array.cpp | 2 +- src/ArrayElements.cpp | 34 +++++----- src/ArrayElements.h | 2 +- src/BackLLVM.cpp | 11 ++-- src/BinaryOp.cpp | 41 +++++++----- src/BinaryOp.h | 2 +- src/Cast.cpp | 4 +- src/Cast.h | 2 +- src/CmpOp.cpp | 7 +- src/DebugInfo.cpp | 32 +++++++++ src/Double.h | 4 +- src/FlipOp.h | 4 +- src/Float.h | 4 +- src/Float128.h | 4 +- src/FunctionCall.cpp | 20 +++--- src/FunctionCall.h | 2 +- src/FunctionDecl.cpp | 57 +++++++++++++--- src/FunctionDecl.h | 1 + src/FunctionDeclExtern.cpp | 4 +- src/FunctionParams.cpp | 4 +- src/FunctionParams.h | 2 +- src/Header.h | 65 +++++++++++++++---- src/Int1.h | 4 +- src/Int16.h | 4 +- src/Int32.h | 4 +- src/Int64.h | 4 +- src/Int8.h | 4 +- src/Language.l | 14 +++- src/Language.y | 46 ++++++++----- src/Load.cpp | 28 ++++---- src/Load.h | 2 +- src/LoadArray.cpp | 18 ++--- src/LoadArray.h | 2 +- src/Loop.cpp | 14 +++- src/Matrix.cpp | 2 +- src/MatrixElements.cpp | 34 +++++----- src/MatrixElements.h | 2 +- src/Node.h | 4 +- src/Program.cpp | 21 ++++++ src/RobSymbol.h | 2 + src/Scalar.cpp | 28 ++++++-- src/SourceLocation.h | 5 ++ src/While.cpp | 26 +++++--- src/main.cpp | 9 ++- 50 files changed, 415 insertions(+), 201 deletions(-) create mode 100644 src/DebugInfo.cpp diff --git a/Makefile b/Makefile index 826f4da..bb89aec 100644 --- a/Makefile +++ b/Makefile @@ -27,8 +27,8 @@ COMPILER_NAME=$(shell basename "${PWD}") SRC = src BIN = . -FLAGS=-O3 -march=native -flto -#DFLAGS=-ggdb -O0 +#FLAGS=-O3 -march=native -flto +DFLAGS=-ggdb -O0 -std=c++17 CPPS=$(patsubst src/%.cpp,src/out/%.o,$(wildcard ${SRC}/*.cpp)) YACS=$(patsubst src/%.y,src/out/%_y.o,$(wildcard ${SRC}/*.y)) diff --git a/hack/avr/Makefile b/hack/avr/Makefile index a5ae5a6..67b6c56 100644 --- a/hack/avr/Makefile +++ b/hack/avr/Makefile @@ -18,7 +18,7 @@ all: ${ROBCMP} ${ALL} ${CC} ${CCPLAT} -Oz -S -emit-llvm ${INCLUDES} $< -o $@ %.c.o: %.c - ${CC} ${CCPLAT} -Oz -c ${INCLUDES} $< -o $@ + ${CC} ${CCPLAT} -ggdb -O0 -c ${INCLUDES} $< -o $@ @@ -36,7 +36,7 @@ all: ${ROBCMP} ${ALL} %.elf : %.o @#${CC} -v ${CCPLAT} ${AVRLIB} $< -o $@ @#avr-gcc -v -mmcu=atmega328p $< -o $@ - avr-ld -o $@ --gc-sections -Tdata=0x800100 $< + avr-ld -o $@ -Tdata=0x800100 $< %.hex : %.elf avr-objcopy -Oihex $< $@ diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 4827a75..4d9ede8 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -25,11 +25,19 @@ ldflags = ["-nostdlib", "-entry=main", "-T" + ldscripts_folder + "/share/stm32f1.lld.ld", "-Bstatic"] elif mcu == "atmega328p": ld = "avr-ld" - ldflags = ["--gc-sections", "-Tdata=0x800100"] + ldflags = ["-Tdata=0x800100"] else: sys.stderr.write("The requested mcu is not supported.\n") env.Exit(1) +build_type = env.subst("$BUILD_TYPE") +robcmp_args = ["robcmp", "-a", board, "-o", "$TARGET"] +if build_type == "debug": + robcmp_args.append("-g") +elif build_type == "release": + robcmp_args.append("-Oz") + ldflags.append("--gc-sections") +robcmp_args.append("$SOURCE") env.Append( BUILDERS=dict( @@ -42,7 +50,7 @@ suffix=".elf" ), Rob=Builder( - action = ' '.join(["robcmp", "-a", board, "-o", "$TARGET", "$SOURCE"]), + action = ' '.join(robcmp_args), suffix = '.o', src_suffix = '.rob', ) diff --git a/platformio/platform/platform.py b/platformio/platform/platform.py index 296bedc..1c8ce51 100644 --- a/platformio/platform/platform.py +++ b/platformio/platform/platform.py @@ -43,6 +43,7 @@ def _add_default_debug_tools(self, board): if debug.get("target_mcu", ""): debug["tools"]["robcmp"]["server"]["arguments"] = [ + "-f", "$PROGNAME", "-m", debug["target_mcu"], "-hw", "led" ] diff --git a/platformio/samples/avr328p-blink/platformio.ini b/platformio/samples/avr328p-blink/platformio.ini index f7a59fb..b75fd8c 100644 --- a/platformio/samples/avr328p-blink/platformio.ini +++ b/platformio/samples/avr328p-blink/platformio.ini @@ -1,6 +1,12 @@ -[env:arduino-pro-micro] +[env] platform = robcmp board = avr328p upload_protocol = serial + +[env:release] +build_type = release + +[env:debug] +build_type = debug debug_tool = robcmp diff --git a/platformio/samples/avr328p-blink/src/main.rob b/platformio/samples/avr328p-blink/src/main.rob index b2d49dd..e72c794 100644 --- a/platformio/samples/avr328p-blink/src/main.rob +++ b/platformio/samples/avr328p-blink/src/main.rob @@ -42,5 +42,3 @@ int16 main() { wait(); } } - - diff --git a/src/Array.cpp b/src/Array.cpp index ce21b53..4108f85 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -6,7 +6,7 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock Value *array_size = ConstantInt::get(Type::getInt8Ty(global_context), size); //Get Type of elements in Array of Elements, and define as I. - Type* I = elements->getArrayType(block, allocblock); + Type* I = robTollvmDataType[elements->getArrayType(block, allocblock)]; //Declare array type. ArrayType* arrayType = ArrayType::get(I, size); diff --git a/src/ArrayElements.cpp b/src/ArrayElements.cpp index 7f3e469..b3e29a8 100644 --- a/src/ArrayElements.cpp +++ b/src/ArrayElements.cpp @@ -17,38 +17,38 @@ unsigned ArrayElements::getStructSize() const { return elements.size(); } -Type *ArrayElements::getArrayType(BasicBlock *block, BasicBlock *allocblock) const { +LanguageDataType ArrayElements::getArrayType(BasicBlock *block, BasicBlock *allocblock) const { unsigned intsize = 0; unsigned floatsize = 0; for(auto& i : elements) { - Type *ty = i.value->getLLVMResultType(block, allocblock); - if (ty->isIntegerTy() && intsize < ty->getIntegerBitWidth()) - intsize = ty->getIntegerBitWidth(); + LanguageDataType dt = i.value->getResultType(block, allocblock); + if (isIntegerDataType(dt) && intsize < LanguageDataTypeBitWidth[dt]) + intsize = LanguageDataTypeBitWidth[dt]; - if (floatsize < 32 && ty->isFloatTy()) + if (floatsize < 32 && dt == tfloat) floatsize = 32; - else if (floatsize < 64 && ty->isDoubleTy()) + else if (floatsize < 64 && dt == tdouble) floatsize = 64; - else if (floatsize < 128 && ty->isFP128Ty()) + else if (floatsize < 128 && dt == tldouble) floatsize = 128; } if (intsize == 0 && floatsize == 0) { - yyerrorcpp("FIXME: vector of non-consts.", NULL); - return NULL; + yyerrorcpp("FIXME: vector of non-consts/non-numbers.", NULL); + return tvoid; } if (floatsize == 0) { switch (intsize) { - case 1: return Type::getInt1Ty(global_context); - case 8: return Type::getInt8Ty(global_context); - case 16: return Type::getInt16Ty(global_context); - case 32: return Type::getInt32Ty(global_context); - default: return Type::getInt64Ty(global_context); + case 1: return tbool; + case 8: return tint8; + case 16: return tint16; + case 32: return tint32; + default: return tint64; } } else { switch (floatsize) { - case 32: return Type::getFloatTy(global_context); - case 64: return Type::getDoubleTy(global_context); - default: return Type::getFP128Ty(global_context); + case 32: return tfloat; + case 64: return tdouble; + default: return tldouble; } } } diff --git a/src/ArrayElements.h b/src/ArrayElements.h index c11f4b2..6f44750 100644 --- a/src/ArrayElements.h +++ b/src/ArrayElements.h @@ -14,7 +14,7 @@ class ArrayElements { unsigned getStructSize () const; unsigned getElementCount (int position) const; Node *getStructElement (int position) const; - Type *getArrayType(BasicBlock *block, BasicBlock *allocblock) const; + LanguageDataType getArrayType(BasicBlock *block, BasicBlock *allocblock) const; }; #endif diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index b3f79c5..8b2590d 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -24,10 +25,12 @@ using namespace llvm; // Program main module -Module *mainmodule; -BasicBlock *global_alloc; +Module* mainmodule; +BasicBlock* global_alloc; LLVMContext global_context; -static IRBuilder<> builder(global_context); +std::unique_ptr> Builder; +std::unique_ptr DBuilder; +struct DebugInfo RobDbgInfo; // symbol table std::map> tabelasym; @@ -69,7 +72,7 @@ void print_llvm_ir(const char *target, char opt_level) { } TargetOptions opt; - auto RM = optional(); + auto RM = Optional(); auto targetMachine = Target->createTargetMachine(ai.triple, ai.cpu, ai.features, opt, RM); mainmodule->setDataLayout(targetMachine->createDataLayout()); diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index 39997ad..5fc6251 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -15,7 +15,9 @@ Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, Value *lhs = lhsn->generate(func, block, allocblock); Value *rhs = rhsn->generate(func, block, allocblock); - return BinaryOperator::Create(op, lhs, rhs, "logicop", block); + + Builder->SetInsertPoint(block); + return Builder->CreateBinOp(op, lhs, rhs, "logicop"); } Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, @@ -31,6 +33,8 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, enum Instruction::BinaryOps llvmop; + Builder->SetInsertPoint(block); + if (Ty1->isIntegerTy() && Ty2->isIntegerTy()) { /*fallback SDiv disabled if (opint == Instruction::SDiv) { @@ -52,11 +56,11 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, int64_t v = c->getUniqueInteger().getZExtValue(); if (Ty1->getIntegerBitWidth() < v) { if (v >= 8 && v <= 15) - lhs = new ZExtInst(lhs, Type::getInt16Ty(global_context), "zext16", block); + lhs = Builder->CreateZExt(lhs, Type::getInt16Ty(global_context), "zext16"); else if (v >= 16 && v <= 31) - lhs = new ZExtInst(lhs, Type::getInt32Ty(global_context), "zext32", block); + lhs = Builder->CreateZExt(lhs, Type::getInt32Ty(global_context), "zext32"); else if (v >= 32 && v <= 63) - lhs = new ZExtInst(lhs, Type::getInt64Ty(global_context), "zext64", block); + lhs = Builder->CreateZExt(lhs, Type::getInt64Ty(global_context), "zext64"); else yyerrorcpp("Number of shift bits exceeds the max int precision for left side.", this); Ty1 = lhs->getType(); @@ -73,9 +77,9 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, } else { if (Ty1->isIntegerTy()) - lhs = new SIToFPInst(lhs, Ty2, "castitof", block); + lhs = Builder->CreateSIToFP(lhs, Ty2, "castitof"); else if (Ty2->isIntegerTy()) - rhs = new SIToFPInst(rhs, Ty1, "castitof", block); + rhs = Builder->CreateSIToFP(rhs, Ty1, "castitof"); llvmop = opflt; } @@ -101,13 +105,13 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, } } - return BinaryOperator::Create(llvmop, lhs, rhs, "binop", block); + return Builder->CreateBinOp(llvmop, lhs, rhs, "binop"); } -Type *BinaryOp::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { - Type *lty = lhsn->getLLVMResultType(block, allocblock); - Type *rty = rhsn->getLLVMResultType(block, allocblock); - if (lty->isIntegerTy() && rty->isIntegerTy()) { +LanguageDataType BinaryOp::getResultType(BasicBlock *block, BasicBlock *allocblock) { + LanguageDataType lty = lhsn->getResultType(block, allocblock); + LanguageDataType rty = rhsn->getResultType(block, allocblock); + if (isIntegerDataType(lty) && isIntegerDataType(rty)) { if (op == TOK_LSHIFT || op == TOK_RSHIFT) { // zext the left operator if we know the rside bitwidth Constant *c = NULL; @@ -117,22 +121,22 @@ Type *BinaryOp::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { } if (c) { int64_t v = c->getUniqueInteger().getZExtValue(); - if (lty->getIntegerBitWidth() < v) { + if (LanguageDataTypeBitWidth[lty] < v) { if (v >= 8 && v <= 15) - return Type::getInt16Ty(global_context); + return tint16; else if (v >= 16 && v <= 31) - return Type::getInt32Ty(global_context); + return tint32; else if (v >= 32 && v <= 63) - return Type::getInt64Ty(global_context); + return tint64; else - return NULL; + return tvoid; } } } - return lty->getIntegerBitWidth() > rty->getIntegerBitWidth() ? lty : rty; + return LanguageDataTypeBitWidth[lty] > LanguageDataTypeBitWidth[rty] ? lty : rty; } else { - if (lty->isIntegerTy()) + if (isIntegerDataType(lty)) return rty; else return lty; @@ -140,6 +144,7 @@ Type *BinaryOp::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { } Value *BinaryOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + RobDbgInfo.emitLocation(this); switch (op) { case '+' : return binary_operator(Instruction::Add, Instruction::FAdd, func, block, allocblock); case '-' : return binary_operator(Instruction::Sub, Instruction::FSub, func, block, allocblock); diff --git a/src/BinaryOp.h b/src/BinaryOp.h index 1cfeb06..2841c51 100644 --- a/src/BinaryOp.h +++ b/src/BinaryOp.h @@ -22,7 +22,7 @@ class BinaryOp: public Node { int getOperator() const { return op; }; - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override; + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/Cast.cpp b/src/Cast.cpp index f40781d..1aa8f95 100644 --- a/src/Cast.cpp +++ b/src/Cast.cpp @@ -1,8 +1,8 @@ #include "Header.h" -Type *Cast::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { - return robTollvmDataType[dt]; +LanguageDataType Cast::getResultType(BasicBlock *block, BasicBlock *allocblock) { + return dt; } Value *Cast::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) diff --git a/src/Cast.h b/src/Cast.h index cfd1ce9..74faec6 100644 --- a/src/Cast.h +++ b/src/Cast.h @@ -11,5 +11,5 @@ class Cast: public Node { Cast(LanguageDataType dt, Node *expr): dt(dt), expr(expr) {} virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; virtual void accept(Visitor &v) override; - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override; + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/CmpOp.cpp b/src/CmpOp.cpp index c200ed5..47a1c93 100644 --- a/src/CmpOp.cpp +++ b/src/CmpOp.cpp @@ -28,6 +28,8 @@ Value *CmpOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock return ConstantInt::get(Type::getInt1Ty(global_context), 1); // error recover } + RobDbgInfo.emitLocation(this); + bool isFloatPointCmp = true; if (tl->isFloatingPointTy() && tr->isIntegerTy()) rexp = Coercion::Convert(rexp, tl, block, rexpn); @@ -58,10 +60,11 @@ Value *CmpOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock return NULL; } + Builder->SetInsertPoint(block); if (isFloatPointCmp) - return new FCmpInst(*block, predicate, lexp, rexp, "cmpf"); + return Builder->CreateFCmp(predicate, lexp, rexp, "cmpf"); else { - return new ICmpInst(*block, predicate, lexp, rexp, "cmpi"); + return Builder->CreateICmp(predicate, lexp, rexp, "cmpi"); } } diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp new file mode 100644 index 0000000..4371e0d --- /dev/null +++ b/src/DebugInfo.cpp @@ -0,0 +1,32 @@ +#include "Header.h" + +void DebugInfo::emitLocation(SourceLocation *s) { + if (!s) + return Builder->SetCurrentDebugLocation(DebugLoc()); + DIScope *scope; + if (scopes.empty()) + scope = cunit; + else + scope = scopes.back(); + Builder->SetCurrentDebugLocation(DILocation::get( + scope->getContext(), s->getLineNo(), s->getColNo(), scope)); +} + +void DebugInfo::push_scope(DIFile *f, DIScope *s) { + scopes.push_back(s); + files.push_back(f); +} + +void DebugInfo::pop_scope() { + scopes.pop_back(); + files.pop_back(); +} + +DIFile* DebugInfo::currFile() { + return files.back(); +} + +DIScope* DebugInfo::currScope() { + return scopes.back(); +} + diff --git a/src/Double.h b/src/Double.h index 4c26290..b9c5e33 100644 --- a/src/Double.h +++ b/src/Double.h @@ -11,8 +11,8 @@ class Double: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getDoubleTy(global_context); + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return tdouble; } }; diff --git a/src/FlipOp.h b/src/FlipOp.h index 32c4b24..3ba7635 100644 --- a/src/FlipOp.h +++ b/src/FlipOp.h @@ -14,8 +14,8 @@ class FlipOp: public Node { virtual void accept(Visitor &v) override; - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return value->getLLVMResultType(block, allocblock); + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return value->getResultType(block, allocblock); } virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; diff --git a/src/Float.h b/src/Float.h index 74fc342..0d8879b 100644 --- a/src/Float.h +++ b/src/Float.h @@ -11,8 +11,8 @@ class Float: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getFloatTy(global_context); + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return tfloat; } }; diff --git a/src/Float128.h b/src/Float128.h index bb87b32..1f01899 100644 --- a/src/Float128.h +++ b/src/Float128.h @@ -13,8 +13,8 @@ class Float128: public Node { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getFP128Ty(global_context); + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return tldouble; } }; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 66542c2..03fbc0d 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -1,16 +1,14 @@ #include "Header.h" -Type* FunctionCall::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { +LanguageDataType FunctionCall::getResultType(BasicBlock *block, BasicBlock *allocblock) { auto symbol = search_symbol(name); - if (symbol) { - Function *cfunc = dyn_cast(symbol->value); - if (cfunc) - return cfunc->getReturnType(); - } - return NULL; + if (symbol) + return symbol->dt; + return tvoid; } Value *FunctionCall::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + auto symbol = search_symbol(name); if (symbol == NULL) { yyerrorcpp("Function " + name + " not defined.", this); @@ -30,10 +28,8 @@ Value *FunctionCall::generate(Function *func, BasicBlock *block, BasicBlock *all } ArrayRef argsRef(args); - bool isVoidReturn = cfunc->getReturnType()->isVoidTy(); - if (isVoidReturn) - return CallInst::Create(cfunc, argsRef, "", block); - else - return CallInst::Create(cfunc, argsRef, "fc", block); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateCall(cfunc, argsRef, "fc"); } diff --git a/src/FunctionCall.h b/src/FunctionCall.h index 304eeb7..675a7b9 100644 --- a/src/FunctionCall.h +++ b/src/FunctionCall.h @@ -13,7 +13,7 @@ class FunctionCall: public Node { } virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - Type* getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override; + LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; }; #endif diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 0c436b1..391d9c6 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -11,37 +11,67 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) std::vector arg_types; if (parameters->getNumParams() != 0) for (int i = 0; i < parameters->getNumParams(); i++) - arg_types.push_back(parameters->getParamType(i)); + arg_types.push_back(robTollvmDataType[parameters->getParamType(i)]); Type *xtype = robTollvmDataType[tipo]; FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, 0, name, mainmodule); nfunc->setDSOLocal(true); - llvm::AttrBuilder attrs(global_context); + llvm::AttrBuilder attrs(global_context); attrs.addAttribute(llvm::Attribute::MinSize); - //attrs.addAttribute("stack-protector-buffer-size", llvm::utostr(8)); + //attrs.addAttribute("stack-protector-buffer-size", llvm::utostr(8)); //attrs.addAttribute("frame-pointer", "all"); //attrs.addAttribute("no-trapping-math", "true"); nfunc->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); - tabelasym[allocblock][name] = new RobSymbol(nfunc); + RobSymbol *rs = new RobSymbol(nfunc); + rs->dt = tipo; + tabelasym[allocblock][name] = rs; + + DIFile *funit; + DISubprogram *sp; + if (debug_info) { + funit = DBuilder->createFile(RobDbgInfo.cunit->getFilename(), RobDbgInfo.cunit->getDirectory()); + DIScope *fcontext = funit; + sp = DBuilder->createFunction(fcontext, name, StringRef(), funit, this->lineno, + getFunctionDIType(), this->lineno, DINode::FlagPrototyped, DISubprogram::SPFlagDefinition); + nfunc->setSubprogram(sp); + RobDbgInfo.push_scope(funit, sp); + RobDbgInfo.emitLocation(nullptr); + } BasicBlock *falloc = BasicBlock::Create(global_context, "entry", nfunc); BasicBlock *fblock = BasicBlock::Create(global_context, "body", nfunc); + Builder->SetInsertPoint(falloc); unsigned Idx = 0; for (auto &Arg : nfunc->args()) { const char *argname = parameters->getParamElement(Idx); + LanguageDataType ptype = parameters->getParamType(Idx); + Arg.setName(argname); - //Value *valor = search_symbol(argname, fblock, fblock); - AllocaInst* variable = new AllocaInst(parameters->getParamType(Idx), 0, argname, falloc); - tabelasym[falloc][argname] = new RobSymbol(variable); - StoreInst *val = new StoreInst(&Arg, variable, false, fblock); + AllocaInst* variable = Builder->CreateAlloca(robTollvmDataType[ptype], 0, argname ); + RobSymbol *rs = new RobSymbol(variable); + rs->dt = ptype; + tabelasym[falloc][argname] = rs; + StoreInst *val = Builder->CreateStore(&Arg, variable, false); + + if (debug_info) { + DILocalVariable *d = DBuilder->createParameterVariable(sp, argname, Idx+1, funit, + this->lineno, RobDbgInfo.types[ptype], true); + DBuilder->insertDeclare(variable, d, DBuilder->createExpression(), + DILocation::get(sp->getContext(), this->lineno, 0, sp), + falloc); + } + Idx++; } nfunc->setCallingConv(CallingConv::C); + if (debug_info) + RobDbgInfo.emitLocation(stmts); + Value *last_block = stmts->generate(nfunc, fblock, falloc); if (!last_block) last_block = fblock; @@ -61,6 +91,17 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) BranchInst::Create(fblock, falloc); + if (debug_info) + RobDbgInfo.pop_scope(); + return nfunc; } +DISubroutineType *FunctionDecl::getFunctionDIType() { + SmallVector Tys; + Tys.push_back(RobDbgInfo.types[tipo]); // return type + for(FunctionParam &p : parameters->parameters) { + Tys.push_back(RobDbgInfo.types[p.type]); + } + return DBuilder->createSubroutineType(DBuilder->getOrCreateTypeArray(Tys)); +} diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 59b8226..f3c53f1 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -23,6 +23,7 @@ class FunctionDecl: public Node { virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + DISubroutineType *getFunctionDIType(); }; #endif diff --git a/src/FunctionDeclExtern.cpp b/src/FunctionDeclExtern.cpp index d0f0318..fd852c8 100644 --- a/src/FunctionDeclExtern.cpp +++ b/src/FunctionDeclExtern.cpp @@ -11,8 +11,8 @@ Value *FunctionDeclExtern::generate(Function *, BasicBlock *, BasicBlock *allocb std::vector arg_types; if (parameters->getNumParams() != 0) for (int i = 0; i < parameters->getNumParams(); i++) - arg_types.push_back(parameters->getParamType(i)); - + arg_types.push_back(robTollvmDataType[parameters->getParamType(i)]); + Type *xtype = robTollvmDataType[tipo]; FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, 0, name, mainmodule); diff --git a/src/FunctionParams.cpp b/src/FunctionParams.cpp index 31cf9bd..0452962 100644 --- a/src/FunctionParams.cpp +++ b/src/FunctionParams.cpp @@ -10,8 +10,8 @@ unsigned FunctionParams::getNumParams() const { return parameters.size(); }; -Type *FunctionParams::getParamType(int position) const { - return robTollvmDataType[parameters[position].type]; +LanguageDataType FunctionParams::getParamType(int position) const { + return parameters[position].type; } const char *FunctionParams::getParamElement(int position) const { diff --git a/src/FunctionParams.h b/src/FunctionParams.h index 63bfe1b..4b44bea 100644 --- a/src/FunctionParams.h +++ b/src/FunctionParams.h @@ -11,7 +11,7 @@ class FunctionParams { void append(FunctionParam& fp); unsigned getNumParams() const; - Type *getParamType (int position) const; + LanguageDataType getParamType (int position) const; const char *getParamElement (int position) const; }; diff --git a/src/Header.h b/src/Header.h index a1c9f59..899573f 100644 --- a/src/Header.h +++ b/src/Header.h @@ -17,11 +17,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -38,6 +40,14 @@ enum LanguageDataType {tvoid, tbool, tchar, tint8, tint16, tint32, tint64, tint8u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, __ldt_last}; +static bool isIntegerDataType(LanguageDataType dt) { + return dt >= tint8 && dt <= tint64u; +} + +static bool isFloatDataType(LanguageDataType dt) { + return dt >= tfloat && dt <= tldouble; +} + static const char *LanguageDataTypeNames[__ldt_last] = {"void", "boolean", "char", "int8", "int16", "int32", "int64", "unsigned int8", "unsigned int16", "unsigned int32", "unsigned int64", "float", @@ -46,6 +56,15 @@ static const char *LanguageDataTypeNames[__ldt_last] = {"void", "boolean", "char static const unsigned LanguageDataTypeBitWidth[__ldt_last] = {0, 1, 8, 8, 16, 32, 64, 8, 16, 32, 64, 32, 64, 128}; +static const unsigned LanguageDataTypeDwarfEnc[__ldt_last] = { + dwarf::DW_ATE_address, + dwarf::DW_ATE_boolean, + dwarf::DW_ATE_unsigned_char, + dwarf::DW_ATE_signed, dwarf::DW_ATE_signed, dwarf::DW_ATE_signed, dwarf::DW_ATE_signed, + dwarf::DW_ATE_unsigned, dwarf::DW_ATE_unsigned, dwarf::DW_ATE_unsigned, dwarf::DW_ATE_unsigned, + dwarf::DW_ATE_float, dwarf::DW_ATE_float, dwarf::DW_ATE_float +}; + enum DataQualifier {qnone, qconst, qvolatile}; extern Type* robTollvmDataType[]; @@ -74,24 +93,46 @@ typedef struct { #include "Field.h" +typedef struct { + int first_line; + int first_column; + int last_line; + int last_column; +} location_t; + #include "bison.hpp" extern int yyerror(const char *s); extern int yylex(); -extern int yylineno; -extern int yycolno; extern Node* getNodeForIntConst(int64_t i); -// Program main module -extern Module *mainmodule; -extern BasicBlock *global_alloc; - extern char* build_filename; extern char* build_outputfilename; -extern LLVMContext global_context; #include "SourceLocation.h" +// Program main module and IR Builder +extern Module* mainmodule; +extern BasicBlock* global_alloc; +extern LLVMContext global_context; +extern std::unique_ptr> Builder; + +// Debug Info +extern bool debug_info; +extern std::unique_ptr DBuilder; +struct DebugInfo { + DICompileUnit *cunit; + DIType *types[__ldt_last]; + vector files; + vector scopes; + void emitLocation(SourceLocation *s); + void push_scope(DIFile *f, DIScope *); + void pop_scope(); + DIFile *currFile(); + DIScope *currScope(); +}; +extern struct DebugInfo RobDbgInfo; + // symbol table #include "RobSymbol.h" extern map> tabelasym; @@ -129,8 +170,8 @@ static string getTypeName(Type *ty) { static int yyerrorcpp(const string& s, SourceLocation *n) { string e = COLOR_RED "semantic error: " COLOR_RESET + s; if (n) { - yylineno = n->getLineNo(); - yycolno = n->getColNo(); + yylloc.first_line = n->getLineNo(); + yylloc.first_column = n->getColNo(); } return yyerror(e.c_str()); } @@ -138,11 +179,11 @@ static int yyerrorcpp(const string& s, SourceLocation *n) { static void yywarncpp(const string& s, SourceLocation *n) { string e = COLOR_BLUE "semantic warning: " COLOR_RESET + s; if (n) { - yylineno = n->getLineNo(); - yycolno = n->getColNo(); + yylloc.first_line = n->getLineNo(); + yylloc.first_column = n->getColNo(); } fprintf(stderr, "%s:%d:%d %s\n", - build_filename, yylineno, yycolno, e.c_str()); + build_filename, yylloc.first_line, yylloc.first_column, e.c_str()); } static RobSymbol *search_symbol(const string& ident, BasicBlock *firstb = NULL, BasicBlock *secondb = NULL) { diff --git a/src/Int1.h b/src/Int1.h index f55868c..ab82125 100644 --- a/src/Int1.h +++ b/src/Int1.h @@ -12,7 +12,7 @@ class Int1: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getInt1Ty(global_context); + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return tbool; } }; diff --git a/src/Int16.h b/src/Int16.h index 18b8972..5900bb3 100644 --- a/src/Int16.h +++ b/src/Int16.h @@ -14,8 +14,8 @@ class Int16: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getInt16Ty(global_context); + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return tint16; } }; diff --git a/src/Int32.h b/src/Int32.h index 5b4c520..5482849 100644 --- a/src/Int32.h +++ b/src/Int32.h @@ -14,8 +14,8 @@ class Int32: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getInt32Ty(global_context); + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return tint32; } }; diff --git a/src/Int64.h b/src/Int64.h index 15536d5..c94ece2 100644 --- a/src/Int64.h +++ b/src/Int64.h @@ -13,8 +13,8 @@ class Int64: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getInt64Ty(global_context); + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return tint64; } }; diff --git a/src/Int8.h b/src/Int8.h index efbc253..868a1cf 100644 --- a/src/Int8.h +++ b/src/Int8.h @@ -13,8 +13,8 @@ class Int8: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override { - return Type::getInt8Ty(global_context); + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return tint8; } }; diff --git a/src/Language.l b/src/Language.l index 9ff7304..bd58a77 100644 --- a/src/Language.l +++ b/src/Language.l @@ -6,8 +6,16 @@ extern void unescape(char *s); extern int yycolno; -extern int yycolnew; -#define YY_USER_ACTION yycolno = yycolnew; yycolnew += yyleng; + +static void update_loc() { + yylloc.first_line = yylineno; + yylloc.last_line = yylineno; + yylloc.first_column = yycolno; + yylloc.last_column = yycolno + yyleng - 1; + yycolno += yyleng; +} + +#define YY_USER_ACTION update_loc(); %} @@ -17,7 +25,7 @@ extern int yycolnew; %% [ \t\r] { /* ignore spaces */ } -[\n] { yycolnew = 0; yycolno = 0; } +[\n] { yycolno = 0; } "/*" { yymore(); BEGIN COMMENT; } [^*] { yymore(); } "*"/[^/] { yymore(); } diff --git a/src/Language.y b/src/Language.y index adc6add..eeb032c 100644 --- a/src/Language.y +++ b/src/Language.y @@ -9,9 +9,10 @@ Node* getNodeForIntConst(int64_t i); std::vector vectorglobal; extern int errorsfound; - %} +%locations +%define api.location.type {location_t} %define parse.error verbose %token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST @@ -73,6 +74,7 @@ extern int errorsfound; %type struct_field %type struct_fields %type complex_identifier +%type error %precedence IFX %precedence TOK_ELSE @@ -95,8 +97,8 @@ programa : gstmts { Program p($1); }; ; -gstmts : gstmts gstmt { $1->append($2); } - | gstmt { $$ = new Stmts($1); } +gstmts : gstmts gstmt { $1->append($gstmt);} + | gstmt { $$ = new Stmts($gstmt); $gstmt->setLocation(@gstmt); } ; gstmt : TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($1, $3, qnone); } @@ -117,9 +119,11 @@ fe : funcblock { $$ = $1; } funcblock : type_f TOK_IDENTIFIER '(' funcparams ')' ';' { $$ = new FunctionDeclExtern($1, $2, $4); + $$->setLocation(@type_f); } | type_f TOK_IDENTIFIER '(' funcparams ')' '{' stmts '}' { $$ = new FunctionDecl($1, $2, $4, $7); + $$->setLocation(@type_f); } ; @@ -132,9 +136,8 @@ eventblock : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}' { } ; -stmts : stmts stmt { $1->append($2); - $$ = $1; } - | stmt { $$ = new Stmts($1); } +stmts : stmts stmt { $1->append($stmt); } + | stmt { $$ = new Stmts($stmt); $stmt->setLocation(@stmt); } ; stmt : gstmt { $$ = $1; } @@ -207,10 +210,14 @@ funcparams: funcparams ',' funcparam { } ; -funcparam : type_f TOK_IDENTIFIER { - FunctionParam fp{$2, $1}; - $$ = fp; +funcparam : type_f TOK_IDENTIFIER[id] { + $$ = FunctionParam{$id, $type_f}; } + | TOK_IDENTIFIER[id1] TOK_IDENTIFIER[id2] { + yyerrorcpp(string_format("Invalid type name '%s' for parameter %s.", $id1, $id2), nullptr); + $$ = FunctionParam{$2, tvoid}; + } + ; type_f : TOK_VOID { $$ = tvoid; } | TOK_FCHAR { $$ = tchar; } @@ -226,6 +233,11 @@ type_f : TOK_VOID { $$ = tvoid; } | TOK_FFLOAT { $$ = tfloat; } | TOK_FDOUBLE { $$ = tdouble; } | TOK_FLONG TOK_FDOUBLE { $$ = tldouble; } +/* | TOK_IDENTIFIER[ident] { + yyerrok; + yyerrorcpp(string_format("Invalid type name '%s'.", $ident), nullptr); + $$ = tvoid; + }*/ ; paramscall : paramscall ',' expr {$1 -> append($3); @@ -252,8 +264,15 @@ elseblock : TOK_ELSE stmt { $$ = $2; } | TOK_ELSE '{' stmts '}' { $$ = $3; } ; -whileblock : TOK_WHILE '(' logicexpr ')' '{' stmts '}' { $$ = new While($3, $6); } - | TOK_LOOP '{' stmts '}' { $$ = new Loop($3); } +whileblock : TOK_WHILE '(' logicexpr ')' '{' stmts '}' { + $logicexpr->setLocation(@logicexpr); + $$ = new While($logicexpr, $stmts); + $$->setLocation(@TOK_WHILE); + } + | TOK_LOOP '{' stmts '}' { + $$ = new Loop($stmts); + $$->setLocation(@TOK_LOOP); + } ; logicexpr : logicexpr TOK_OR logicterm { $$ = new BinaryOp($1, TOK_OR, $3); } @@ -374,15 +393,12 @@ struct_field : type_f TOK_IDENTIFIER ';' { %% -extern int yylineno; -extern int yycolno; -extern char *yytext; extern char *build_filename; int yyerror(const char *s) { fprintf(stderr, "%s:%d:%d: %s\n", - build_filename, yylineno, yycolno, s); + build_filename, yylloc.first_line, yylloc.first_column, s); errorsfound++; return 0; } diff --git a/src/Load.cpp b/src/Load.cpp index 89a04c5..fa5e400 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -1,16 +1,10 @@ #include "Header.h" -Type* Load::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { +LanguageDataType Load::getResultType(BasicBlock *block, BasicBlock *allocblock) { auto rsym = search_symbol(ident, allocblock, block); - if (rsym) { - if (auto *lvalue = dyn_cast(rsym->value)) - return lvalue->getAllocatedType(); - else if (auto *lvalue = dyn_cast(rsym->value)) - return lvalue->getValueType(); - else - return rsym->pointerType; - } - return NULL; + if (rsym) + return rsym->dt; + return tvoid; } Value* Load::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { @@ -33,19 +27,21 @@ Value* Load::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) } } - LoadInst *ret = NULL; + Type *ty; bool vol = rsym->qualifier == qvolatile; if (auto *lvalue = dyn_cast(sym)) - ret = new LoadInst(lvalue->getAllocatedType(), sym, ident, vol, block); + ty = lvalue->getAllocatedType(); else if (auto *lvalue = dyn_cast(sym)) - ret = new LoadInst(lvalue->getValueType(), sym, ident, vol, block); + ty = lvalue->getValueType(); else if (rsym->pointerType != NULL) - ret = new LoadInst(rsym->pointerType, sym, ident, vol, block); + ty = rsym->pointerType; else { printf("ERR: Going to return NULL!\n"); } - - return ret; + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateLoad(ty, sym, vol, ident); } void Load::accept(Visitor &v) { diff --git a/src/Load.h b/src/Load.h index b51c4b0..2788bc8 100644 --- a/src/Load.h +++ b/src/Load.h @@ -16,7 +16,7 @@ class Load: public Node { virtual void accept(Visitor& v) override; - virtual Type* getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) override; + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index b91860c..934f42d 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -1,21 +1,11 @@ #include "Header.h" -Type* LoadArray::getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { +LanguageDataType LoadArray::getResultType(BasicBlock *block, BasicBlock *allocblock) { if (!rsym) rsym = search_symbol(ident, allocblock, block); - if (rsym) { - Type *ty = NULL; - if (auto *aux = dyn_cast(rsym->value)) - ty = aux->getAllocatedType(); - else if (auto *aux = dyn_cast(rsym->value)) - ty = aux->getValueType(); - - if (ty->isArrayTy()) { - ArrayType *arrayTy = (ArrayType*)ty; - return arrayTy->getArrayElementType(); - } - } - return NULL; + if (rsym) + return rsym->dt; + return tvoid; } Value *LoadArray::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { diff --git a/src/LoadArray.h b/src/LoadArray.h index 24ab96e..fa3c0de 100644 --- a/src/LoadArray.h +++ b/src/LoadArray.h @@ -13,7 +13,7 @@ class LoadArray: public Node { Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); - virtual Type* getLLVMResultType(BasicBlock *block, BasicBlock *allocblock); + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock); virtual Node *getLoadIndex(RobSymbol *rsym, BasicBlock *block, BasicBlock *allocblock) { return position; diff --git a/src/Loop.cpp b/src/Loop.cpp index c0385aa..e43b9ea 100644 --- a/src/Loop.cpp +++ b/src/Loop.cpp @@ -7,10 +7,20 @@ Loop::Loop(Node *stms) : stmts(stms) { Value *Loop::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { BasicBlock *bodyloop = BasicBlock::Create(global_context, "loop_body", func, 0); + + RobDbgInfo.emitLocation(this); + + // go to loop + Builder->SetInsertPoint(block); + Builder->CreateBr(bodyloop); + // alloc instructions inside bodyloop should go to allocblock to prevent repeatedly allocation Value *newb = stmts->generate(func, bodyloop, allocblock); - BranchInst::Create(bodyloop, bodyloop); - BranchInst::Create(bodyloop, block); + + // return to loop at end + Builder->SetInsertPoint(bodyloop); + Builder->CreateBr(bodyloop); + BasicBlock *endloop = BasicBlock::Create(global_context, "loop_end", func, 0); return endloop; } diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 840faf7..7387cfc 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -7,7 +7,7 @@ Value *Matrix::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc */ //Get Type of elements in Vector of Elements, and define as I. - Type* I = melements->getMatrixType(block, allocblock); + Type* I = robTollvmDataType[melements->getMatrixType(block, allocblock)]; // The matrix size unsigned int lines = melements->getLineCount(); diff --git a/src/MatrixElements.cpp b/src/MatrixElements.cpp index 24c9ffd..7f75e0e 100644 --- a/src/MatrixElements.cpp +++ b/src/MatrixElements.cpp @@ -26,40 +26,40 @@ unsigned MatrixElements::getColumnCount() const { return biggest_r; } -Type *MatrixElements::getMatrixType(BasicBlock *block, BasicBlock *allocblock) const { +LanguageDataType MatrixElements::getMatrixType(BasicBlock *block, BasicBlock *allocblock) const { unsigned intsize = 0; unsigned floatsize = 0; for(auto& j : elements) { for (auto& i : j.array->elements) { - Type *ty = i.value->getLLVMResultType(block, allocblock); - if (ty->isIntegerTy() && intsize < ty->getIntegerBitWidth()) - intsize = ty->getIntegerBitWidth(); + LanguageDataType dt = i.value->getResultType(block, allocblock); + if (isIntegerDataType(dt) && intsize < LanguageDataTypeBitWidth[dt]) + intsize = LanguageDataTypeBitWidth[dt]; - if (floatsize < 32 && ty->isFloatTy()) + if (floatsize < 32 && dt == tfloat) floatsize = 32; - else if (floatsize < 64 && ty->isDoubleTy()) + else if (floatsize < 64 && dt == tdouble) floatsize = 64; - else if (floatsize < 128 && ty->isFP128Ty()) + else if (floatsize < 128 && dt == tldouble) floatsize = 128; } } if (intsize == 0 && floatsize == 0) { - yyerrorcpp("FIXME: matrix of non-consts.", NULL); - return NULL; + yyerrorcpp("FIXME: vector of non-consts/non-numbers.", NULL); + return tvoid; } if (floatsize == 0) { switch (intsize) { - case 1: return Type::getInt1Ty(global_context); - case 8: return Type::getInt8Ty(global_context); - case 16: return Type::getInt16Ty(global_context); - case 32: return Type::getInt32Ty(global_context); - default: return Type::getInt64Ty(global_context); + case 1: return tbool; + case 8: return tint8; + case 16: return tint16; + case 32: return tint32; + default: return tint64; } } else { switch (floatsize) { - case 32: return Type::getFloatTy(global_context); - case 64: return Type::getDoubleTy(global_context); - default: return Type::getFP128Ty(global_context); + case 32: return tfloat; + case 64: return tdouble; + default: return tldouble; } } } diff --git a/src/MatrixElements.h b/src/MatrixElements.h index 0d238a8..6c8c20f 100644 --- a/src/MatrixElements.h +++ b/src/MatrixElements.h @@ -13,7 +13,7 @@ class MatrixElements { unsigned getColumnCount() const; unsigned getLineCount() const; unsigned getElementCount(int position) const; - Type *getMatrixType(BasicBlock *block, BasicBlock *allocblock) const; + LanguageDataType getMatrixType(BasicBlock *block, BasicBlock *allocblock) const; }; #endif diff --git a/src/Node.h b/src/Node.h index 56234a9..e5b88d3 100644 --- a/src/Node.h +++ b/src/Node.h @@ -20,11 +20,11 @@ class Node : public SourceLocation { virtual std::vector const& children() const; virtual void accept(Visitor &); - virtual Type *getLLVMResultType(BasicBlock *block, BasicBlock *allocblock) { + virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) { /* this method should be overrided in descending classes * that define vars/consts */ - return NULL; + return tvoid; } }; diff --git a/src/Program.cpp b/src/Program.cpp index 0fdb795..f8a0af9 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -114,8 +114,29 @@ void Program::generate() { robTollvmDataType[tldouble] = Type::getFP128Ty(global_context); mainmodule = new Module(build_filename, global_context); + Builder = make_unique>(global_context); + + if (debug_info) { + mainmodule->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); + mainmodule->addModuleFlag(Module::Warning, "Dwarf Version", 2); + DBuilder = make_unique(*mainmodule); + RobDbgInfo.cunit = DBuilder->createCompileUnit(dwarf::DW_LANG_C, + DBuilder->createFile(build_filename, std::filesystem::current_path().string()), + "Robcmp", false, "", 0); + for(int t = 0; t < __ldt_last; t++) { + RobDbgInfo.types[t] = DBuilder->createBasicType( + LanguageDataTypeNames[t], + LanguageDataTypeBitWidth[t], + LanguageDataTypeDwarfEnc[t] + ); + } + } + global_alloc = BasicBlock::Create(global_context, "global"); // generate the program! stmts->generate(NULL, NULL, global_alloc); + + if (debug_info) + DBuilder->finalize(); } diff --git a/src/RobSymbol.h b/src/RobSymbol.h index d273889..71a59d1 100644 --- a/src/RobSymbol.h +++ b/src/RobSymbol.h @@ -9,11 +9,13 @@ class RobSymbol: public SourceLocation { unsigned int matrixLines; unsigned int matrixCols; Structure *structure; + LanguageDataType dt; RobSymbol(Value *v, DataQualifier qualifier = qnone, Type *pointerType = NULL): value(v), qualifier(qualifier), pointerType(pointerType) { matrixLines = matrixCols = 0; structure = nullptr; + dt = tvoid; } }; diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 552ce68..c5000f5 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -14,6 +14,8 @@ Scalar::Scalar(ComplexIdentifier *ci, Node *e, DataQualifier qualifier) : Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + RobDbgInfo.emitLocation(this); + string id = complexIdent ? complexIdent->names[0] : name; auto symbol = search_symbol(id, allocblock, block); Field field; @@ -37,6 +39,8 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc if (symbol == NULL) { Value *ret, *leftv; Value *exprv = expr->generate(func, block, allocblock); + LanguageDataType dt = expr->getResultType(block, allocblock); + if (!exprv) return NULL; @@ -48,16 +52,28 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc if (qualifier == qconst) ret = leftv = exprvc; else { - GlobalVariable *gv = new GlobalVariable(*mainmodule, exprvc->getType(), + GlobalVariable *gv = new GlobalVariable(*mainmodule, robTollvmDataType[dt], false, GlobalValue::CommonLinkage, exprvc, name); ret = leftv = gv; } } else { - leftv = new AllocaInst(exprv->getType(), 0, name, allocblock); - ret = new StoreInst(exprv, leftv, qualifier == qvolatile, block); + Builder->SetInsertPoint(allocblock); + leftv = Builder->CreateAlloca(exprv->getType(), 0, name); + Builder->SetInsertPoint(block); + ret = Builder->CreateStore(exprv, leftv, qualifier == qvolatile); + if (debug_info) { + auto sp = RobDbgInfo.currScope(); + auto funit = RobDbgInfo.currFile(); + DILocalVariable *d = DBuilder->createAutoVariable( + sp, name, funit, lineno, RobDbgInfo.types[dt], true); + DBuilder->insertDeclare(leftv, d, DBuilder->createExpression(), + DILocation::get(sp->getContext(), lineno, 0, sp), allocblock); + } } - tabelasym[allocblock][name] = new RobSymbol(leftv, qualifier); + RobSymbol *rs = new RobSymbol(leftv, qualifier); + rs->dt = dt; + tabelasym[allocblock][name] = rs; return ret; } else { @@ -107,7 +123,9 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc nvalue = Coercion::Convert(exprv, leftvty, block, expr); } - return new StoreInst(nvalue, symbol->value, qualifier == qvolatile, block); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateStore(nvalue, symbol->value, qualifier == qvolatile); } } diff --git a/src/SourceLocation.h b/src/SourceLocation.h index 345035b..34829d0 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -21,4 +21,9 @@ class SourceLocation { virtual int getColNo() { return colno; } + + virtual void setLocation(location_t l) { + lineno = l.first_line; + colno = l.first_column; + } }; diff --git a/src/While.cpp b/src/While.cpp index f8f5959..0bf2019 100644 --- a/src/While.cpp +++ b/src/While.cpp @@ -8,26 +8,34 @@ While::While(Node *e, Node *stms) : expr(e), stmts(stms) { Value *While::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { BasicBlock *condwhile = BasicBlock::Create(global_context, "while_cond", func, 0); + BasicBlock *bodywhile = BasicBlock::Create(global_context, "while_body", func, 0); + BasicBlock *endwhile = BasicBlock::Create(global_context, "while_end", func, 0); + + // go to condition + RobDbgInfo.emitLocation(expr); + Builder->SetInsertPoint(block); + Builder->CreateBr(condwhile); + Value *exprv = expr->generate(func, condwhile, allocblock); - BasicBlock *bodywhile = BasicBlock::Create(global_context, "while_body", func, 0); - + // check condition + RobDbgInfo.emitLocation(expr); + Builder->SetInsertPoint(condwhile); + Builder->CreateCondBr(exprv, bodywhile, endwhile); + // alloc instructions inside bodywhile should go to allocblock to prevent repeatedly allocation Value *newb = stmts->generate(func, bodywhile, allocblock); - BasicBlock *endwhile = BasicBlock::Create(global_context, "while_end", func, 0); - - BranchInst::Create(condwhile, block); - BranchInst::Create(bodywhile, endwhile, exprv, condwhile); - // identify last while body block BasicBlock *endbody = bodywhile; if (newb->getValueID() == Value::BasicBlockVal) endbody = (BasicBlock*)newb; // if end block already has a terminator, don't generate branch - if (!((BasicBlock*)endbody)->getTerminator()) - BranchInst::Create(condwhile, endbody); + if (!((BasicBlock*)endbody)->getTerminator()) { + Builder->SetInsertPoint(endbody); + Builder->CreateBr(condwhile); + } return endwhile; } diff --git a/src/main.cpp b/src/main.cpp index a9d06cf..043d1b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,20 +14,22 @@ Function *AttachInterrupt::fattach = NULL; // file name char *build_filename; char *build_outputfilename; +bool debug_info; int main(int argc, char *argv[]) { char optimization = 'z'; const char *targetarch = ""; build_outputfilename = NULL; + debug_info = false; if (argc <= 1) { - fprintf(stderr, "Syntax: %s -O{1,2,3,s,z} -a {", argv[0]); + fprintf(stderr, "Syntax: %s -a {", argv[0]); for(int t = 1; t < (sizeof(supportedTargets)/sizeof(TargetInfo)); t++) { if (t > 1) fprintf(stderr, ","); fprintf(stderr, "%s", supportedTargets[t].name); } - fprintf(stderr, "} -o output_file input_file\n"); + fprintf(stderr, "} -g -O{1,2,3,s,z} -o output_file input_file\n"); return 1; } @@ -41,6 +43,9 @@ int main(int argc, char *argv[]) { else if (strncmp(argv[i], "-a", 2) == 0) { targetarch = argv[++i]; } + else if (strncmp(argv[i], "-g", 2) == 0) { + debug_info = true; + } else if (strncmp(argv[i], "-o", 2) == 0) { build_outputfilename = argv[++i]; } From 8ba9bfd1f892a3149fc6dd0a1c02dd0f9172b41d Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 19 Jul 2023 10:32:05 -0300 Subject: [PATCH 020/117] Enable debug symbols emission in some Nodes and small fixes. --- platformio/platform/builder/main.py | 1 + platformio/platform/platform.py | 3 +- platformio/samples/avr328p-blink/src/main.rob | 15 +++++++-- platformio/samples/avr328p-blink/src/two.rob | 4 +-- src/Array.cpp | 32 +++++++++++++++---- src/BackLLVM.cpp | 15 +++------ src/Coercion.cpp | 15 +++++---- src/DebugInfo.cpp | 6 ++++ src/Header.h | 23 +++++++------ src/Language.y | 2 +- src/LoadArray.cpp | 2 +- src/Loop.cpp | 13 ++++++-- src/Program.cpp | 4 +++ src/RobSymbol.h | 2 ++ src/Scalar.cpp | 27 +++++++++++----- src/SourceLocation.h | 5 +++ src/main.cpp | 16 ++++++++-- 17 files changed, 134 insertions(+), 51 deletions(-) diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 4d9ede8..e6b8925 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -34,6 +34,7 @@ robcmp_args = ["robcmp", "-a", board, "-o", "$TARGET"] if build_type == "debug": robcmp_args.append("-g") + robcmp_args.append("-O0") elif build_type == "release": robcmp_args.append("-Oz") ldflags.append("--gc-sections") diff --git a/platformio/platform/platform.py b/platformio/platform/platform.py index 1c8ce51..f414781 100644 --- a/platformio/platform/platform.py +++ b/platformio/platform/platform.py @@ -3,6 +3,7 @@ # Require packages according to upload_protocol and custom_mcu # +import os from platformio.public import PlatformBase class RobcmpPlatform(PlatformBase): @@ -43,7 +44,7 @@ def _add_default_debug_tools(self, board): if debug.get("target_mcu", ""): debug["tools"]["robcmp"]["server"]["arguments"] = [ - "-f", "$PROGNAME", + "-f", "$PROG_PATH", "-m", debug["target_mcu"], "-hw", "led" ] diff --git a/platformio/samples/avr328p-blink/src/main.rob b/platformio/samples/avr328p-blink/src/main.rob index e72c794..a17cd14 100644 --- a/platformio/samples/avr328p-blink/src/main.rob +++ b/platformio/samples/avr328p-blink/src/main.rob @@ -24,6 +24,7 @@ register int8 ddrb at 0x24 { void wait(); int16 main() { + arr = {10000, 5000, 3000, 2000, 1000, 500}; /* pin 13 is controlled by bit 5 of DDRB and PORTB registers * - bit 5 of DDRB indicates if the pin is input (0) or output (1) @@ -33,12 +34,22 @@ int16 main() { // set pin 13 as output ddrb.pin13 = true; + w = 0; + t = 10; loop { // set bit 5 high portb.pin13 = true; - wait(); + wait(arr[w]); // set bit 5 low portb.pin13 = false; - wait(); + wait(arr[w]); + + t--; + if (t == 0) { + w++; + } + if (w > 5) { + w = 0; + } } } diff --git a/platformio/samples/avr328p-blink/src/two.rob b/platformio/samples/avr328p-blink/src/two.rob index b7ceb5d..c55893f 100644 --- a/platformio/samples/avr328p-blink/src/two.rob +++ b/platformio/samples/avr328p-blink/src/two.rob @@ -1,6 +1,6 @@ -void wait() { - volatile i = 50000; +void wait(int32 q) { + volatile i = q; while (i > 0) { i--; } diff --git a/src/Array.cpp b/src/Array.cpp index 4108f85..d180598 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -6,7 +6,8 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock Value *array_size = ConstantInt::get(Type::getInt8Ty(global_context), size); //Get Type of elements in Array of Elements, and define as I. - Type* I = robTollvmDataType[elements->getArrayType(block, allocblock)]; + LanguageDataType pointee_dt = elements->getArrayType(block, allocblock); + Type* I = robTollvmDataType[pointee_dt]; //Declare array type. ArrayType* arrayType = ArrayType::get(I, size); @@ -37,6 +38,9 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock return NULL; } + auto sp = RobDbgInfo.currScope(); + auto funit = RobDbgInfo.currFile(); + //Allocate array. Value* var; if (allocblock == global_alloc) { // when alloc is global @@ -48,21 +52,37 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock GlobalVariable *gv = new GlobalVariable(*mainmodule, arrayType, false, GlobalValue::ExternalLinkage, ConstantArray::get(arrayType, constantRefs), name); var = gv; + + if (debug_info) { + //FIXME: Replace 16 with pointer size for platform! + auto di_ptr = DBuilder->createPointerType(RobDbgInfo.types[pointee_dt], 16); + auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", + funit, lineno, di_ptr, false); + gv->addDebugInfo(d); + } + } else { - var = new AllocaInst(arrayType, 0, name, allocblock); + Builder->SetInsertPoint(allocblock); + var = Builder->CreateAlloca(arrayType, 0, name); + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); StoreInst *store = NULL; for(unsigned index = 0; index < elementValues.size(); index++) { Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), index); Value* indexList[2] = {zero, idx}; - GetElementPtrInst* gep = GetElementPtrInst::Create(arrayType, var, - ArrayRef(indexList), "", block); - store = new StoreInst(elementValues[index], gep, false, block); + Value* gep = Builder->CreateGEP(arrayType, var, + ArrayRef(indexList), "elem"); + store = Builder->CreateStore(elementValues[index], gep, false); } } //Add array to table of symbols. - tabelasym[allocblock][name] = new RobSymbol(var); + RobSymbol *rs = new RobSymbol(var); + rs->dt = tarray; + rs->pointee_dt = pointee_dt; + tabelasym[allocblock][name] = rs; return var; } diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 8b2590d..4d4ee34 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -46,7 +46,7 @@ Function *init; Function *print; Function *i16div; -void print_llvm_ir(const char *target, char opt_level) { +void print_llvm_ir(char opt_level) { InitializeAllTargetInfos(); InitializeAllTargets(); @@ -56,13 +56,7 @@ void print_llvm_ir(const char *target, char opt_level) { std::string defaultt = sys::getDefaultTargetTriple(); supportedTargets[0].triple = defaultt.c_str(); - TargetInfo ai = supportedTargets[0]; - for(int t = 0; t < (sizeof(supportedTargets)/sizeof(TargetInfo)); t++) { - if (strcmp(target, supportedTargets[t].name) == 0) { - ai = supportedTargets[t]; - break; - } - } + TargetInfo ai = supportedTargets[currentTarget]; std::string Error; auto Target = TargetRegistry::lookupTarget(ai.triple, Error); @@ -72,8 +66,9 @@ void print_llvm_ir(const char *target, char opt_level) { } TargetOptions opt; - auto RM = Optional(); - auto targetMachine = Target->createTargetMachine(ai.triple, ai.cpu, ai.features, opt, RM); + auto RM = optional(); + auto targetMachine = Target->createTargetMachine(ai.triple, + ai.cpu, ai.features, opt, RM); mainmodule->setDataLayout(targetMachine->createDataLayout()); mainmodule->setTargetTriple(ai.triple); diff --git a/src/Coercion.cpp b/src/Coercion.cpp index 9a28497..eb459b7 100644 --- a/src/Coercion.cpp +++ b/src/Coercion.cpp @@ -20,6 +20,9 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati Value *r = v; Type *ty = v->getType(); + + RobDbgInfo.emitLocation(loc); + Builder->SetInsertPoint(block); if (ty != destty){ //Float to Integer @@ -27,7 +30,7 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati if (Constant *c = dyn_cast(v)) r = ConstantExpr::getFPToSI(c, destty); else - r = new FPToSIInst(v, destty, "fptosi", block); + r = Builder->CreateFPToSI(v, destty, "fptosi"); yywarncpp("Float point converted to integer.", loc); } //Integer to Float @@ -35,7 +38,7 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati if (Constant *c = dyn_cast(v)) r = ConstantExpr::getSIToFP(c, destty); else - r = new SIToFPInst(v, destty, "sitofp", block); + r = Builder->CreateSIToFP(v, destty, "sitofp"); } //Floating point to Floating point else if (ty->isFloatingPointTy() && destty->isFloatingPointTy()) { @@ -45,12 +48,12 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati if (Constant *c = dyn_cast(v)) r = ConstantExpr::getFPExtend(c, destty); else - r = new FPExtInst(v, destty, "fpext", block); + r = Builder->CreateFPExt(v, destty, "fpext"); else if (dtybw < tybw) { if (Constant *c = dyn_cast(v)) r = ConstantExpr::getFPTrunc(c, destty); else - r = new FPTruncInst(v, destty, "fptrunc", block); + r = Builder->CreateFPTrunc(v, destty, "fptrunc"); yywarncpp("Float point value truncated.", loc); } } @@ -62,14 +65,14 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati if (Constant *c = dyn_cast(v)) r = ConstantExpr::getTrunc(c, destty); else - r = new TruncInst(v, destty, "trunc", block); + r = Builder->CreateTrunc(v, destty, "trunc"); yywarncpp("Integer value truncated.", loc); } else if (wty < wdestty) { if (Constant *c = dyn_cast(v)) r = ConstantExpr::getZExt(c, destty); else - r = new ZExtInst(v, destty, "zext", block); + r = Builder->CreateZExt(v, destty, "zext"); } } else if (!destty->isPointerTy()) { diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index 4371e0d..2c6a112 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -1,6 +1,8 @@ #include "Header.h" void DebugInfo::emitLocation(SourceLocation *s) { + if (!debug_info) + return; if (!s) return Builder->SetCurrentDebugLocation(DebugLoc()); DIScope *scope; @@ -23,10 +25,14 @@ void DebugInfo::pop_scope() { } DIFile* DebugInfo::currFile() { + if (!debug_info) + return NULL; return files.back(); } DIScope* DebugInfo::currScope() { + if (!debug_info) + return NULL; return scopes.back(); } diff --git a/src/Header.h b/src/Header.h index 899573f..350ec4b 100644 --- a/src/Header.h +++ b/src/Header.h @@ -37,7 +37,7 @@ using namespace llvm; /* After adding new types here, go to Program::generate to fill * the robTollvmDataType vector */ enum LanguageDataType {tvoid, tbool, tchar, tint8, tint16, tint32, tint64, - tint8u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, + tint8u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, tarray, __ldt_last}; static bool isIntegerDataType(LanguageDataType dt) { @@ -51,10 +51,10 @@ static bool isFloatDataType(LanguageDataType dt) { static const char *LanguageDataTypeNames[__ldt_last] = {"void", "boolean", "char", "int8", "int16", "int32", "int64", "unsigned int8", "unsigned int16", "unsigned int32", "unsigned int64", "float", - "double", "long double"}; + "double", "long double", "array"}; static const unsigned LanguageDataTypeBitWidth[__ldt_last] = {0, 1, 8, 8, - 16, 32, 64, 8, 16, 32, 64, 32, 64, 128}; + 16, 32, 64, 8, 16, 32, 64, 32, 64, 128, 0 /*use currentTarget->pointerSize*/}; static const unsigned LanguageDataTypeDwarfEnc[__ldt_last] = { dwarf::DW_ATE_address, @@ -62,7 +62,8 @@ static const unsigned LanguageDataTypeDwarfEnc[__ldt_last] = { dwarf::DW_ATE_unsigned_char, dwarf::DW_ATE_signed, dwarf::DW_ATE_signed, dwarf::DW_ATE_signed, dwarf::DW_ATE_signed, dwarf::DW_ATE_unsigned, dwarf::DW_ATE_unsigned, dwarf::DW_ATE_unsigned, dwarf::DW_ATE_unsigned, - dwarf::DW_ATE_float, dwarf::DW_ATE_float, dwarf::DW_ATE_float + dwarf::DW_ATE_float, dwarf::DW_ATE_float, dwarf::DW_ATE_float, + dwarf::DW_ATE_address }; enum DataQualifier {qnone, qconst, qvolatile}; @@ -151,13 +152,17 @@ typedef struct { const char *triple; const char *cpu; const char *features; + const uint8_t pointerSize; } TargetInfo; -static TargetInfo supportedTargets[] = { - {"", "", "", ""}, // default target - {"avr328p", "avr-atmel-none", "atmega328p", "+avr5"}, - {"stm32f1", "thumbv7m-none-eabi", "cortex-m3", ""}, - {"esp32", "xtensa", "", ""}, +enum SupportedTargets {native, avr328p, stm32f1, esp32, __last_target}; +extern enum SupportedTargets currentTarget; + +static TargetInfo supportedTargets[__last_target] = { + {"", "", "", "", 64}, // default target + {"avr328p", "avr-atmel-none", "atmega328p", "+avr5", 16}, + {"stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", 32}, + {"esp32", "xtensa", "", "", 32}, }; static string getTypeName(Type *ty) { diff --git a/src/Language.y b/src/Language.y index eeb032c..fee34ca 100644 --- a/src/Language.y +++ b/src/Language.y @@ -105,7 +105,7 @@ gstmt : TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($1, $3, qnone); } | complex_identifier '=' expr ';' { $$ = new Scalar($1, $3, qnone); } | TOK_CONST TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qconst); } | TOK_VOLATILE TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qvolatile); } - | TOK_IDENTIFIER '=' relements ';' { $$ = new Array($1, $3); } + | TOK_IDENTIFIER '=' relements ';' { $$ = new Array($1, $3); $$->setLocation(@1); } | TOK_IDENTIFIER '=' rmatrix ';' { $$ = new Matrix($1, $3);} | registerstmt { $$ = $1; } | fe { $$ = $1; } diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index 934f42d..aa130fb 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -4,7 +4,7 @@ LanguageDataType LoadArray::getResultType(BasicBlock *block, BasicBlock *allocbl if (!rsym) rsym = search_symbol(ident, allocblock, block); if (rsym) - return rsym->dt; + return rsym->pointee_dt; return tvoid; } diff --git a/src/Loop.cpp b/src/Loop.cpp index e43b9ea..13bbf26 100644 --- a/src/Loop.cpp +++ b/src/Loop.cpp @@ -17,9 +17,16 @@ Value *Loop::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) // alloc instructions inside bodyloop should go to allocblock to prevent repeatedly allocation Value *newb = stmts->generate(func, bodyloop, allocblock); - // return to loop at end - Builder->SetInsertPoint(bodyloop); - Builder->CreateBr(bodyloop); + // identify last while body block + BasicBlock *endbody = bodyloop; + if (newb->getValueID() == Value::BasicBlockVal) + endbody = (BasicBlock*)newb; + + // if end block already has a terminator, don't generate branch + if (!((BasicBlock*)endbody)->getTerminator()) { + Builder->SetInsertPoint(endbody); + Builder->CreateBr(bodyloop); + } BasicBlock *endloop = BasicBlock::Create(global_context, "loop_end", func, 0); return endloop; diff --git a/src/Program.cpp b/src/Program.cpp index f8a0af9..242d875 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -123,6 +123,10 @@ void Program::generate() { RobDbgInfo.cunit = DBuilder->createCompileUnit(dwarf::DW_LANG_C, DBuilder->createFile(build_filename, std::filesystem::current_path().string()), "Robcmp", false, "", 0); + + // global scope + RobDbgInfo.push_scope(RobDbgInfo.cunit->getFile(), RobDbgInfo.cunit); + for(int t = 0; t < __ldt_last; t++) { RobDbgInfo.types[t] = DBuilder->createBasicType( LanguageDataTypeNames[t], diff --git a/src/RobSymbol.h b/src/RobSymbol.h index 71a59d1..d33880c 100644 --- a/src/RobSymbol.h +++ b/src/RobSymbol.h @@ -10,12 +10,14 @@ class RobSymbol: public SourceLocation { unsigned int matrixCols; Structure *structure; LanguageDataType dt; + LanguageDataType pointee_dt; RobSymbol(Value *v, DataQualifier qualifier = qnone, Type *pointerType = NULL): value(v), qualifier(qualifier), pointerType(pointerType) { matrixLines = matrixCols = 0; structure = nullptr; dt = tvoid; + pointee_dt = tvoid; } }; diff --git a/src/Scalar.cpp b/src/Scalar.cpp index c5000f5..c3e1338 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -20,6 +20,7 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc auto symbol = search_symbol(id, allocblock, block); Field field; + // semantic validation of complexIdent if (complexIdent) { string idfield = complexIdent->names[1]; auto fieldit = symbol->structure->fields.find(idfield); @@ -44,6 +45,9 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc if (!exprv) return NULL; + auto sp = RobDbgInfo.currScope(); + auto funit = RobDbgInfo.currFile(); + if (allocblock == global_alloc) { Constant *exprvc = dyn_cast(exprv); if (exprvc == NULL) @@ -55,19 +59,24 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc GlobalVariable *gv = new GlobalVariable(*mainmodule, robTollvmDataType[dt], false, GlobalValue::CommonLinkage, exprvc, name); ret = leftv = gv; + + if (debug_info) { + auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", + funit, lineno, RobDbgInfo.types[dt], false); + gv->addDebugInfo(d); + } } } else { Builder->SetInsertPoint(allocblock); leftv = Builder->CreateAlloca(exprv->getType(), 0, name); Builder->SetInsertPoint(block); ret = Builder->CreateStore(exprv, leftv, qualifier == qvolatile); + if (debug_info) { - auto sp = RobDbgInfo.currScope(); - auto funit = RobDbgInfo.currFile(); DILocalVariable *d = DBuilder->createAutoVariable( sp, name, funit, lineno, RobDbgInfo.types[dt], true); DBuilder->insertDeclare(leftv, d, DBuilder->createExpression(), - DILocation::get(sp->getContext(), lineno, 0, sp), allocblock); + DILocation::get(sp->getContext(), lineno, colno, sp), allocblock); } } @@ -90,6 +99,8 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc Value *exprv = expr->generate(func, block, allocblock); Value *nvalue; + Builder->SetInsertPoint(block); + if (complexIdent) { /* this code does: * symbol->value &= ~(0x11... << field.startBit) @@ -108,23 +119,23 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc if (field.startBit > 0) { Constant *shiftl = ConstantInt::get(leftvty, field.startBit); ones = ConstantExpr::getShl(ones, shiftl); - exprv = BinaryOperator::CreateShl(exprv, shiftl, "shift", block); + exprv = Builder->CreateShl(exprv, shiftl, "shift"); } Constant *mask = ConstantExpr::getNot(ones); // Load pointer value Load ld(id); + ld.setLocation(expr); Value *leftv = ld.generate(func, block, allocblock); // Apply mask, than or - Value *vaftermask = BinaryOperator::CreateAnd(leftv, mask, "mask", block); - nvalue = BinaryOperator::CreateOr(vaftermask, exprv, "setbits", block); + Builder->SetInsertPoint(block); //caution, after generate! + Value *vaftermask = Builder->CreateAnd(leftv, mask, "mask"); + nvalue = Builder->CreateOr(vaftermask, exprv, "setbits"); } else { nvalue = Coercion::Convert(exprv, leftvty, block, expr); } - RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(block); return Builder->CreateStore(nvalue, symbol->value, qualifier == qvolatile); } } diff --git a/src/SourceLocation.h b/src/SourceLocation.h index 34829d0..4be6035 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -26,4 +26,9 @@ class SourceLocation { lineno = l.first_line; colno = l.first_column; } + + virtual void setLocation(SourceLocation *s) { + lineno = s->lineno; + colno = s->colno; + } }; diff --git a/src/main.cpp b/src/main.cpp index 043d1b5..49b8f08 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "Header.h" @@ -8,13 +9,14 @@ int yycolno = 0; int yycolnew = 0; extern int yyparse(); extern FILE *yyin; -void print_llvm_ir(const char *target, char opt_level); +void print_llvm_ir(char opt_level); Function *AttachInterrupt::fattach = NULL; // file name char *build_filename; char *build_outputfilename; bool debug_info; +enum SupportedTargets currentTarget; int main(int argc, char *argv[]) { @@ -59,6 +61,16 @@ int main(int argc, char *argv[]) { } i++; } + + // set current target + currentTarget = native; //native + for(int t = native; t < __last_target; t++) { + if (strcmp(targetarch, supportedTargets[t].name) == 0) { + currentTarget = static_cast(t); + break; + } + } + yyparse(); if (yyin) fclose(yyin); @@ -68,7 +80,7 @@ int main(int argc, char *argv[]) { return errorsfound; } - print_llvm_ir(targetarch, optimization); + print_llvm_ir(optimization); return 0; } From 41cfc5fd51089ec2f3b8495cc905da18237de550 Mon Sep 17 00:00:00 2001 From: Thiago Borges Date: Wed, 19 Jul 2023 12:19:01 -0300 Subject: [PATCH 021/117] simple debug .rob --- hack/debug/Makefile | 7 +++++++ hack/debug/main.rob | 20 ++++++++++++++++++++ src/BackLLVM.cpp | 2 +- src/Header.h | 3 ++- 4 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 hack/debug/Makefile create mode 100644 hack/debug/main.rob diff --git a/hack/debug/Makefile b/hack/debug/Makefile new file mode 100644 index 0000000..b2189cc --- /dev/null +++ b/hack/debug/Makefile @@ -0,0 +1,7 @@ +all: + robcmp -a avr328p -O0 -g main.rob > main.ll + robcmp -a avr328p -O0 -g main.rob -o main.o + @#ld -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem main.o -o main + @#avr-ld --target avr5 -Tdata=0x800100 main.o -o main.elf + avr-gcc -mmcu=atmega328p main.o -o main.elf + diff --git a/hack/debug/main.rob b/hack/debug/main.rob new file mode 100644 index 0000000..cdfc4c7 --- /dev/null +++ b/hack/debug/main.rob @@ -0,0 +1,20 @@ + +int16 wait(int32 qtd) { + volatile q = qtd; + while(q > 0) { + q--; + } +} + +int16 main() { + i = (int32)1; + loop { + wait(i*1000); + wait(i*10); + i++; + if (i > 5) { + i = 0; + } + } +} + diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 4d4ee34..537a3fe 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -66,7 +66,7 @@ void print_llvm_ir(char opt_level) { } TargetOptions opt; - auto RM = optional(); + auto RM = Optional(); auto targetMachine = Target->createTargetMachine(ai.triple, ai.cpu, ai.features, opt, RM); diff --git a/src/Header.h b/src/Header.h index 350ec4b..990d534 100644 --- a/src/Header.h +++ b/src/Header.h @@ -155,11 +155,12 @@ typedef struct { const uint8_t pointerSize; } TargetInfo; -enum SupportedTargets {native, avr328p, stm32f1, esp32, __last_target}; +enum SupportedTargets {native, avr48, avr328p, stm32f1, esp32, __last_target}; extern enum SupportedTargets currentTarget; static TargetInfo supportedTargets[__last_target] = { {"", "", "", "", 64}, // default target + {"avr48", "avr-atmel-none", "atmega48", "+avr4", 16}, {"avr328p", "avr-atmel-none", "atmega328p", "+avr5", 16}, {"stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", 32}, {"esp32", "xtensa", "", "", 32}, From 7d39a046b6bc79ea9c393f241d5007d2b22742cf Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 20 Jul 2023 14:37:45 -0300 Subject: [PATCH 022/117] Implement asm keyword (used in interruption tables) and fixes. --- .gitignore | 1 + hack/debug/Makefile | 42 ++++++++++++-- hack/debug/avr5.S | 112 +++++++++++++++++++++++++++++++++++++ hack/debug/avr5.ld | 91 ++++++++++++++++++++++++++++++ hack/debug/main.c | 50 +++++++++++++++++ hack/debug/main.rob | 87 +++++++++++++++++++++++++--- rob.vim | 2 +- src/BackLLVM.cpp | 4 +- src/CmpOp.cpp | 4 +- src/Coercion.cpp | 8 +-- src/FunctionCall.cpp | 6 +- src/FunctionDecl.cpp | 79 +++++++++++++++++--------- src/FunctionDecl.h | 4 +- src/FunctionDeclExtern.cpp | 11 +++- src/FunctionDeclExtern.h | 4 +- src/Header.h | 17 +++--- src/InlineAssembly.cpp | 18 ++++++ src/InlineAssembly.h | 12 ++++ src/Language.l | 1 + src/Language.y | 15 +++-- src/Load.cpp | 15 +---- src/Pointer.cpp | 15 +++-- src/Return.cpp | 5 +- src/RobSymbol.h | 9 ++- src/Scalar.cpp | 14 +++-- src/SourceLocation.h | 4 ++ src/main.cpp | 6 +- 27 files changed, 537 insertions(+), 99 deletions(-) create mode 100644 hack/debug/avr5.S create mode 100644 hack/debug/avr5.ld create mode 100644 hack/debug/main.c create mode 100644 src/InlineAssembly.cpp create mode 100644 src/InlineAssembly.h diff --git a/.gitignore b/.gitignore index 7740f2c..62c165f 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,4 @@ llvm-objcopy llvm-ranlib avr-ld .vscode +refdatasheets diff --git a/hack/debug/Makefile b/hack/debug/Makefile index b2189cc..03636d2 100644 --- a/hack/debug/Makefile +++ b/hack/debug/Makefile @@ -1,7 +1,39 @@ -all: - robcmp -a avr328p -O0 -g main.rob > main.ll - robcmp -a avr328p -O0 -g main.rob -o main.o +AVRDUDECFG=-C /Users/thborges/.platformio/packages/tool-avrdude/avrdude.conf +AVRDUDEPORT=`ls /dev/cu.usb*` + +#OPT=-O0 -g +OPT=-Os + +all: avr5.o main.o main.lld.elf main.lld.size main.avr.elf main.avr.size + +avr5.o: avr5.s + avr-gcc -mmcu=atmega328p -O3 -c avr5.S + +main.ll: main.rob + robcmp -a avr328p ${OPT} $< > $@ + +main.o: main.rob + robcmp -a avr328p ${OPT} $< -o $@ @#ld -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem main.o -o main - @#avr-ld --target avr5 -Tdata=0x800100 main.o -o main.elf - avr-gcc -mmcu=atmega328p main.o -o main.elf +main.c.o: main.c + avr-gcc ${OPT} -mmcu=atmega328p -c $< -o $@ + +main.avr.elf: main.c.o + avr-gcc -Wl,--gc-sections ${OPT} -mmcu=atmega328p $< -o $@ + +main.lld.elf: main.o avr5.o + @#clang-16 -v -fuse-ld=lld -e main -target avr -mmcu=atmega328p main.o -o main.elf + ld.lld --gc-sections -o $@ -Tavr5.ld -Tdata=0x800100 -e main ${LOPT} main.o avr5.o + +%.hex : %.elf + avr-objcopy -Oihex $< $@ + +%.up: %.hex + avrdude ${AVRDUDECFG} -v -V -c arduino -p m328p -U flash:w:$<:i -P ${AVRDUDEPORT} + +%.size: %.elf + avr-size $< + +clean: + rm -f *.o *.elf *.ll *.hex diff --git a/hack/debug/avr5.S b/hack/debug/avr5.S new file mode 100644 index 0000000..d0013a1 --- /dev/null +++ b/hack/debug/avr5.S @@ -0,0 +1,112 @@ +/* + * Code excerpt from libgcc + * vim: syntax=nasm + */ + +#define A0 26 +#define B0 18 +#define C0 22 + +#define A1 A0+1 + +#define B1 B0+1 +#define B2 B0+2 +#define B3 B0+3 + +#define C1 C0+1 +#define C2 C0+2 +#define C3 C0+3 + +#define __zero_reg__ r1 +#define __tmp_reg__ r0 + + +.macro DEFUN name +.global \name +.func \name +\name: +.endm + + +.macro ENDF name +.size \name, .-\name +.endfunc +.endm + + +.macro wmov r_dest, r_src + movw \r_dest, \r_src +.endm + + +;;; R25:R22 = (unsigned long) R27:R26 * (unsigned long) R19:R18 +;;; C3:C0 = (unsigned long) A1:A0 * (unsigned long) B1:B0 +;;; Clobbers: __tmp_reg__ +DEFUN __umulhisi3 + mul A0, B0 + movw C0, r0 + mul A1, B1 + movw C2, r0 + mul A0, B1 +;;#ifdef __AVR_HAVE_JMP_CALL__ + ;; This function is used by many other routines, often multiple times. + ;; Therefore, if the flash size is not too limited, avoid the RCALL + ;; and inverst 6 Bytes to speed things up. + add C1, r0 + adc C2, r1 + clr __zero_reg__ + adc C3, __zero_reg__ +;;#else +;; rcall 1f +;;#endif + mul A1, B0 +1: add C1, r0 + adc C2, r1 + clr __zero_reg__ + adc C3, __zero_reg__ + ret +ENDF __umulhisi3 + + +;;; R25:R22 = (unsigned long) R27:R26 * R21:R18 +;;; (C3:C0) = (unsigned long) A1:A0 * B3:B0 +;;; Clobbers: __tmp_reg__ +DEFUN __muluhisi3 + call __umulhisi3 + mul A0, B3 + add C3, r0 + mul A1, B2 + add C3, r0 + mul A0, B2 + add C2, r0 + adc C3, r1 + clr __zero_reg__ + ret +ENDF __muluhisi3 + +/******************************************************* + Multiplication 32 x 32 with MUL +*******************************************************/ + +;;; R25:R22 = R25:R22 * R21:R18 +;;; (C3:C0) = C3:C0 * B3:B0 +;;; Clobbers: R26, R27, __tmp_reg__ +DEFUN __mulsi3 + movw A0, C0 + push C2 + push C3 + call __muluhisi3 + pop A1 + pop A0 + ;; A1:A0 now contains the high word of A + mul A0, B0 + add C2, r0 + adc C3, r1 + mul A0, B1 + add C3, r0 + mul A1, B0 + add C3, r0 + clr __zero_reg__ + ret +ENDF __mulsi3 + diff --git a/hack/debug/avr5.ld b/hack/debug/avr5.ld new file mode 100644 index 0000000..2ab2d07 --- /dev/null +++ b/hack/debug/avr5.ld @@ -0,0 +1,91 @@ +/* Default linker script, for normal executables */ +/* Copyright (C) 2014 Free Software Foundation, Inc. + Copying and distribution of this script, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. */ + +OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") + +OUTPUT_ARCH(avr:5) + +MEMORY +{ + text (rx) : ORIGIN = 0, LENGTH = 128K + data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0 + eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K + fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K + lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K + signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K + user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = 1K +} + +SECTIONS +{ + .text : { + _start__vectors = .; + KEEP(*(.vectors)) + . = 106; /* should be 104, but llvm requires a return at the end of __vectors*/ + _end_vectors = .; + . = ALIGN(2); + _stext = .; + *(.progmem*) + . = ALIGN(2); + *(.text) + . = ALIGN(2); + *(.text.*) + _etext = . ; + } > text + + .data : { + PROVIDE (__data_start = .) ; + *(.data) + *(.data*) + *(.rodata) /* We need to include .rodata here if gcc is used */ + *(.rodata*) /* with -fdata-sections. */ + . = ALIGN(2); + _edata = . ; + PROVIDE (__data_end = .) ; + } > data AT> text + + .bss ADDR(.data) + SIZEOF (.data) : AT (ADDR (.bss)) { + PROVIDE (__bss_start = .) ; + *(.bss) + *(.bss*) + *(COMMON) + PROVIDE (__bss_end = .) ; + } > data + + __data_load_start = LOADADDR(.data); + __data_load_end = __data_load_start + SIZEOF(.data); + + /* Global data not cleared after reset. */ + .eeprom : { + KEEP(*(.eeprom*)) + __eeprom_end = . ; + } > eeprom + + .fuse : { + KEEP(*(.fuse)) + KEEP(*(.lfuse)) + KEEP(*(.hfuse)) + KEEP(*(.efuse)) + } > fuse + + .lock : { + KEEP(*(.lock*)) + } > lock + + .signature : { + KEEP(*(.signature*)) + } > signature + + .user_signatures : { + KEEP(*(.user_signatures*)) + } > user_signatures + + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } +} diff --git a/hack/debug/main.c b/hack/debug/main.c new file mode 100644 index 0000000..380d185 --- /dev/null +++ b/hack/debug/main.c @@ -0,0 +1,50 @@ + +typedef struct { + char pin8 : 1; + char pin9 : 1; + char pin10 : 1; + char pin11 : 1; + char pin12 : 1; + char pin13 : 1; + char others : 2; +} ddrb_t; + + +typedef struct { + char pin8 : 1; + char pin9 : 1; + char pin10 : 1; + char pin11 : 1; + char pin12 : 1; + char pin13 : 1; + char others : 2; +} portb_t; + + +void wait(long qtd) { + volatile long q = qtd; + while(q > 0) { + q--; + } +} + +void main() { + volatile ddrb_t *ddrb = (ddrb_t*)0x24; + volatile portb_t *portb = (portb_t*)0x25; + + ddrb->pin13 = 1; //output + char i = 10; + for(;;) { + // blink + portb->pin13 = 0; + wait(i*100000); + portb->pin13 = 1; + wait(i*100000); + + i--; + if (i == 0) { + i = 10; + } + } +} + diff --git a/hack/debug/main.rob b/hack/debug/main.rob index cdfc4c7..5944faa 100644 --- a/hack/debug/main.rob +++ b/hack/debug/main.rob @@ -1,19 +1,90 @@ -int16 wait(int32 qtd) { +void main(); +void __init(); +void __bad_irq(); + +void __vectors() { + /* atmega328p has 26 interruptions */ + asm "jmp __init"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; +} + +void __bad_irq() { + __vectors(); +} + +register int8 SREG at 0x3f; +register int16 STACK at 0x3d; + +void __init() { + SREG = 0; + STACK = 0x0AFF; + main(); + loop { asm "nop"; } +} + +register int8 ddrb at 0x24 { + bool pin8; + bool pin9; + bool pin10; + bool pin11; + bool pin12; + bool pin13; +} + +register int8 portb at 0x25 { + bool pin8; + bool pin9; + bool pin10; + bool pin11; + bool pin12; + bool pin13; +} + +void wait(int32 qtd) { volatile q = qtd; while(q > 0) { q--; } } -int16 main() { - i = (int32)1; +void main() { + ddrb.pin13 = true; //output + i = 10; loop { - wait(i*1000); - wait(i*10); - i++; - if (i > 5) { - i = 0; + // blink + portb.pin13 = false; + wait(i*100000); + portb.pin13 = true; + wait(i*100000); + + i--; + if (i == 0) { + i = 10; } } } diff --git a/rob.vim b/rob.vim index deff6d8..f528282 100644 --- a/rob.vim +++ b/rob.vim @@ -7,7 +7,7 @@ if exists("b:current_syntax") finish endif -syn keyword keywords while loop if delay print return register at volatile const +syn keyword keywords while loop if delay print return register at volatile const asm syn keyword typeKeywords void char int8 int16 int32 int64 long unsigned float double bool syn keyword operatorKeywords and or quando esta servo syn keyword booleanKeyword true false diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 537a3fe..6e144cd 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -56,7 +56,7 @@ void print_llvm_ir(char opt_level) { std::string defaultt = sys::getDefaultTargetTriple(); supportedTargets[0].triple = defaultt.c_str(); - TargetInfo ai = supportedTargets[currentTarget]; + TargetInfo ai = currentTarget; std::string Error; auto Target = TargetRegistry::lookupTarget(ai.triple, Error); @@ -66,7 +66,7 @@ void print_llvm_ir(char opt_level) { } TargetOptions opt; - auto RM = Optional(); + auto RM = optional(); auto targetMachine = Target->createTargetMachine(ai.triple, ai.cpu, ai.features, opt, RM); diff --git a/src/CmpOp.cpp b/src/CmpOp.cpp index 47a1c93..99ef633 100644 --- a/src/CmpOp.cpp +++ b/src/CmpOp.cpp @@ -38,8 +38,8 @@ Value *CmpOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock else { // left and right are integers isFloatPointCmp = false; - unsigned tlbw = dyn_cast(tl)->getBitWidth(); - unsigned trbw = dyn_cast(tr)->getBitWidth(); + unsigned tlbw = tl->getIntegerBitWidth(); + unsigned trbw = tr->getIntegerBitWidth(); if (tlbw > trbw) rexp = Coercion::Convert(rexp, tl, block, rexpn); else if (tlbw < trbw) diff --git a/src/Coercion.cpp b/src/Coercion.cpp index eb459b7..6f6154c 100644 --- a/src/Coercion.cpp +++ b/src/Coercion.cpp @@ -59,8 +59,8 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati } //Generic ExtInt to Int else if (destty->isIntegerTy() && ty->isIntegerTy()){ - unsigned wty = dyn_cast(ty)->getBitWidth(); - unsigned wdestty = dyn_cast(destty)->getBitWidth(); + unsigned wty = ty->getIntegerBitWidth(); + unsigned wdestty = destty->getIntegerBitWidth(); if (wty > wdestty){ if (Constant *c = dyn_cast(v)) r = ConstantExpr::getTrunc(c, destty); @@ -70,9 +70,9 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati } else if (wty < wdestty) { if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getZExt(c, destty); + r = ConstantExpr::getSExt(c, destty); else - r = Builder->CreateZExt(v, destty, "zext"); + r = Builder->CreateSExt(v, destty, "sext"); } } else if (!destty->isPointerTy()) { diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 03fbc0d..753066b 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -21,15 +21,17 @@ Value *FunctionCall::generate(Function *func, BasicBlock *block, BasicBlock *all return NULL; } - vector args; + vector args; for (int i = 0; i < parameters->getNumParams(); i++){ Value *valor = parameters->getParamElement(i)->generate(func, block, allocblock); + Type *pty = robTollvmDataType[symbol->params->getParamType(i)]; + valor = Coercion::Convert(valor, pty, block, this); args.push_back(valor); } ArrayRef argsRef(args); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); - return Builder->CreateCall(cfunc, argsRef, "fc"); + return Builder->CreateCall(cfunc, argsRef); } diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 391d9c6..85051c3 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -2,32 +2,61 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) { auto sym = search_symbol(name); - if (sym != NULL) { + if (sym != NULL && !sym->isDeclaration) { yyerrorcpp("Function/symbol " + name + " already defined.", this); yyerrorcpp(name + " was first defined here.", sym); return NULL; } - std::vector arg_types; - if (parameters->getNumParams() != 0) - for (int i = 0; i < parameters->getNumParams(); i++) - arg_types.push_back(robTollvmDataType[parameters->getParamType(i)]); - + Function *nfunc; Type *xtype = robTollvmDataType[tipo]; - FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); + if (sym && sym->isDeclaration) { + if (sym->params->getNumParams() != parameters->getNumParams()) { + yyerrorcpp("The number of function parameters differs between its declaration and definition.", this); + yyerrorcpp("The function declarations is here.", sym); + return NULL; + } + for(int i = 0; i < sym->params->getNumParams(); i++) { + FunctionParam &p = sym->params->parameters[i]; + if (p.type != parameters->parameters[i].type) { + yyerrorcpp(string_format("Parameter %s has distinct types in declaration '%s' and definition '%s'.", + LanguageDataTypeNames[p.type], LanguageDataTypeNames[parameters->parameters[i].type]), this); + yyerrorcpp("The function declarations is here.", sym); + } + } + if (tipo != sym->dt) { + yyerrorcpp(string_format("Function return type has distinct types in declaration '%s' and definition '%s'.", + LanguageDataTypeNames[sym->dt], LanguageDataTypeNames[tipo]), this); + yyerrorcpp("The function declarations is here.", sym); + } + nfunc = mainmodule->getFunction(name); + } else { + std::vector arg_types; + if (parameters->getNumParams() != 0) + for (int i = 0; i < parameters->getNumParams(); i++) + arg_types.push_back(robTollvmDataType[parameters->getParamType(i)]); + + FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); + nfunc = Function::Create(ftype, Function::ExternalLinkage, 1, name, mainmodule); + } - Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, 0, name, mainmodule); nfunc->setDSOLocal(true); llvm::AttrBuilder attrs(global_context); - attrs.addAttribute(llvm::Attribute::MinSize); - //attrs.addAttribute("stack-protector-buffer-size", llvm::utostr(8)); - //attrs.addAttribute("frame-pointer", "all"); - //attrs.addAttribute("no-trapping-math", "true"); + attrs.addAttribute(Attribute::MinSize); + + if (name == "__vectors") { // FIXME: remove after adding functions attributes to language + nfunc->setSection(".vectors"); + } + nfunc->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); + nfunc->setCallingConv(CallingConv::C); - RobSymbol *rs = new RobSymbol(nfunc); - rs->dt = tipo; - tabelasym[allocblock][name] = rs; + if (!sym) + sym = new RobSymbol(nfunc); + sym->dt = tipo; + sym->params = parameters; + sym->isDeclaration = false; + tabelasym[allocblock][name] = sym; DIFile *funit; DISubprogram *sp; @@ -38,12 +67,14 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) getFunctionDIType(), this->lineno, DINode::FlagPrototyped, DISubprogram::SPFlagDefinition); nfunc->setSubprogram(sp); RobDbgInfo.push_scope(funit, sp); - RobDbgInfo.emitLocation(nullptr); } BasicBlock *falloc = BasicBlock::Create(global_context, "entry", nfunc); BasicBlock *fblock = BasicBlock::Create(global_context, "body", nfunc); + + RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(falloc); + unsigned Idx = 0; for (auto &Arg : nfunc->args()) { @@ -51,7 +82,7 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) LanguageDataType ptype = parameters->getParamType(Idx); Arg.setName(argname); - AllocaInst* variable = Builder->CreateAlloca(robTollvmDataType[ptype], 0, argname ); + AllocaInst* variable = Builder->CreateAlloca(robTollvmDataType[ptype], 0, argname); RobSymbol *rs = new RobSymbol(variable); rs->dt = ptype; tabelasym[falloc][argname] = rs; @@ -67,11 +98,8 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) Idx++; } - nfunc->setCallingConv(CallingConv::C); - - if (debug_info) - RobDbgInfo.emitLocation(stmts); + RobDbgInfo.emitLocation(stmts); Value *last_block = stmts->generate(nfunc, fblock, falloc); if (!last_block) last_block = fblock; @@ -79,13 +107,14 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) // prevent mallformed block at the end without proper return instruction if (last_block && last_block->getValueID() == Value::BasicBlockVal) { BasicBlock *lb = (BasicBlock*)last_block; + Builder->SetInsertPoint(lb); + RobDbgInfo.emitLocation(&endfunction); if (lb->getTerminator() == NULL) { if (!xtype->isVoidTy()) { - Value *ret = ConstantInt::get(Type::getInt8Ty(global_context), 0); - ret = Coercion::Convert(ret, xtype, lb, this); - ReturnInst::Create(global_context, ret, lb); + Value *ret = ConstantInt::get(xtype, 0); + Builder->CreateRet(ret); } else - ReturnInst::Create(global_context, NULL, lb); + Builder->CreateRetVoid(); } } diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index f3c53f1..a494f41 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -9,12 +9,14 @@ class FunctionDecl: public Node { LanguageDataType tipo; string name; FunctionParams *parameters; + SourceLocation endfunction; public: - FunctionDecl(LanguageDataType tipo, string name, FunctionParams *fp, Node *stmts){ + FunctionDecl(LanguageDataType tipo, string name, FunctionParams *fp, Node *stmts, SourceLocation ef){ this->tipo = tipo; this->stmts = stmts; this->name = name; this->parameters = fp; + this->endfunction = ef; } bool isFunctionDecl() { diff --git a/src/FunctionDeclExtern.cpp b/src/FunctionDeclExtern.cpp index fd852c8..e290542 100644 --- a/src/FunctionDeclExtern.cpp +++ b/src/FunctionDeclExtern.cpp @@ -15,9 +15,16 @@ Value *FunctionDeclExtern::generate(Function *, BasicBlock *, BasicBlock *allocb Type *xtype = robTollvmDataType[tipo]; FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, 0, name, mainmodule); + Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, 1, name, mainmodule); + nfunc->setDSOLocal(true); nfunc->setCallingConv(CallingConv::C); - tabelasym[allocblock][name] = new RobSymbol(nfunc); + + RobSymbol *rs = new RobSymbol(nfunc); + rs->params = parameters; + rs->setLocation(this); + rs->isDeclaration = true; + rs->dt = tipo; + tabelasym[allocblock][name] = rs; return nfunc; } diff --git a/src/FunctionDeclExtern.h b/src/FunctionDeclExtern.h index f97aadc..80500f0 100644 --- a/src/FunctionDeclExtern.h +++ b/src/FunctionDeclExtern.h @@ -5,11 +5,11 @@ class FunctionDeclExtern: public Node { private: - int tipo; + LanguageDataType tipo; string name; FunctionParams *parameters; public: - FunctionDeclExtern(int tipo, string name, FunctionParams *fp){ + FunctionDeclExtern(LanguageDataType tipo, string name, FunctionParams *fp){ this->tipo = tipo; this->name = name; this->parameters = fp; diff --git a/src/Header.h b/src/Header.h index 990d534..40b20c1 100644 --- a/src/Header.h +++ b/src/Header.h @@ -152,18 +152,18 @@ typedef struct { const char *triple; const char *cpu; const char *features; - const uint8_t pointerSize; + const LanguageDataType pointerType; } TargetInfo; -enum SupportedTargets {native, avr48, avr328p, stm32f1, esp32, __last_target}; -extern enum SupportedTargets currentTarget; +enum SupportedTargets {native, avr328p, stm32f1, esp32, __last_target}; +extern enum SupportedTargets currentTargetId; +#define currentTarget (supportedTargets[currentTargetId]) static TargetInfo supportedTargets[__last_target] = { - {"", "", "", "", 64}, // default target - {"avr48", "avr-atmel-none", "atmega48", "+avr4", 16}, - {"avr328p", "avr-atmel-none", "atmega328p", "+avr5", 16}, - {"stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", 32}, - {"esp32", "xtensa", "", "", 32}, + {"", "", "", "", tint64}, // default target + {"avr328p", "avr-atmel-none", "atmega328p", "+avr5", tint16}, + {"stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, + {"esp32", "xtensa", "", "", tint32}, }; static string getTypeName(Type *ty) { @@ -261,6 +261,7 @@ string string_format(const char *format, Args ... args) { #include "Pointer.h" #include "FlipOp.h" #include "Cast.h" +#include "InlineAssembly.h" #include "Visitor.h" #include "RecursiveVisitor.h" diff --git a/src/InlineAssembly.cpp b/src/InlineAssembly.cpp new file mode 100644 index 0000000..ace9a97 --- /dev/null +++ b/src/InlineAssembly.cpp @@ -0,0 +1,18 @@ +#include "Header.h" + +Value *InlineAssembly::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + Type *voidty = robTollvmDataType[tvoid]; + std::vector arg_types; + FunctionType *ftype = FunctionType::get(voidty, ArrayRef(arg_types), false); + InlineAsm *asmcall = InlineAsm::get(ftype, assembly, "", false, false, InlineAsm::AD_ATT); + Error err = asmcall->verify(ftype, ""); + if (err) { + std::string error_message; + raw_string_ostream OS(error_message); + OS << err; + yyerrorcpp(error_message, this); + } + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateCall(ftype, asmcall, std::nullopt); +} diff --git a/src/InlineAssembly.h b/src/InlineAssembly.h new file mode 100644 index 0000000..98242a4 --- /dev/null +++ b/src/InlineAssembly.h @@ -0,0 +1,12 @@ + +#pragma once + +#include "Header.h" + +class InlineAssembly: public Node { +private: + string assembly; +public: + InlineAssembly(const char *a): assembly(a) { } + Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); +}; diff --git a/src/Language.l b/src/Language.l index bd58a77..550e2b5 100644 --- a/src/Language.l +++ b/src/Language.l @@ -51,6 +51,7 @@ static void update_loc() { "true" { return TOK_TRUE; } "false" { return TOK_FALSE; } "at" { return TOK_AT; } +"asm" { return TOK_ASM; } "if" { return TOK_IF; } "else" { return TOK_ELSE; } diff --git a/src/Language.y b/src/Language.y index fee34ca..28b85ba 100644 --- a/src/Language.y +++ b/src/Language.y @@ -15,7 +15,7 @@ extern int errorsfound; %define api.location.type {location_t} %define parse.error verbose -%token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST +%token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST TOK_ASM %token TOK_IF TOK_ELSE %token TOK_LOOP TOK_WHILE %token TOK_PRINT @@ -68,7 +68,7 @@ extern int errorsfound; %type TOK_DOUBLE %type TOK_LDOUBLE %type TOK_IDENTIFIER -%type TOK_STRING +%type TOK_STRING asminline %type TOK_STEPPER %type
type_f registertype %type struct_field @@ -121,18 +121,18 @@ funcblock : type_f TOK_IDENTIFIER '(' funcparams ')' ';' { $$ = new FunctionDeclExtern($1, $2, $4); $$->setLocation(@type_f); } - | type_f TOK_IDENTIFIER '(' funcparams ')' '{' stmts '}' { - $$ = new FunctionDecl($1, $2, $4, $7); + | type_f TOK_IDENTIFIER '(' funcparams ')' '{' stmts '}'[ef] { + $$ = new FunctionDecl($1, $2, $4, $7, @ef); $$->setLocation(@type_f); } ; -eventblock : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}' { +eventblock : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { char funcname[100]; snprintf(funcname, 100, "__callback_int_p%d_e%d", (int)$2, (int)$4); vectorglobal.push_back(new AttachInterrupt($2, funcname, $4)); FunctionParams *fps = new FunctionParams(); - $$ = new FunctionDecl(tvoid, funcname, fps, $6); + $$ = new FunctionDecl(tvoid, funcname, fps, $6, @ef); } ; @@ -157,6 +157,7 @@ stmt : gstmt { $$ = $1; } | whileblock { $$ = $1; } | returnblock ';' { $$ = $1; } | printstmt ';' { $$ = $1; } + | asminline ';' { $$ = new InlineAssembly($1); $$->setLocation(@1); } | TOK_STEPPER expr ';' { $$ = new StepperGoto($1, $2); } | TOK_SERVO expr ';' { $$ = new ServoGoto($2); } | TOK_IDENTIFIER '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6);} @@ -391,6 +392,8 @@ struct_field : type_f TOK_IDENTIFIER ';' { } ; +asminline : TOK_ASM TOK_STRING { $$ = $2; } + ; %% extern char *build_filename; diff --git a/src/Load.cpp b/src/Load.cpp index fa5e400..5ea9216 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -26,21 +26,12 @@ Value* Load::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) return NULL; } } - - Type *ty; - bool vol = rsym->qualifier == qvolatile; - if (auto *lvalue = dyn_cast(sym)) - ty = lvalue->getAllocatedType(); - else if (auto *lvalue = dyn_cast(sym)) - ty = lvalue->getValueType(); - else if (rsym->pointerType != NULL) - ty = rsym->pointerType; - else { - printf("ERR: Going to return NULL!\n"); - } RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); + + bool vol = rsym->qualifier == qvolatile; + Type *ty = robTollvmDataType[rsym->dt]; return Builder->CreateLoad(ty, sym, vol, ident); } diff --git a/src/Pointer.cpp b/src/Pointer.cpp index a68c7cc..c51b1b0 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -11,23 +11,26 @@ Value *Pointer::generate(Function *func, BasicBlock *block, BasicBlock *allocblo } // generate code to produce the address - Value *addri = address->generate(func, block, allocblock); - if (addri == NULL) { + Value *addr = address->generate(func, block, allocblock); + if (addr == NULL) { yyerrorcpp("Unable to compute the address for '" + name + "' register.", this); return NULL; } + Type *targetPointerType = robTollvmDataType[currentTarget.pointerType]; Value *addrp = NULL; - if (Constant *addrc = dyn_cast(addri)) - addrp = ConstantExpr::getIntToPtr(addrc, Type::getInt64PtrTy(global_context)); // FIXME: What is the method to get an opaque pointer type? + if (Constant *addrc = dyn_cast(addr)) + addrp = ConstantExpr::getIntToPtr(addrc, targetPointerType); else - addrp = new IntToPtrInst(addri, Type::getInt64PtrTy(global_context), name, allocblock); + addrp = new IntToPtrInst(addr, targetPointerType, name, allocblock); Type *ty = robTollvmDataType[type]; DataQualifier vol = isVolatile ? qvolatile : qnone; - RobSymbol *rs = new RobSymbol(addrp, vol, ty); + RobSymbol *rs = new RobSymbol(addrp, vol); rs->structure = structure; + rs->setLocation(this); + rs->dt = type; tabelasym[allocblock][name] = rs; return addrp; diff --git a/src/Return.cpp b/src/Return.cpp index 2f4c2b0..8ebe556 100644 --- a/src/Return.cpp +++ b/src/Return.cpp @@ -1,9 +1,10 @@ #include "Header.h" Value *Return::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - IRBuilder<> builder(block); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); Value *ret = node->generate(func, block, allocblock); Type *retty = func->getReturnType(); ret = Coercion::Convert(ret, retty, block, this); - return builder.CreateRet(ret); + return Builder->CreateRet(ret); } diff --git a/src/RobSymbol.h b/src/RobSymbol.h index d33880c..58bc49f 100644 --- a/src/RobSymbol.h +++ b/src/RobSymbol.h @@ -4,20 +4,23 @@ class RobSymbol: public SourceLocation { public: Value* value; - Type* pointerType; DataQualifier qualifier; unsigned int matrixLines; unsigned int matrixCols; Structure *structure; LanguageDataType dt; LanguageDataType pointee_dt; + FunctionParams *params; + bool isDeclaration; - RobSymbol(Value *v, DataQualifier qualifier = qnone, Type *pointerType = NULL): - value(v), qualifier(qualifier), pointerType(pointerType) { + RobSymbol(Value *v, DataQualifier qualifier = qnone): + value(v), qualifier(qualifier) { matrixLines = matrixCols = 0; structure = nullptr; dt = tvoid; pointee_dt = tvoid; + params = nullptr; + isDeclaration = false; } }; diff --git a/src/Scalar.cpp b/src/Scalar.cpp index c3e1338..d53faba 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -68,13 +68,19 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc } } else { Builder->SetInsertPoint(allocblock); - leftv = Builder->CreateAlloca(exprv->getType(), 0, name); + AllocaInst *newvar = Builder->CreateAlloca(exprv->getType(), 0, name); + newvar->setAlignment(Align(1)); + leftv = newvar; Builder->SetInsertPoint(block); ret = Builder->CreateStore(exprv, leftv, qualifier == qvolatile); if (debug_info) { + llvm::DIType *dty = RobDbgInfo.types[dt]; + if (qualifier == qvolatile) { + dty = DBuilder->createQualifiedType(dwarf::DW_TAG_volatile_type, dty); + } DILocalVariable *d = DBuilder->createAutoVariable( - sp, name, funit, lineno, RobDbgInfo.types[dt], true); + sp, name, funit, lineno, dty, true); DBuilder->insertDeclare(leftv, d, DBuilder->createExpression(), DILocation::get(sp->getContext(), lineno, colno, sp), allocblock); } @@ -92,10 +98,8 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc return NULL; } - Type *leftvty = symbol->value->getType(); + Type *leftvty = robTollvmDataType[symbol->dt]; qualifier = symbol->qualifier; - if (symbol->pointerType) - leftvty = symbol->pointerType; Value *exprv = expr->generate(func, block, allocblock); Value *nvalue; diff --git a/src/SourceLocation.h b/src/SourceLocation.h index 4be6035..bf0cca8 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -14,6 +14,10 @@ class SourceLocation { colno = yycolno; } + SourceLocation(location_t l) { + setLocation(l); + } + virtual int getLineNo() { return lineno; } diff --git a/src/main.cpp b/src/main.cpp index 49b8f08..90ce54c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,7 +16,7 @@ Function *AttachInterrupt::fattach = NULL; char *build_filename; char *build_outputfilename; bool debug_info; -enum SupportedTargets currentTarget; +enum SupportedTargets currentTargetId; int main(int argc, char *argv[]) { @@ -63,10 +63,10 @@ int main(int argc, char *argv[]) { } // set current target - currentTarget = native; //native + currentTargetId = native; //native for(int t = native; t < __last_target; t++) { if (strcmp(targetarch, supportedTargets[t].name) == 0) { - currentTarget = static_cast(t); + currentTargetId = static_cast(t); break; } } From 80587c55d0747d5913a700bf0ee555d47b498a01 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 20 Jul 2023 16:30:44 -0300 Subject: [PATCH 023/117] Update platformio toolchain and add a semantic check for wrong number of parameters in function calls --- hack/debug/Makefile | 2 +- lib/Makefile | 9 ++ lib/avr328p.ld | 19 +++ lib/avr328p.rob | 56 +++++++++ lib/avr5.S | 112 ++++++++++++++++++ {hack/debug => lib}/avr5.ld | 22 +--- .../share/stm32f1.lld.ld => lib/stm32f1.ld | 0 platformio/platform/builder/main.py | 30 +++-- platformio/samples/avr328p-blink/src/main.rob | 24 ++-- platformio/toolchain-robcmp/Makefile | 14 ++- src/FunctionCall.cpp | 7 ++ src/FunctionDecl.cpp | 6 +- 12 files changed, 255 insertions(+), 46 deletions(-) create mode 100644 lib/Makefile create mode 100644 lib/avr328p.ld create mode 100644 lib/avr328p.rob create mode 100644 lib/avr5.S rename {hack/debug => lib}/avr5.ld (65%) rename platformio/toolchain-robcmp/share/stm32f1.lld.ld => lib/stm32f1.ld (100%) diff --git a/hack/debug/Makefile b/hack/debug/Makefile index 03636d2..a2f81c1 100644 --- a/hack/debug/Makefile +++ b/hack/debug/Makefile @@ -24,7 +24,7 @@ main.avr.elf: main.c.o main.lld.elf: main.o avr5.o @#clang-16 -v -fuse-ld=lld -e main -target avr -mmcu=atmega328p main.o -o main.elf - ld.lld --gc-sections -o $@ -Tavr5.ld -Tdata=0x800100 -e main ${LOPT} main.o avr5.o + ld.lld --gc-sections -o $@ -L../../share/avr/ -Tavr328p.ld -Tdata=0x800100 -e main ${LOPT} main.o avr5.o %.hex : %.elf avr-objcopy -Oihex $< $@ diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..0d18991 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,9 @@ + +all: avr5.o + +avr5.o: avr5.s + @#here we are interested in the fastest possible code, intead of size + avr-gcc -mmcu=avr5 -O3 -c avr5.S + +clean: + rm -f avr5.o diff --git a/lib/avr328p.ld b/lib/avr328p.ld new file mode 100644 index 0000000..71cd8ae --- /dev/null +++ b/lib/avr328p.ld @@ -0,0 +1,19 @@ +/* + * RobCmp linker script for atmega328p + */ + +MEMORY +{ + text (rx) : ORIGIN = 0, LENGTH = 128K + data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0 + eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K + fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K + lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K + signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K + user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = 1K +} + +__vectors_size = 106; /* should be 104, but llvm ir requires a return at the end of __vectors*/ + +INCLUDE avr5.ld + diff --git a/lib/avr328p.rob b/lib/avr328p.rob new file mode 100644 index 0000000..6f0cf38 --- /dev/null +++ b/lib/avr328p.rob @@ -0,0 +1,56 @@ +/* + * Robcmp interruptions vector for atmega328p + */ + +void main(); +void __init(); +void __bad_irq(); + +void __vectors() { + /* atmega328p has 26 interruptions */ + /* FIXME: provide proper interrupt functions instead of __bad_irq after implementing "weak" attribute for functions */ + asm "jmp __init"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; + asm "jmp __bad_irq"; +} + +void __bad_irq() { + // reset + __vectors(); +} + +register int8 SREG at 0x3f; +register int16 STACK at 0x3d; + +void __init() { + // clear SREG, set STACK at RAM top and call main + // if main returns, reset. + SREG = 0; + STACK = 0x0AFF; + main(); + __vectors(); +} + diff --git a/lib/avr5.S b/lib/avr5.S new file mode 100644 index 0000000..d0013a1 --- /dev/null +++ b/lib/avr5.S @@ -0,0 +1,112 @@ +/* + * Code excerpt from libgcc + * vim: syntax=nasm + */ + +#define A0 26 +#define B0 18 +#define C0 22 + +#define A1 A0+1 + +#define B1 B0+1 +#define B2 B0+2 +#define B3 B0+3 + +#define C1 C0+1 +#define C2 C0+2 +#define C3 C0+3 + +#define __zero_reg__ r1 +#define __tmp_reg__ r0 + + +.macro DEFUN name +.global \name +.func \name +\name: +.endm + + +.macro ENDF name +.size \name, .-\name +.endfunc +.endm + + +.macro wmov r_dest, r_src + movw \r_dest, \r_src +.endm + + +;;; R25:R22 = (unsigned long) R27:R26 * (unsigned long) R19:R18 +;;; C3:C0 = (unsigned long) A1:A0 * (unsigned long) B1:B0 +;;; Clobbers: __tmp_reg__ +DEFUN __umulhisi3 + mul A0, B0 + movw C0, r0 + mul A1, B1 + movw C2, r0 + mul A0, B1 +;;#ifdef __AVR_HAVE_JMP_CALL__ + ;; This function is used by many other routines, often multiple times. + ;; Therefore, if the flash size is not too limited, avoid the RCALL + ;; and inverst 6 Bytes to speed things up. + add C1, r0 + adc C2, r1 + clr __zero_reg__ + adc C3, __zero_reg__ +;;#else +;; rcall 1f +;;#endif + mul A1, B0 +1: add C1, r0 + adc C2, r1 + clr __zero_reg__ + adc C3, __zero_reg__ + ret +ENDF __umulhisi3 + + +;;; R25:R22 = (unsigned long) R27:R26 * R21:R18 +;;; (C3:C0) = (unsigned long) A1:A0 * B3:B0 +;;; Clobbers: __tmp_reg__ +DEFUN __muluhisi3 + call __umulhisi3 + mul A0, B3 + add C3, r0 + mul A1, B2 + add C3, r0 + mul A0, B2 + add C2, r0 + adc C3, r1 + clr __zero_reg__ + ret +ENDF __muluhisi3 + +/******************************************************* + Multiplication 32 x 32 with MUL +*******************************************************/ + +;;; R25:R22 = R25:R22 * R21:R18 +;;; (C3:C0) = C3:C0 * B3:B0 +;;; Clobbers: R26, R27, __tmp_reg__ +DEFUN __mulsi3 + movw A0, C0 + push C2 + push C3 + call __muluhisi3 + pop A1 + pop A0 + ;; A1:A0 now contains the high word of A + mul A0, B0 + add C2, r0 + adc C3, r1 + mul A0, B1 + add C3, r0 + mul A1, B0 + add C3, r0 + clr __zero_reg__ + ret +ENDF __mulsi3 + diff --git a/hack/debug/avr5.ld b/lib/avr5.ld similarity index 65% rename from hack/debug/avr5.ld rename to lib/avr5.ld index 2ab2d07..3b16305 100644 --- a/hack/debug/avr5.ld +++ b/lib/avr5.ld @@ -1,30 +1,16 @@ -/* Default linker script, for normal executables */ -/* Copyright (C) 2014 Free Software Foundation, Inc. - Copying and distribution of this script, with or without modification, - are permitted in any medium without royalty provided the copyright - notice and this notice are preserved. */ +/* + * RobCmp linker script for avr5 familly + */ OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") - OUTPUT_ARCH(avr:5) -MEMORY -{ - text (rx) : ORIGIN = 0, LENGTH = 128K - data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0 - eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K - fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K - lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K - signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K - user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = 1K -} - SECTIONS { .text : { _start__vectors = .; KEEP(*(.vectors)) - . = 106; /* should be 104, but llvm requires a return at the end of __vectors*/ + . = __vectors_size; _end_vectors = .; . = ALIGN(2); _stext = .; diff --git a/platformio/toolchain-robcmp/share/stm32f1.lld.ld b/lib/stm32f1.ld similarity index 100% rename from platformio/toolchain-robcmp/share/stm32f1.lld.ld rename to lib/stm32f1.ld diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index e6b8925..06668ee 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -9,23 +9,27 @@ env = DefaultEnvironment() platform = env.PioPlatform() -ldscripts_folder = platform.get_package_dir("toolchain-robcmp") +ldscripts_folder = join(platform.get_package_dir("toolchain-robcmp"), "lib") -os.environ['LD_LIBRARY_PATH'] = join(ldscripts_folder, "lib") +os.environ['LD_LIBRARY_PATH'] = ldscripts_folder # Needed by debug env.Replace( PROGNAME="firmware.elf" ) +sources = [] + board = env.subst("$BOARD") mcu = env.subst("$BOARD_MCU") +ldflags = ["-nostdlib", "-entry=main", "-L", ldscripts_folder, "-Bstatic"] if mcu == "stm32f1": - ld = "ld.lld" - ldflags = ["-nostdlib", "-entry=main", "-T" + ldscripts_folder + "/share/stm32f1.lld.ld", "-Bstatic"] + ldflags.append("-Tstm32f1.ld") elif mcu == "atmega328p": - ld = "avr-ld" - ldflags = ["-Tdata=0x800100"] + ldflags.append("-Tavr328p.ld") + ldflags.append("-Tdata=0x800100") + ldflags.append(join(ldscripts_folder, "avr5.o")) + sources += Glob(join(ldscripts_folder, "avr328p.rob")) else: sys.stderr.write("The requested mcu is not supported.\n") env.Exit(1) @@ -47,7 +51,7 @@ suffix=".bin" ), Linker=Builder( - action = ' '.join([ld, "$SOURCES", ' '.join(ldflags), "-o", "$TARGET"]), + action = ' '.join(["ld.lld", "$SOURCES", ' '.join(ldflags), "-o", "$TARGET"]), suffix=".elf" ), Rob=Builder( @@ -58,7 +62,7 @@ ) ) -sources = Glob(env.subst(join("$PROJECT_DIR/src/", "*.rob"))) +sources += Glob(env.subst(join("$PROJECT_DIR/src/", "*.rob"))) #source_fnames = [join("$PROJECT_DIR/src/", f.name) for f in sources] #print("SOURCES: ", source_fnames) @@ -121,4 +125,14 @@ upload = env.Alias(["upload"], target_bin, upload_actions) AlwaysBuild(upload) +# SIZE +target_size = env.AddPlatformTarget( + "size", + target_elf, + env.VerboseAction("llvm-size -d $SOURCES", "Calculating size $SOURCE"), + "Program Size", + "Calculate program size", +) + +env.Depends(target_bin, "size") Default(target_bin) diff --git a/platformio/samples/avr328p-blink/src/main.rob b/platformio/samples/avr328p-blink/src/main.rob index a17cd14..4e2a8fb 100644 --- a/platformio/samples/avr328p-blink/src/main.rob +++ b/platformio/samples/avr328p-blink/src/main.rob @@ -21,10 +21,10 @@ register int8 ddrb at 0x24 { bool pin13; } -void wait(); +void wait(int32 q); int16 main() { - arr = {10000, 5000, 3000, 2000, 1000, 500}; + arr = {1000000, 500000, 300000, 200000, 100000, 50000}; /* pin 13 is controlled by bit 5 of DDRB and PORTB registers * - bit 5 of DDRB indicates if the pin is input (0) or output (1) @@ -34,22 +34,22 @@ int16 main() { // set pin 13 as output ddrb.pin13 = true; - w = 0; - t = 10; + i = 0; + t = 5; loop { - // set bit 5 high portb.pin13 = true; - wait(arr[w]); - // set bit 5 low + wait(arr[i]); + portb.pin13 = false; - wait(arr[w]); + wait(arr[i]); t--; if (t == 0) { - w++; - } - if (w > 5) { - w = 0; + t = 5; + i++; + if (i == 6) { + i = 0; + } } } } diff --git a/platformio/toolchain-robcmp/Makefile b/platformio/toolchain-robcmp/Makefile index eadbb65..b355ded 100644 --- a/platformio/toolchain-robcmp/Makefile +++ b/platformio/toolchain-robcmp/Makefile @@ -8,9 +8,9 @@ ifeq ($(LLVM_LD),) LLVM_LD=$(shell which ld.lld) endif -AVR_LD=$(shell which avr-ld) -ifeq ($(AVR_LD),) - $(error "Can't find avr-ld!") +LLVM_SIZE=$(shell which llvm-size-16) +ifeq ($(LLVM_SIZE),) + LLVM_SIZE=$(shell which llvm-size) endif ifeq ($(LLVM_LD),) @@ -21,7 +21,11 @@ ifeq ($(LLVM_OBJCOPY),) $(error "Can't find llvm-objcopy!") endif -TOOLS=$(LLVM_OBJCOPY) $(LLVM_LD) $(AVR_LD) ../../robcmp +ifeq ($(LLVM_SIZE),) + $(error "Can't find llvm-size!") +endif + +TOOLS=$(LLVM_OBJCOPY) $(LLVM_LD) $(LLVM_SIZE) ../../robcmp ifeq ($(OS),Windows_NT) uname_S := Windows @@ -39,6 +43,8 @@ ifeq ($(uname_S), Linux) LIBS=$(shell ./libllvmpath.sh ${LLVM_LD}) endif +LIBS += ../../lib/*.ld ../../lib/*.o ../../lib/*.rob + version=$(shell cat version) all: bin lib ../toolchain-robcmp-${suffix}-${version}.tar.gz diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 753066b..5b97d77 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -21,6 +21,13 @@ Value *FunctionCall::generate(Function *func, BasicBlock *block, BasicBlock *all return NULL; } + if (symbol->params->getNumParams() != parameters->getNumParams()) { + yyerrorcpp(string_format("Function %s has %d parameter(s) but was called with %d.", + name.c_str(), symbol->params->getNumParams(), parameters->getNumParams()), this); + yyerrorcpp("The function declaration is here.", symbol); + return NULL; + } + vector args; for (int i = 0; i < parameters->getNumParams(); i++){ Value *valor = parameters->getParamElement(i)->generate(func, block, allocblock); diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 85051c3..aa2d412 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -13,7 +13,7 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) if (sym && sym->isDeclaration) { if (sym->params->getNumParams() != parameters->getNumParams()) { yyerrorcpp("The number of function parameters differs between its declaration and definition.", this); - yyerrorcpp("The function declarations is here.", sym); + yyerrorcpp("The function declaration is here.", sym); return NULL; } for(int i = 0; i < sym->params->getNumParams(); i++) { @@ -21,13 +21,13 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) if (p.type != parameters->parameters[i].type) { yyerrorcpp(string_format("Parameter %s has distinct types in declaration '%s' and definition '%s'.", LanguageDataTypeNames[p.type], LanguageDataTypeNames[parameters->parameters[i].type]), this); - yyerrorcpp("The function declarations is here.", sym); + yyerrorcpp("The function declaration is here.", sym); } } if (tipo != sym->dt) { yyerrorcpp(string_format("Function return type has distinct types in declaration '%s' and definition '%s'.", LanguageDataTypeNames[sym->dt], LanguageDataTypeNames[tipo]), this); - yyerrorcpp("The function declarations is here.", sym); + yyerrorcpp("The function declaration is here.", sym); } nfunc = mainmodule->getFunction(name); } else { From b1520707ad67a9ecba404af628a91078376ab7dd Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Fri, 21 Jul 2023 11:51:52 -0300 Subject: [PATCH 024/117] Implements complex identifiers in Load and other fixes. Forces if and else to have blocks. --- lib/avr5.S | 214 +++++++++++++++++++++++++++++++++++++++++++ src/BackLLVM.cpp | 8 +- src/Cast.cpp | 2 +- src/Coercion.cpp | 11 ++- src/Coercion.h | 3 +- src/FunctionCall.cpp | 2 +- src/FunctionDecl.cpp | 6 +- src/Language.y | 31 +++++-- src/Load.cpp | 43 ++++++++- src/Load.h | 4 +- src/Scalar.cpp | 2 +- src/Stmts.h | 1 + src/main.cpp | 2 +- 13 files changed, 301 insertions(+), 28 deletions(-) diff --git a/lib/avr5.S b/lib/avr5.S index d0013a1..fb82ec0 100644 --- a/lib/avr5.S +++ b/lib/avr5.S @@ -33,6 +33,13 @@ .endfunc .endm +.macro mov_l r_dest, r_src +movw \r_dest, \r_src +.endm + +.macro mov_h r_dest, r_src +; empty +.endm .macro wmov r_dest, r_src movw \r_dest, \r_src @@ -110,3 +117,210 @@ DEFUN __mulsi3 ret ENDF __mulsi3 +.macro NEG4 reg + com \reg+3 + com \reg+2 + com \reg+1 +.if \reg >= 16 + neg \reg + sbci \reg+1, -1 + sbci \reg+2, -1 + sbci \reg+3, -1 +.else + com \reg + adc \reg, __zero_reg__ + adc \reg+1, __zero_reg__ + adc \reg+2, __zero_reg__ + adc \reg+3, __zero_reg__ +.endif +.endm + +/******************************************************* + Division 32 / 32 => (result + remainder) +*******************************************************/ +#define r_remHH r31 /* remainder High */ +#define r_remHL r30 +#define r_remH r27 +#define r_remL r26 /* remainder Low */ + +/* return: remainder */ +#define r_arg1HH r25 /* dividend High */ +#define r_arg1HL r24 +#define r_arg1H r23 +#define r_arg1L r22 /* dividend Low */ + +/* return: quotient */ +#define r_arg2HH r21 /* divisor High */ +#define r_arg2HL r20 +#define r_arg2H r19 +#define r_arg2L r18 /* divisor Low */ + +#define r_cnt __zero_reg__ /* loop count (0 after the loop!) */ + +DEFUN __udivmodsi4 + ldi r_remL, 33 ; init loop counter + mov r_cnt, r_remL + sub r_remL,r_remL + sub r_remH,r_remH ; clear remainder and carry + mov_l r_remHL, r_remL + mov_h r_remHH, r_remH + rjmp __udivmodsi4_ep ; jump to entry point +__udivmodsi4_loop: + rol r_remL ; shift dividend into remainder + rol r_remH + rol r_remHL + rol r_remHH + cp r_remL,r_arg2L ; compare remainder & divisor + cpc r_remH,r_arg2H + cpc r_remHL,r_arg2HL + cpc r_remHH,r_arg2HH + brcs __udivmodsi4_ep ; remainder <= divisor + sub r_remL,r_arg2L ; restore remainder + sbc r_remH,r_arg2H + sbc r_remHL,r_arg2HL + sbc r_remHH,r_arg2HH +__udivmodsi4_ep: + rol r_arg1L ; shift dividend (with CARRY) + rol r_arg1H + rol r_arg1HL + rol r_arg1HH + dec r_cnt ; decrement loop counter + brne __udivmodsi4_loop + ; __zero_reg__ now restored (r_cnt == 0) + com r_arg1L + com r_arg1H + com r_arg1HL + com r_arg1HH +; div/mod results to return registers, as for the ldiv() function + mov_l r_arg2L, r_arg1L ; quotient + mov_h r_arg2H, r_arg1H + mov_l r_arg2HL, r_arg1HL + mov_h r_arg2HH, r_arg1HH + mov_l r_arg1L, r_remL ; remainder + mov_h r_arg1H, r_remH + mov_l r_arg1HL, r_remHL + mov_h r_arg1HH, r_remHH + ret +ENDF __udivmodsi4 + + +DEFUN __negsi2 + NEG4 22 + ret +ENDF __negsi2 + + +DEFUN __divmodsi4 + mov __tmp_reg__,r_arg2HH + bst r_arg1HH,7 ; store sign of dividend + brtc 0f + com __tmp_reg__ ; r0.7 is sign of result + call __negsi2 ; dividend negative: negate +0: + sbrc r_arg2HH,7 + rcall __divmodsi4_neg2 ; divisor negative: negate + call __udivmodsi4 ; do the unsigned div/mod + sbrc __tmp_reg__, 7 ; correct quotient sign + rcall __divmodsi4_neg2 + brtc __divmodsi4_exit ; correct remainder sign + jmp __negsi2 +__divmodsi4_neg2: + ;; correct divisor/quotient sign + com r_arg2HH + com r_arg2HL + com r_arg2H + neg r_arg2L + sbci r_arg2H,0xff + sbci r_arg2HL,0xff + sbci r_arg2HH,0xff +__divmodsi4_exit: + ret +ENDF __divmodsi4 + +#undef r_remHH +#undef r_remHL +#undef r_remH +#undef r_remL +#undef r_arg1HH +#undef r_arg1HL +#undef r_arg1H +#undef r_arg1L +#undef r_arg2HH +#undef r_arg2HL +#undef r_arg2H +#undef r_arg2L +#undef r_cnt + +/******************************************************* + Division 16 / 16 => (result + remainder) +*******************************************************/ +#define r_remL r26 /* remainder Low */ +#define r_remH r27 /* remainder High */ + +/* return: remainder */ +#define r_arg1L r24 /* dividend Low */ +#define r_arg1H r25 /* dividend High */ + +/* return: quotient */ +#define r_arg2L r22 /* divisor Low */ +#define r_arg2H r23 /* divisor High */ + +#define r_cnt r21 /* loop count */ + +DEFUN __udivmodhi4 + sub r_remL,r_remL + sub r_remH,r_remH ; clear remainder and carry + ldi r_cnt,17 ; init loop counter + rjmp __udivmodhi4_ep ; jump to entry point +__udivmodhi4_loop: + rol r_remL ; shift dividend into remainder + rol r_remH + cp r_remL,r_arg2L ; compare remainder & divisor + cpc r_remH,r_arg2H + brcs __udivmodhi4_ep ; remainder < divisor + sub r_remL,r_arg2L ; restore remainder + sbc r_remH,r_arg2H +__udivmodhi4_ep: + rol r_arg1L ; shift dividend (with CARRY) + rol r_arg1H + dec r_cnt ; decrement loop counter + brne __udivmodhi4_loop + com r_arg1L + com r_arg1H +; div/mod results to return registers, as for the div() function + mov_l r_arg2L, r_arg1L ; quotient + mov_h r_arg2H, r_arg1H + mov_l r_arg1L, r_remL ; remainder + mov_h r_arg1H, r_remH + ret +ENDF __udivmodhi4 + +DEFUN __divmodhi4 + .global _div +_div: + bst r_arg1H,7 ; store sign of dividend + mov __tmp_reg__,r_arg2H + brtc 0f + com __tmp_reg__ ; r0.7 is sign of result + rcall __divmodhi4_neg1 ; dividend negative: negate +0: + sbrc r_arg2H,7 + rcall __divmodhi4_neg2 ; divisor negative: negate + call __udivmodhi4 ; do the unsigned div/mod + sbrc __tmp_reg__,7 + rcall __divmodhi4_neg2 ; correct remainder sign + brtc __divmodhi4_exit +__divmodhi4_neg1: + ;; correct dividend/remainder sign + com r_arg1H + neg r_arg1L + sbci r_arg1H,0xff + ret +__divmodhi4_neg2: + ;; correct divisor/result sign + com r_arg2H + neg r_arg2L + sbci r_arg2H,0xff +__divmodhi4_exit: + ret +ENDF __divmodhi4 diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 6e144cd..9028941 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -97,8 +97,12 @@ void print_llvm_ir(char opt_level) { default : ol = OptimizationLevel::Oz; break; } - ModulePassManager modulePassManager = - passBuilder.buildPerModuleDefaultPipeline(ol); + ModulePassManager modulePassManager; + if (ol == OptimizationLevel::O0) + modulePassManager = passBuilder.buildO0DefaultPipeline(ol); + else + modulePassManager = passBuilder.buildPerModuleDefaultPipeline(ol); + modulePassManager.run(*mainmodule, moduleAnalysisManager); if (build_outputfilename) { diff --git a/src/Cast.cpp b/src/Cast.cpp index 1aa8f95..311e158 100644 --- a/src/Cast.cpp +++ b/src/Cast.cpp @@ -12,7 +12,7 @@ Value *Cast::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) return NULL; Type *destty = robTollvmDataType[dt]; - Value *ret = Coercion::Convert(exprv, destty, block, expr); + Value *ret = Coercion::Convert(exprv, destty, block, expr, true); if (ret == NULL) { yyerrorcpp("Can't cast from '" + getTypeName(exprv->getType()) + "' to '" + diff --git a/src/Coercion.cpp b/src/Coercion.cpp index 6f6154c..0c47f36 100644 --- a/src/Coercion.cpp +++ b/src/Coercion.cpp @@ -16,7 +16,7 @@ unsigned Coercion::GetFloatingPointBitwidth(Type *ty) { } } -Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocation *loc){ +Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocation *loc, bool isCast){ Value *r = v; Type *ty = v->getType(); @@ -31,7 +31,8 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati r = ConstantExpr::getFPToSI(c, destty); else r = Builder->CreateFPToSI(v, destty, "fptosi"); - yywarncpp("Float point converted to integer.", loc); + if (!isCast) + yywarncpp("Float point converted to integer.", loc); } //Integer to Float else if (destty->isFloatingPointTy() && ty->isIntegerTy()){ @@ -54,7 +55,8 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati r = ConstantExpr::getFPTrunc(c, destty); else r = Builder->CreateFPTrunc(v, destty, "fptrunc"); - yywarncpp("Float point value truncated.", loc); + if (!isCast) + yywarncpp("Float point value truncated.", loc); } } //Generic ExtInt to Int @@ -66,7 +68,8 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati r = ConstantExpr::getTrunc(c, destty); else r = Builder->CreateTrunc(v, destty, "trunc"); - yywarncpp("Integer value truncated.", loc); + if (!isCast) + yywarncpp("Integer value truncated.", loc); } else if (wty < wdestty) { if (Constant *c = dyn_cast(v)) diff --git a/src/Coercion.h b/src/Coercion.h index 6fe4674..38920bd 100644 --- a/src/Coercion.h +++ b/src/Coercion.h @@ -3,7 +3,8 @@ class Coercion{ public: - static Value *Convert(Value *v, Type *destty, BasicBlock *block, SourceLocation *loc); + static Value *Convert(Value *v, Type *destty, BasicBlock *block, SourceLocation *loc, + bool isCast = false); static unsigned GetFloatingPointBitwidth(Type *ty); }; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 5b97d77..eeb7020 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -22,7 +22,7 @@ Value *FunctionCall::generate(Function *func, BasicBlock *block, BasicBlock *all } if (symbol->params->getNumParams() != parameters->getNumParams()) { - yyerrorcpp(string_format("Function %s has %d parameter(s) but was called with %d.", + yyerrorcpp(string_format("Function %s has %d argument(s) but was called with %d.", name.c_str(), symbol->params->getNumParams(), parameters->getNumParams()), this); yyerrorcpp("The function declaration is here.", symbol); return NULL; diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index aa2d412..08898ee 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -12,20 +12,20 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) Type *xtype = robTollvmDataType[tipo]; if (sym && sym->isDeclaration) { if (sym->params->getNumParams() != parameters->getNumParams()) { - yyerrorcpp("The number of function parameters differs between its declaration and definition.", this); + yyerrorcpp("The number of function arguments differs between its declaration and definition.", this); yyerrorcpp("The function declaration is here.", sym); return NULL; } for(int i = 0; i < sym->params->getNumParams(); i++) { FunctionParam &p = sym->params->parameters[i]; if (p.type != parameters->parameters[i].type) { - yyerrorcpp(string_format("Parameter %s has distinct types in declaration '%s' and definition '%s'.", + yyerrorcpp(string_format("Argument %s has distinct type in declaration '%s' and definition '%s'.", LanguageDataTypeNames[p.type], LanguageDataTypeNames[parameters->parameters[i].type]), this); yyerrorcpp("The function declaration is here.", sym); } } if (tipo != sym->dt) { - yyerrorcpp(string_format("Function return type has distinct types in declaration '%s' and definition '%s'.", + yyerrorcpp(string_format("Function return type has distinct type in declaration '%s' and definition '%s'.", LanguageDataTypeNames[sym->dt], LanguageDataTypeNames[tipo]), this); yyerrorcpp("The function declaration is here.", sym); } diff --git a/src/Language.y b/src/Language.y index 28b85ba..bff872b 100644 --- a/src/Language.y +++ b/src/Language.y @@ -76,8 +76,6 @@ extern int errorsfound; %type complex_identifier %type error -%precedence IFX -%precedence TOK_ELSE %start programa %% @@ -255,21 +253,36 @@ returnblock : TOK_RETURN expr { $$ = new Return($2); } | TOK_RETURN logicexpr { $$ = new Return($2); } ; -condblock : TOK_IF '(' logicexpr ')' stmt %prec IFX { $$ = new If($3, $5, NULL); } - | TOK_IF '(' logicexpr ')' stmt elseblock { $$ = new If($3, $5, $6); } - | TOK_IF '(' logicexpr ')' '{' stmts '}' %prec IFX { $$ = new If($3, $6, NULL); } - | TOK_IF '(' logicexpr ')' '{' stmts '}' elseblock { $$ = new If($3, $6, $8); } +condblock : TOK_IF logicexpr '{' stmts '}' { + $logicexpr->setLocation(@logicexpr); + $stmts->setLocation(@stmts); + $$ = new If($logicexpr, $stmts, NULL); + $$->setLocation(@TOK_IF); + } + | TOK_IF logicexpr '{' stmts '}' elseblock { + $logicexpr->setLocation(@logicexpr); + $stmts->setLocation(@stmts); + $$ = new If($logicexpr, $stmts, $elseblock); + $$->setLocation(@TOK_IF); + } ; -elseblock : TOK_ELSE stmt { $$ = $2; } - | TOK_ELSE '{' stmts '}' { $$ = $3; } +elseblock : TOK_ELSE '{' stmts '}' { + $$ = $stmts; + $$->setLocation(@stmts); + } ; -whileblock : TOK_WHILE '(' logicexpr ')' '{' stmts '}' { +whileblock : TOK_WHILE logicexpr '{' stmts '}' { $logicexpr->setLocation(@logicexpr); $$ = new While($logicexpr, $stmts); $$->setLocation(@TOK_WHILE); } + | TOK_WHILE logicexpr ';' { + $logicexpr->setLocation(@logicexpr); + $$ = new While($logicexpr, new Stmts()); + $$->setLocation(@TOK_WHILE); + } | TOK_LOOP '{' stmts '}' { $$ = new Loop($stmts); $$->setLocation(@TOK_LOOP); diff --git a/src/Load.cpp b/src/Load.cpp index 5ea9216..234995e 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -2,8 +2,15 @@ LanguageDataType Load::getResultType(BasicBlock *block, BasicBlock *allocblock) { auto rsym = search_symbol(ident, allocblock, block); - if (rsym) - return rsym->dt; + if (rsym) { + if (complexIdent) { + auto it = rsym->structure->fields.find(complexIdent->names[1]); + if (it != rsym->structure->fields.end()) { + return it->second.fieldDataType; + } + } else + return rsym->dt; + } return tvoid; } @@ -13,6 +20,19 @@ Value* Load::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) yyerrorcpp("Variable " + ident + " not defined.", this); return NULL; } + Field field; + + // semantic validation of complexIdent + if (complexIdent) { + string idfield = complexIdent->names[1]; + auto fieldit = rsym->structure->fields.find(idfield); + if (fieldit == rsym->structure->fields.end()) { + yyerrorcpp("Field " + idfield + " not declared in " + ident, this); + return NULL; + } else { + field = fieldit->second; + } + } auto sym = rsym->value; if (rsym->qualifier == qconst) @@ -29,10 +49,25 @@ Value* Load::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); - + bool vol = rsym->qualifier == qvolatile; Type *ty = robTollvmDataType[rsym->dt]; - return Builder->CreateLoad(ty, sym, vol, ident); + Value *v = Builder->CreateLoad(ty, sym, vol, ident); + + if (complexIdent) { + /* this code does: + * v = symbol->value << pointerbits - field_start - field_width + * v = v >> pointer_bits - field_width + */ + int bs = LanguageDataTypeBitWidth[rsym->dt] - field.bitWidth; + if (bs - field.startBit > 0) + v = Builder->CreateShl(v, ConstantInt::get(ty, bs - field.startBit)); + if (bs > 0) + v = Builder->CreateAShr(v, ConstantInt::get(ty, bs)); + v = Builder->CreateTrunc(v, robTollvmDataType[field.fieldDataType]); + } + + return v; } void Load::accept(Visitor &v) { diff --git a/src/Load.h b/src/Load.h index 2788bc8..de59afa 100644 --- a/src/Load.h +++ b/src/Load.h @@ -8,7 +8,9 @@ class Load: public Node { ComplexIdentifier *complexIdent; public: Load(const string i): ident(i), complexIdent(nullptr) {} - Load(ComplexIdentifier *ci): complexIdent(ci) {} + Load(ComplexIdentifier *ci): complexIdent(ci) { + this->ident = complexIdent->names[0]; + } virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; diff --git a/src/Scalar.cpp b/src/Scalar.cpp index d53faba..941e49e 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -29,7 +29,7 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc yyerrorcpp("Symbol " + id + " must be defined first.", this); return NULL; } else if (fieldit == symbol->structure->fields.end()) { - yyerrorcpp("Symbol " + id + "." + idfield + " not declared.", this); + yyerrorcpp("Field " + idfield + " not declared in " + id, this); return NULL; } else { field = fieldit->second; diff --git a/src/Stmts.h b/src/Stmts.h index 433ff8e..f7a1ac0 100644 --- a/src/Stmts.h +++ b/src/Stmts.h @@ -6,6 +6,7 @@ class Stmts: public Node { private: std::vector stmts; public: + Stmts() {}; Stmts(Node *s); virtual std::vector const& children() const override; diff --git a/src/main.cpp b/src/main.cpp index 90ce54c..213399a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) { int i = 1; while (i < argc) { if (strncmp(argv[i], "-O", 2) == 0) { - if (strlen(argv[1]) > 2) + if (strlen(argv[i]) > 2) optimization = argv[i][2]; } else if (strncmp(argv[i], "-a", 2) == 0) { From 23c87ebf1d16cb3130a96411a96b859478cda014 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 22 Jul 2023 00:10:08 -0300 Subject: [PATCH 025/117] One parser (flex) and two scanners (bison) working together. Will process the use (#include) keyword. --- .gitignore | 6 +- Makefile | 17 +- hack/debug/main.c | 4 +- platformio/samples/avr328p-blink/src/main.rob | 8 + .../syntaxes/rob.tmLanguage.json | 11 +- src/Array.cpp | 10 +- src/ArrayElements.cpp | 8 +- src/ArrayElements.h | 2 +- src/AttachInterrupt.h | 2 + src/BackLLVM.cpp | 6 +- src/BinaryOp.cpp | 15 +- src/BinaryOp.h | 2 +- src/BuildTypes.h | 101 ++++++++++ src/Cast.cpp | 6 +- src/Cast.h | 6 +- src/CmpOp.cpp | 1 + src/DebugInfo.cpp | 2 + src/Double.h | 2 +- src/Field.h | 2 +- src/FlipOp.h | 2 +- src/Float.h | 2 +- src/Float128.h | 2 +- src/FunctionCall.cpp | 4 +- src/FunctionCall.h | 2 +- src/FunctionDecl.cpp | 133 ++----------- src/FunctionDecl.h | 29 +-- src/FunctionDeclExtern.cpp | 31 --- src/FunctionDeclExtern.h | 27 --- src/FunctionImpl.cpp | 149 ++++++++++++++ src/FunctionImpl.h | 36 ++++ src/FunctionParams.cpp | 2 +- src/FunctionParams.h | 2 +- src/Header.h | 150 +++++--------- src/InlineAssembly.cpp | 2 +- src/Int1.h | 2 +- src/Int16.h | 2 +- src/Int32.h | 2 +- src/Int64.h | 2 +- src/Int8.h | 2 +- src/Interface.cpp | 29 +++ src/Interface.h | 15 ++ src/Language.l | 58 +++--- src/Language.y | 143 ++++++-------- src/LanguageHeader.y | 59 ++++++ src/LanguageUse.y | 184 ++++++++++++++++++ src/Load.cpp | 8 +- src/Load.h | 2 +- src/LoadArray.cpp | 2 +- src/LoadArray.h | 2 +- src/Matrix.cpp | 2 +- src/MatrixElements.cpp | 8 +- src/MatrixElements.h | 2 +- src/Node.h | 78 +++++++- src/Pointer.cpp | 4 +- src/Pointer.h | 10 +- src/PrintAstVisitor.cpp | 1 + src/Program.cpp | 33 +--- src/Program.h | 14 +- src/RobSymbol.h | 4 +- src/Scalar.cpp | 16 +- src/Scanner.cpp | 67 +++++++ src/Scanner.h | 28 +++ src/SourceLocation.h | 30 +-- src/Stmts.cpp | 52 +++-- src/Stmts.h | 14 +- src/UserType.cpp | 22 +++ src/UserType.h | 19 ++ src/main.cpp | 31 +-- 68 files changed, 1132 insertions(+), 599 deletions(-) create mode 100644 src/BuildTypes.h delete mode 100644 src/FunctionDeclExtern.cpp delete mode 100644 src/FunctionDeclExtern.h create mode 100644 src/FunctionImpl.cpp create mode 100644 src/FunctionImpl.h create mode 100644 src/Interface.cpp create mode 100644 src/Interface.h create mode 100644 src/LanguageHeader.y create mode 100644 src/LanguageUse.y create mode 100644 src/Scanner.cpp create mode 100644 src/Scanner.h create mode 100644 src/UserType.cpp create mode 100644 src/UserType.h diff --git a/.gitignore b/.gitignore index 62c165f..3eab1e2 100644 --- a/.gitignore +++ b/.gitignore @@ -43,9 +43,11 @@ # Generated robcmp -bison.hpp run_test/out/* -src/Language_y.output +src/*_y.output +src/*_gen_*.* +src/*_gen.y +src/*_l.cpp .vscode/** *.tar.gz *.bin diff --git a/Makefile b/Makefile index bb89aec..2a20751 100644 --- a/Makefile +++ b/Makefile @@ -30,17 +30,25 @@ BIN = . #FLAGS=-O3 -march=native -flto DFLAGS=-ggdb -O0 -std=c++17 +SCANNERS=src/Language_gen.y src/LanguageUse_gen.y CPPS=$(patsubst src/%.cpp,src/out/%.o,$(wildcard ${SRC}/*.cpp)) -YACS=$(patsubst src/%.y,src/out/%_y.o,$(wildcard ${SRC}/*.y)) +YACS=$(patsubst src/%.y,src/out/%_y.o,$(SCANNERS)) LEXS=$(patsubst src/%.l,src/out/%_l.o,$(wildcard ${SRC}/*.l)) all: src/out $(COMPILER_NAME) %_l.cpp: %.l - lex -o $@ $< + flex -o $@ $< + +.PRECIOUS : %_l.cpp %_y.cpp %_y.hpp + +main.cpp : %_l.cpp %_y.cpp %_y.hpp + +%_gen.y : src/LanguageHeader.y %.y + cat $^ > $@ %_y.cpp: %.y - bison -Wall --report=state --defines=$(SRC)/bison.hpp -o $@ $< + bison -Wall --defines=$(patsubst %.cpp,%.hpp,$@) -o $@ $< $(SED) 's/\"syntax\ error\"/COLOR_RED\ \"syntax\ error\"\ COLOR_RESET/' -i $@ $(SED) 's/\"syntax\ error:/COLOR_RED\ \"syntax\ error:\"\ COLOR_RESET\"/' -i $@ $(SED) 's/\"syntax\ error,/COLOR_RED\ \"syntax\ error:\"\ COLOR_RESET\"/' -i $@ @@ -55,7 +63,6 @@ src/out: mkdir ${SRC}/out clean: - rm -f ${SRC}/*_y.cpp ${SRC}/*_l.cpp ${SRC}/bison.hpp ${SRC}/out/*.o + rm -f ${SRC}/*_y.{hpp,cpp} ${SRC}/*_l.{hpp,cpp} ${SRC}/out/*.o #.SILENT: -.PRECIOUS: bison.hpp diff --git a/hack/debug/main.c b/hack/debug/main.c index 380d185..8283733 100644 --- a/hack/debug/main.c +++ b/hack/debug/main.c @@ -28,10 +28,12 @@ void wait(long qtd) { } } -void main() { +int main() { volatile ddrb_t *ddrb = (ddrb_t*)0x24; volatile portb_t *portb = (portb_t*)0x25; + char a = ddrb->pin13; + ddrb->pin13 = 1; //output char i = 10; for(;;) { diff --git a/platformio/samples/avr328p-blink/src/main.rob b/platformio/samples/avr328p-blink/src/main.rob index 4e2a8fb..003b62f 100644 --- a/platformio/samples/avr328p-blink/src/main.rob +++ b/platformio/samples/avr328p-blink/src/main.rob @@ -22,10 +22,14 @@ register int8 ddrb at 0x24 { } void wait(int32 q); +void serial_start(int32 clock, int32 baud_rate); +void serial_write(int8 c); int16 main() { arr = {1000000, 500000, 300000, 200000, 100000, 50000}; + serial_start(16000000, 9600); + /* pin 13 is controlled by bit 5 of DDRB and PORTB registers * - bit 5 of DDRB indicates if the pin is input (0) or output (1) * - bit 5 of PORTB toggles pin HIGH or LOW @@ -51,5 +55,9 @@ int16 main() { i = 0; } } + serial_write(65); + serial_write(66); + serial_write(67); + serial_write(10); } } diff --git a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json index 6859ef7..b5f19d6 100644 --- a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json +++ b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json @@ -42,13 +42,20 @@ "keywords": { "patterns": [{ "name": "keyword.control.rob", - "match": "\\b(while|loop|if|delay|print|return|register|at|volatile|const)\\b" + "match": "\\b(while|loop|if|delay|print|return|register|at|volatile|const|type|interface|implements|use)\\b" }] }, "types": { "patterns": [{ "name": "storage.type.rob", "match": "\\b(void|char|int8|int16|int32|int64|long|unsigned|float|double|bool)\\b" + }, + { + "match": "(\\w+)\\s+(\\w+)[\\(\\),]", + "captures": { + "1": { "name": "storage.type.rob" }, + "2": { "name": "variable.name.rob" } + } }] }, "numeric-consts": { @@ -60,7 +67,7 @@ "functions": { "patterns": [{ "name": "support.function.rob", - "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*(?=\\())\\b" + "match": "\\b(\\w+(?=\\())\\b" }] }, "ident": { diff --git a/src/Array.cpp b/src/Array.cpp index d180598..9d51e79 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -6,8 +6,8 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock Value *array_size = ConstantInt::get(Type::getInt8Ty(global_context), size); //Get Type of elements in Array of Elements, and define as I. - LanguageDataType pointee_dt = elements->getArrayType(block, allocblock); - Type* I = robTollvmDataType[pointee_dt]; + BasicDataType pointee_dt = elements->getArrayType(block, allocblock); + Type* I = buildTypes->llvmType(pointee_dt); //Declare array type. ArrayType* arrayType = ArrayType::get(I, size); @@ -54,10 +54,10 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock var = gv; if (debug_info) { - //FIXME: Replace 16 with pointer size for platform! - auto di_ptr = DBuilder->createPointerType(RobDbgInfo.types[pointee_dt], 16); + auto di_ptr = DBuilder->createPointerType(buildTypes->diType(pointee_dt), + buildTypes->bitWidth(currentTarget.pointerType)); auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", - funit, lineno, di_ptr, false); + funit, this->getLineNo(), di_ptr, false); gv->addDebugInfo(d); } diff --git a/src/ArrayElements.cpp b/src/ArrayElements.cpp index b3e29a8..c635316 100644 --- a/src/ArrayElements.cpp +++ b/src/ArrayElements.cpp @@ -17,13 +17,13 @@ unsigned ArrayElements::getStructSize() const { return elements.size(); } -LanguageDataType ArrayElements::getArrayType(BasicBlock *block, BasicBlock *allocblock) const { +BasicDataType ArrayElements::getArrayType(BasicBlock *block, BasicBlock *allocblock) const { unsigned intsize = 0; unsigned floatsize = 0; for(auto& i : elements) { - LanguageDataType dt = i.value->getResultType(block, allocblock); - if (isIntegerDataType(dt) && intsize < LanguageDataTypeBitWidth[dt]) - intsize = LanguageDataTypeBitWidth[dt]; + BasicDataType dt = i.value->getResultType(block, allocblock); + if (buildTypes->isIntegerDataType(dt) && intsize < buildTypes->bitWidth(dt)) + intsize = buildTypes->bitWidth(dt); if (floatsize < 32 && dt == tfloat) floatsize = 32; diff --git a/src/ArrayElements.h b/src/ArrayElements.h index 6f44750..24232dd 100644 --- a/src/ArrayElements.h +++ b/src/ArrayElements.h @@ -14,7 +14,7 @@ class ArrayElements { unsigned getStructSize () const; unsigned getElementCount (int position) const; Node *getStructElement (int position) const; - LanguageDataType getArrayType(BasicBlock *block, BasicBlock *allocblock) const; + BasicDataType getArrayType(BasicBlock *block, BasicBlock *allocblock) const; }; #endif diff --git a/src/AttachInterrupt.h b/src/AttachInterrupt.h index b4a6261..2e024a1 100644 --- a/src/AttachInterrupt.h +++ b/src/AttachInterrupt.h @@ -50,4 +50,6 @@ class AttachInterrupt: public Node { } }; +extern std::vector vectorglobal; + #endif diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 9028941..e6d18d8 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -31,12 +31,14 @@ LLVMContext global_context; std::unique_ptr> Builder; std::unique_ptr DBuilder; struct DebugInfo RobDbgInfo; +std::unique_ptr buildTypes; + +// interruptions +std::vector vectorglobal; // symbol table std::map> tabelasym; -Type* robTollvmDataType[__ldt_last]; - // arduino functions Function *analogWrite; Function *analogRead; diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index 5fc6251..b860369 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -1,5 +1,6 @@ #include "Header.h" #include "Int8.h" +#include "Language_gen_y.hpp" BinaryOp::BinaryOp(Node *l, int op, Node *r) { this->lhsn = l; @@ -108,10 +109,10 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, return Builder->CreateBinOp(llvmop, lhs, rhs, "binop"); } -LanguageDataType BinaryOp::getResultType(BasicBlock *block, BasicBlock *allocblock) { - LanguageDataType lty = lhsn->getResultType(block, allocblock); - LanguageDataType rty = rhsn->getResultType(block, allocblock); - if (isIntegerDataType(lty) && isIntegerDataType(rty)) { +BasicDataType BinaryOp::getResultType(BasicBlock *block, BasicBlock *allocblock) { + BasicDataType lty = lhsn->getResultType(block, allocblock); + BasicDataType rty = rhsn->getResultType(block, allocblock); + if (buildTypes->isIntegerDataType(lty) && buildTypes->isIntegerDataType(rty)) { if (op == TOK_LSHIFT || op == TOK_RSHIFT) { // zext the left operator if we know the rside bitwidth Constant *c = NULL; @@ -121,7 +122,7 @@ LanguageDataType BinaryOp::getResultType(BasicBlock *block, BasicBlock *allocblo } if (c) { int64_t v = c->getUniqueInteger().getZExtValue(); - if (LanguageDataTypeBitWidth[lty] < v) { + if (buildTypes->bitWidth(lty) < v) { if (v >= 8 && v <= 15) return tint16; else if (v >= 16 && v <= 31) @@ -133,10 +134,10 @@ LanguageDataType BinaryOp::getResultType(BasicBlock *block, BasicBlock *allocblo } } } - return LanguageDataTypeBitWidth[lty] > LanguageDataTypeBitWidth[rty] ? lty : rty; + return buildTypes->bitWidth(lty) > buildTypes->bitWidth(rty) ? lty : rty; } else { - if (isIntegerDataType(lty)) + if (buildTypes->isIntegerDataType(lty)) return rty; else return lty; diff --git a/src/BinaryOp.h b/src/BinaryOp.h index 2841c51..eb23193 100644 --- a/src/BinaryOp.h +++ b/src/BinaryOp.h @@ -22,7 +22,7 @@ class BinaryOp: public Node { int getOperator() const { return op; }; - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/BuildTypes.h b/src/BuildTypes.h new file mode 100644 index 0000000..aaaea1d --- /dev/null +++ b/src/BuildTypes.h @@ -0,0 +1,101 @@ + +#pragma once + +enum BasicDataType {tvoid, tbool, tchar, tint8, tint16, tint32, tint64, + tint8u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, tarray, + /* new types here! */ + __bdt_last}; + +enum DataQualifier {qnone, qconst, qvolatile}; + +struct DataTypeInfo { + const char *name; + unsigned bitWidth; + Type *llvmType; + unsigned dwarfEnc; + DIType *diType; +}; + +class BuildTypes { +private: + map tinfo; + unsigned nextt = __bdt_last; +public: + BuildTypes(unsigned targetPointerType) { + tinfo[tvoid] = {"void", 0, Type::getVoidTy(global_context), dwarf::DW_ATE_address}; + tinfo[tbool] = {"boolean", 1, Type::getInt1Ty(global_context), dwarf::DW_ATE_boolean}; + tinfo[tchar] = {"char", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned_char}; + tinfo[tint8] = {"int8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint16] = {"int16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint32] = {"int32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint64] = {"int64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint8u] = {"unsigned8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint16u] = {"unsigned16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint32u] = {"unsigned32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint64u] = {"unsigned64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tfloat] = {"float", 32, Type::getFloatTy(global_context), dwarf::DW_ATE_float}; + tinfo[tdouble] = {"double", 64, Type::getDoubleTy(global_context), dwarf::DW_ATE_float}; + tinfo[tldouble] = {"long double", 128, Type::getFP128Ty(global_context), dwarf::DW_ATE_float}; + + unsigned pts = tinfo[targetPointerType].bitWidth; + Type *pty = tinfo[targetPointerType].llvmType; + tinfo[tarray] = {"array", pts, pty, dwarf::DW_ATE_address}; + + if (debug_info) { + for(int t = 0; t < __bdt_last; t++) { + DataTypeInfo &info = tinfo[t]; + info.diType = DBuilder->createBasicType(info.name, info.bitWidth, info.dwarfEnc); + } + } + } + + unsigned addUserDataType(char *name, unsigned bitWidth, Type* llvmType) { + DataTypeInfo info; + info.name = name; + info.bitWidth = bitWidth; + info.llvmType = llvmType; + info.dwarfEnc = dwarf::DW_ATE_address; + //TODO: info.dwarfEnc = DBuilder->createClassType(); + + unsigned result = nextt; + tinfo[nextt++] = info; + return result; + } + + const char *name(unsigned tid) { + return tinfo[tid].name; + } + + const unsigned bitWidth(unsigned tid) { + return tinfo[tid].bitWidth; + } + + unsigned dwarfEnc(unsigned tid) { + return tinfo[tid].dwarfEnc; + } + + Type *llvmType(unsigned tid) { + return tinfo[tid].llvmType; + } + + DIType *diType(unsigned tid) { + return tinfo[tid].diType; + } + + bool isIntegerDataType(unsigned tid) { + return tid >= tint8 && tid <= tint64u; + } + + bool isSignedDataType(unsigned tid) { + return tid >= tint8 && tid <= tint64; + } + + bool isUnsignedDataType(unsigned tid) { + return tid >= tint8u && tid <= tint64u; + } + + bool isFloatDataType(unsigned tid) { + return tid >= tfloat && tid <= tldouble; + } + +}; diff --git a/src/Cast.cpp b/src/Cast.cpp index 311e158..4def6b9 100644 --- a/src/Cast.cpp +++ b/src/Cast.cpp @@ -1,7 +1,7 @@ #include "Header.h" -LanguageDataType Cast::getResultType(BasicBlock *block, BasicBlock *allocblock) { +BasicDataType Cast::getResultType(BasicBlock *block, BasicBlock *allocblock) { return dt; } @@ -11,12 +11,12 @@ Value *Cast::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) if (!exprv) return NULL; - Type *destty = robTollvmDataType[dt]; + Type *destty = buildTypes->llvmType(dt); Value *ret = Coercion::Convert(exprv, destty, block, expr, true); if (ret == NULL) { yyerrorcpp("Can't cast from '" + getTypeName(exprv->getType()) + "' to '" + - LanguageDataTypeNames[dt], this); + buildTypes->name(dt), this); return NULL; } diff --git a/src/Cast.h b/src/Cast.h index 74faec6..6578f39 100644 --- a/src/Cast.h +++ b/src/Cast.h @@ -6,10 +6,10 @@ class Cast: public Node { private: Node *expr; - LanguageDataType dt; + BasicDataType dt; public: - Cast(LanguageDataType dt, Node *expr): dt(dt), expr(expr) {} + Cast(BasicDataType dt, Node *expr): dt(dt), expr(expr) {} virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; virtual void accept(Visitor &v) override; - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/CmpOp.cpp b/src/CmpOp.cpp index 99ef633..155c83c 100644 --- a/src/CmpOp.cpp +++ b/src/CmpOp.cpp @@ -1,5 +1,6 @@ #include "Header.h" +#include "Language_gen_y.hpp" CmpOp::CmpOp (Node *l, int op, Node *r) : lexpn(l), rexpn(r) { this->op = op; diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index 2c6a112..9eac38f 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -5,6 +5,8 @@ void DebugInfo::emitLocation(SourceLocation *s) { return; if (!s) return Builder->SetCurrentDebugLocation(DebugLoc()); + if (s->getLineNo() == 0) + return; DIScope *scope; if (scopes.empty()) scope = cunit; diff --git a/src/Double.h b/src/Double.h index b9c5e33..005c58e 100644 --- a/src/Double.h +++ b/src/Double.h @@ -11,7 +11,7 @@ class Double: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { return tdouble; } }; diff --git a/src/Field.h b/src/Field.h index 4de3ff4..457a465 100644 --- a/src/Field.h +++ b/src/Field.h @@ -4,7 +4,7 @@ #include "Header.h" typedef struct { - LanguageDataType fieldDataType; + BasicDataType fieldDataType; char *fieldName; unsigned startBit; unsigned bitWidth; diff --git a/src/FlipOp.h b/src/FlipOp.h index 3ba7635..a7f7767 100644 --- a/src/FlipOp.h +++ b/src/FlipOp.h @@ -14,7 +14,7 @@ class FlipOp: public Node { virtual void accept(Visitor &v) override; - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { return value->getResultType(block, allocblock); } diff --git a/src/Float.h b/src/Float.h index 0d8879b..612b658 100644 --- a/src/Float.h +++ b/src/Float.h @@ -11,7 +11,7 @@ class Float: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { return tfloat; } }; diff --git a/src/Float128.h b/src/Float128.h index 1f01899..d81ca6d 100644 --- a/src/Float128.h +++ b/src/Float128.h @@ -13,7 +13,7 @@ class Float128: public Node { return true; } - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { return tldouble; } }; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index eeb7020..3969e66 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -1,6 +1,6 @@ #include "Header.h" -LanguageDataType FunctionCall::getResultType(BasicBlock *block, BasicBlock *allocblock) { +BasicDataType FunctionCall::getResultType(BasicBlock *block, BasicBlock *allocblock) { auto symbol = search_symbol(name); if (symbol) return symbol->dt; @@ -31,7 +31,7 @@ Value *FunctionCall::generate(Function *func, BasicBlock *block, BasicBlock *all vector args; for (int i = 0; i < parameters->getNumParams(); i++){ Value *valor = parameters->getParamElement(i)->generate(func, block, allocblock); - Type *pty = robTollvmDataType[symbol->params->getParamType(i)]; + Type *pty = buildTypes->llvmType(symbol->params->getParamType(i)); valor = Coercion::Convert(valor, pty, block, this); args.push_back(valor); } diff --git a/src/FunctionCall.h b/src/FunctionCall.h index 675a7b9..2f16200 100644 --- a/src/FunctionCall.h +++ b/src/FunctionCall.h @@ -13,7 +13,7 @@ class FunctionCall: public Node { } virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; + BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; }; #endif diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 08898ee..5a08517 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -2,135 +2,30 @@ Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) { auto sym = search_symbol(name); - if (sym != NULL && !sym->isDeclaration) { + if (sym != NULL) { yyerrorcpp("Function/symbol " + name + " already defined.", this); yyerrorcpp(name + " was first defined here.", sym); return NULL; } - Function *nfunc; - Type *xtype = robTollvmDataType[tipo]; - if (sym && sym->isDeclaration) { - if (sym->params->getNumParams() != parameters->getNumParams()) { - yyerrorcpp("The number of function arguments differs between its declaration and definition.", this); - yyerrorcpp("The function declaration is here.", sym); - return NULL; - } - for(int i = 0; i < sym->params->getNumParams(); i++) { - FunctionParam &p = sym->params->parameters[i]; - if (p.type != parameters->parameters[i].type) { - yyerrorcpp(string_format("Argument %s has distinct type in declaration '%s' and definition '%s'.", - LanguageDataTypeNames[p.type], LanguageDataTypeNames[parameters->parameters[i].type]), this); - yyerrorcpp("The function declaration is here.", sym); - } - } - if (tipo != sym->dt) { - yyerrorcpp(string_format("Function return type has distinct type in declaration '%s' and definition '%s'.", - LanguageDataTypeNames[sym->dt], LanguageDataTypeNames[tipo]), this); - yyerrorcpp("The function declaration is here.", sym); - } - nfunc = mainmodule->getFunction(name); - } else { - std::vector arg_types; - if (parameters->getNumParams() != 0) - for (int i = 0; i < parameters->getNumParams(); i++) - arg_types.push_back(robTollvmDataType[parameters->getParamType(i)]); - - FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - nfunc = Function::Create(ftype, Function::ExternalLinkage, 1, name, mainmodule); - } + std::vector arg_types; + if (parameters->getNumParams() != 0) + for (int i = 0; i < parameters->getNumParams(); i++) + arg_types.push_back(buildTypes->llvmType(parameters->getParamType(i))); + Type *xtype = buildTypes->llvmType(tipo); + FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); + Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, 1, name, mainmodule); nfunc->setDSOLocal(true); - llvm::AttrBuilder attrs(global_context); - attrs.addAttribute(Attribute::MinSize); - - if (name == "__vectors") { // FIXME: remove after adding functions attributes to language - nfunc->setSection(".vectors"); - } - - nfunc->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); nfunc->setCallingConv(CallingConv::C); - if (!sym) - sym = new RobSymbol(nfunc); - sym->dt = tipo; - sym->params = parameters; - sym->isDeclaration = false; - tabelasym[allocblock][name] = sym; - - DIFile *funit; - DISubprogram *sp; - if (debug_info) { - funit = DBuilder->createFile(RobDbgInfo.cunit->getFilename(), RobDbgInfo.cunit->getDirectory()); - DIScope *fcontext = funit; - sp = DBuilder->createFunction(fcontext, name, StringRef(), funit, this->lineno, - getFunctionDIType(), this->lineno, DINode::FlagPrototyped, DISubprogram::SPFlagDefinition); - nfunc->setSubprogram(sp); - RobDbgInfo.push_scope(funit, sp); - } - - BasicBlock *falloc = BasicBlock::Create(global_context, "entry", nfunc); - BasicBlock *fblock = BasicBlock::Create(global_context, "body", nfunc); - - RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(falloc); - - unsigned Idx = 0; - for (auto &Arg : nfunc->args()) - { - const char *argname = parameters->getParamElement(Idx); - LanguageDataType ptype = parameters->getParamType(Idx); - - Arg.setName(argname); - AllocaInst* variable = Builder->CreateAlloca(robTollvmDataType[ptype], 0, argname); - RobSymbol *rs = new RobSymbol(variable); - rs->dt = ptype; - tabelasym[falloc][argname] = rs; - StoreInst *val = Builder->CreateStore(&Arg, variable, false); - - if (debug_info) { - DILocalVariable *d = DBuilder->createParameterVariable(sp, argname, Idx+1, funit, - this->lineno, RobDbgInfo.types[ptype], true); - DBuilder->insertDeclare(variable, d, DBuilder->createExpression(), - DILocation::get(sp->getContext(), this->lineno, 0, sp), - falloc); - } + RobSymbol *rs = new RobSymbol(nfunc); + rs->params = parameters; + rs->setLocation(this); + rs->isDeclaration = true; + rs->dt = tipo; + tabelasym[allocblock][name] = rs; - Idx++; - } - - RobDbgInfo.emitLocation(stmts); - Value *last_block = stmts->generate(nfunc, fblock, falloc); - if (!last_block) - last_block = fblock; - - // prevent mallformed block at the end without proper return instruction - if (last_block && last_block->getValueID() == Value::BasicBlockVal) { - BasicBlock *lb = (BasicBlock*)last_block; - Builder->SetInsertPoint(lb); - RobDbgInfo.emitLocation(&endfunction); - if (lb->getTerminator() == NULL) { - if (!xtype->isVoidTy()) { - Value *ret = ConstantInt::get(xtype, 0); - Builder->CreateRet(ret); - } else - Builder->CreateRetVoid(); - } - } - - BranchInst::Create(fblock, falloc); - - if (debug_info) - RobDbgInfo.pop_scope(); - return nfunc; } -DISubroutineType *FunctionDecl::getFunctionDIType() { - SmallVector Tys; - Tys.push_back(RobDbgInfo.types[tipo]); // return type - for(FunctionParam &p : parameters->parameters) { - Tys.push_back(RobDbgInfo.types[p.type]); - } - return DBuilder->createSubroutineType(DBuilder->getOrCreateTypeArray(Tys)); -} diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index a494f41..dbd6bfb 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -1,31 +1,32 @@ -#ifndef __FUNCTIONDECL_H__ -#define __FUNCTIONDECL_H__ +#ifndef __FUNCTIONDECLEXTERN_H__ +#define __FUNCTIONDECLEXTERN_H__ #include "Node.h" -class FunctionDecl: public Node { +class FunctionDecl: public NamedNode { private: - Node *stmts; - LanguageDataType tipo; - string name; + BasicDataType tipo; FunctionParams *parameters; - SourceLocation endfunction; public: - FunctionDecl(LanguageDataType tipo, string name, FunctionParams *fp, Node *stmts, SourceLocation ef){ + FunctionDecl(BasicDataType tipo, string name, FunctionParams *fp) : NamedNode(name) { this->tipo = tipo; - this->stmts = stmts; - this->name = name; this->parameters = fp; - this->endfunction = ef; } - bool isFunctionDecl() { + virtual bool isFunctionDecl() override { return true; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - DISubroutineType *getFunctionDIType(); + FunctionParams const& getParameters() { + return *parameters; + } + + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return tipo; + } }; #endif + diff --git a/src/FunctionDeclExtern.cpp b/src/FunctionDeclExtern.cpp deleted file mode 100644 index e290542..0000000 --- a/src/FunctionDeclExtern.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "Header.h" - -Value *FunctionDeclExtern::generate(Function *, BasicBlock *, BasicBlock *allocblock) { - auto sym = search_symbol(name); - if (sym != NULL) { - yyerrorcpp("Function/symbol " + name + " already defined.", this); - yyerrorcpp(name + " was first defined here.", sym); - return NULL; - } - - std::vector arg_types; - if (parameters->getNumParams() != 0) - for (int i = 0; i < parameters->getNumParams(); i++) - arg_types.push_back(robTollvmDataType[parameters->getParamType(i)]); - - Type *xtype = robTollvmDataType[tipo]; - FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, 1, name, mainmodule); - nfunc->setDSOLocal(true); - nfunc->setCallingConv(CallingConv::C); - - RobSymbol *rs = new RobSymbol(nfunc); - rs->params = parameters; - rs->setLocation(this); - rs->isDeclaration = true; - rs->dt = tipo; - tabelasym[allocblock][name] = rs; - - return nfunc; -} - diff --git a/src/FunctionDeclExtern.h b/src/FunctionDeclExtern.h deleted file mode 100644 index 80500f0..0000000 --- a/src/FunctionDeclExtern.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __FUNCTIONDECLEXTERN_H__ -#define __FUNCTIONDECLEXTERN_H__ - -#include "Node.h" - -class FunctionDeclExtern: public Node { -private: - LanguageDataType tipo; - string name; - FunctionParams *parameters; -public: - FunctionDeclExtern(LanguageDataType tipo, string name, FunctionParams *fp){ - this->tipo = tipo; - this->name = name; - this->parameters = fp; - } - - bool isFunctionDecl() { - return true; - } - - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); - -}; - -#endif - diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp new file mode 100644 index 0000000..29d1eb6 --- /dev/null +++ b/src/FunctionImpl.cpp @@ -0,0 +1,149 @@ +#include "Header.h" + +Value *FunctionImpl::generate(Function *, BasicBlock *, BasicBlock *allocblock) { + auto sym = search_symbol(name); + if (sym != NULL && !sym->isDeclaration) { + yyerrorcpp("Function/symbol " + name + " already defined.", this); + yyerrorcpp(name + " was first defined here.", sym); + return NULL; + } + + Function *nfunc; + Type *xtype = buildTypes->llvmType(tipo); + if (sym && sym->isDeclaration) { + //TODO: validateImplementation(); + nfunc = mainmodule->getFunction(name); + } else { + std::vector arg_types; + if (parameters->getNumParams() != 0) + for (int i = 0; i < parameters->getNumParams(); i++) + arg_types.push_back(buildTypes->llvmType(parameters->getParamType(i))); + + FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); + nfunc = Function::Create(ftype, Function::ExternalLinkage, 1, name, mainmodule); + } + + nfunc->setDSOLocal(true); + llvm::AttrBuilder attrs(global_context); + attrs.addAttribute(Attribute::MinSize); + + if (name == "__vectors") { // FIXME: remove after adding functions attributes to language + nfunc->setSection(".vectors"); + } + + nfunc->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); + nfunc->setCallingConv(CallingConv::C); + + if (!sym) + sym = new RobSymbol(nfunc); + sym->dt = tipo; + sym->params = parameters; + sym->isDeclaration = false; + tabelasym[allocblock][name] = sym; + + DIFile *funit; + DISubprogram *sp; + if (debug_info) { + funit = DBuilder->createFile(RobDbgInfo.cunit->getFilename(), RobDbgInfo.cunit->getDirectory()); + DIScope *fcontext = funit; + sp = DBuilder->createFunction(fcontext, name, StringRef(), funit, this->getLineNo(), + getFunctionDIType(), this->getLineNo(), DINode::FlagPrototyped, DISubprogram::SPFlagDefinition); + nfunc->setSubprogram(sp); + RobDbgInfo.push_scope(funit, sp); + } + + BasicBlock *falloc = BasicBlock::Create(global_context, "entry", nfunc); + BasicBlock *fblock = BasicBlock::Create(global_context, "body", nfunc); + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(falloc); + + unsigned Idx = 0; + for (auto &Arg : nfunc->args()) + { + const char *argname = parameters->getParamElement(Idx); + BasicDataType ptype = parameters->getParamType(Idx); + + Arg.setName(argname); + AllocaInst* variable = Builder->CreateAlloca(buildTypes->llvmType(ptype), 0, argname); + RobSymbol *rs = new RobSymbol(variable); + rs->dt = ptype; + tabelasym[falloc][argname] = rs; + StoreInst *val = Builder->CreateStore(&Arg, variable, false); + + if (debug_info) { + DILocalVariable *d = DBuilder->createParameterVariable(sp, argname, Idx+1, funit, + this->getLineNo(), buildTypes->diType(ptype), true); + DBuilder->insertDeclare(variable, d, DBuilder->createExpression(), + DILocation::get(sp->getContext(), this->getLineNo(), 0, sp), + falloc); + } + + Idx++; + } + + RobDbgInfo.emitLocation(stmts); + Value *last_block = stmts->generate(nfunc, fblock, falloc); + if (!last_block) + last_block = fblock; + + // prevent mallformed block at the end without proper return instruction + if (last_block && last_block->getValueID() == Value::BasicBlockVal) { + BasicBlock *lb = (BasicBlock*)last_block; + Builder->SetInsertPoint(lb); + RobDbgInfo.emitLocation(&endfunction); + if (lb->getTerminator() == NULL) { + if (!xtype->isVoidTy()) { + Value *ret = ConstantInt::get(xtype, 0); + Builder->CreateRet(ret); + } else + Builder->CreateRetVoid(); + } + } + + BranchInst::Create(fblock, falloc); + + if (debug_info) + RobDbgInfo.pop_scope(); + + return nfunc; +} + +DISubroutineType *FunctionImpl::getFunctionDIType() { + SmallVector Tys; + Tys.push_back(buildTypes->diType(tipo)); // return type + for(FunctionParam &p : parameters->parameters) { + Tys.push_back(buildTypes->diType(p.type)); + } + return DBuilder->createSubroutineType(DBuilder->getOrCreateTypeArray(Tys)); +} + +bool FunctionImpl::validateImplementation(FunctionDecl *decl) { + bool result = true; + const FunctionParams& decl_parameters = decl->getParameters(); + if (parameters->getNumParams() != decl_parameters.getNumParams()) { + yyerrorcpp(string_format("The number of arguments differs between function declaration(%d) and definition(%d).", + decl_parameters.getNumParams(), parameters->getNumParams()), this); + yyerrorcpp("The function declaration is here.", decl); + result = false; + } + int compareno = std::min(parameters->getNumParams(), decl_parameters.getNumParams()); + for(int i = 0; i < compareno; i++) { + const FunctionParam &p = decl_parameters.parameters[i]; + if (p.type != parameters->parameters[i].type) { + yyerrorcpp(string_format("Argument %s has distinct type in declaration '%s' and definition '%s'.", + parameters->parameters[i].name, buildTypes->name(p.type), + buildTypes->name(parameters->parameters[i].type)), this); + yyerrorcpp("The function declaration is here.", decl); + result = false; + } + } + BasicDataType decl_type = decl->getResultType(NULL, NULL); + if (tipo != decl_type) { + yyerrorcpp(string_format("Function return type has distinct type in declaration '%s' and definition '%s'.", + buildTypes->name(decl_type), buildTypes->name(tipo)), this); + yyerrorcpp("The function declaration is here.", decl); + result = false; + } + return result; +} diff --git a/src/FunctionImpl.h b/src/FunctionImpl.h new file mode 100644 index 0000000..bf46c6e --- /dev/null +++ b/src/FunctionImpl.h @@ -0,0 +1,36 @@ + +#pragma once + +#include "Node.h" + +class FunctionImpl: public NamedNode { +private: + Node *stmts; + BasicDataType tipo; + FunctionParams *parameters; + SourceLocation endfunction; +public: + FunctionImpl(BasicDataType tipo, string name, FunctionParams *fp, Node *stmts, SourceLocation ef) : + NamedNode(name) + { + this->tipo = tipo; + this->stmts = stmts; + this->parameters = fp; + this->endfunction = ef; + this->node_children.push_back(stmts); + } + + virtual bool isFunctionDecl() override { + return true; + } + + virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + + DISubroutineType *getFunctionDIType(); + + bool validateImplementation(FunctionDecl *decl); + + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + return tipo; + } +}; diff --git a/src/FunctionParams.cpp b/src/FunctionParams.cpp index 0452962..6460f71 100644 --- a/src/FunctionParams.cpp +++ b/src/FunctionParams.cpp @@ -10,7 +10,7 @@ unsigned FunctionParams::getNumParams() const { return parameters.size(); }; -LanguageDataType FunctionParams::getParamType(int position) const { +BasicDataType FunctionParams::getParamType(int position) const { return parameters[position].type; } diff --git a/src/FunctionParams.h b/src/FunctionParams.h index 4b44bea..26adf85 100644 --- a/src/FunctionParams.h +++ b/src/FunctionParams.h @@ -11,7 +11,7 @@ class FunctionParams { void append(FunctionParam& fp); unsigned getNumParams() const; - LanguageDataType getParamType (int position) const; + BasicDataType getParamType (int position) const; const char *getParamElement (int position) const; }; diff --git a/src/Header.h b/src/Header.h index 40b20c1..0885224 100644 --- a/src/Header.h +++ b/src/Header.h @@ -3,13 +3,6 @@ //#define ENABLE_ARDUINO //#define ENABLE_PRINT -#define COLOR_RED "\x1b[31m" -#define COLOR_GREEN "\x1b[32m" -#define COLOR_YELLOW "\x1b[33m" -#define COLOR_BLUE "\x1b[34m" -#define COLOR_MAGENTA "\x1b[35m" -#define COLOR_CYAN "\x1b[36m" -#define COLOR_RESET "\x1b[0m" #include #include @@ -34,41 +27,33 @@ using namespace std; using namespace llvm; -/* After adding new types here, go to Program::generate to fill - * the robTollvmDataType vector */ -enum LanguageDataType {tvoid, tbool, tchar, tint8, tint16, tint32, tint64, - tint8u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, tarray, - __ldt_last}; - -static bool isIntegerDataType(LanguageDataType dt) { - return dt >= tint8 && dt <= tint64u; -} - -static bool isFloatDataType(LanguageDataType dt) { - return dt >= tfloat && dt <= tldouble; -} - -static const char *LanguageDataTypeNames[__ldt_last] = {"void", "boolean", "char", "int8", - "int16", "int32", "int64", "unsigned int8", "unsigned int16", - "unsigned int32", "unsigned int64", "float", - "double", "long double", "array"}; +// Program main module and IR Builder +extern Module* mainmodule; +extern BasicBlock* global_alloc; +extern LLVMContext global_context; +extern std::unique_ptr> Builder; -static const unsigned LanguageDataTypeBitWidth[__ldt_last] = {0, 1, 8, 8, - 16, 32, 64, 8, 16, 32, 64, 32, 64, 128, 0 /*use currentTarget->pointerSize*/}; +#include "SourceLocation.h" -static const unsigned LanguageDataTypeDwarfEnc[__ldt_last] = { - dwarf::DW_ATE_address, - dwarf::DW_ATE_boolean, - dwarf::DW_ATE_unsigned_char, - dwarf::DW_ATE_signed, dwarf::DW_ATE_signed, dwarf::DW_ATE_signed, dwarf::DW_ATE_signed, - dwarf::DW_ATE_unsigned, dwarf::DW_ATE_unsigned, dwarf::DW_ATE_unsigned, dwarf::DW_ATE_unsigned, - dwarf::DW_ATE_float, dwarf::DW_ATE_float, dwarf::DW_ATE_float, - dwarf::DW_ATE_address +// Debug Info +extern bool debug_info; +extern std::unique_ptr DBuilder; +struct DebugInfo { + DICompileUnit *cunit; + vector files; + vector scopes; + void emitLocation(SourceLocation *s); + void push_scope(DIFile *f, DIScope *); + void pop_scope(); + DIFile *currFile(); + DIScope *currScope(); }; +extern struct DebugInfo RobDbgInfo; -enum DataQualifier {qnone, qconst, qvolatile}; +#include "BuildTypes.h" +extern std::unique_ptr buildTypes; -extern Type* robTollvmDataType[]; +#include "Scanner.h" class Node; class Stmts; @@ -84,7 +69,7 @@ typedef struct { typedef struct { const char *name; - LanguageDataType type; + BasicDataType type; } FunctionParam; typedef struct { @@ -94,49 +79,13 @@ typedef struct { #include "Field.h" -typedef struct { - int first_line; - int first_column; - int last_line; - int last_column; -} location_t; - -#include "bison.hpp" - -extern int yyerror(const char *s); -extern int yylex(); -extern Node* getNodeForIntConst(int64_t i); - extern char* build_filename; extern char* build_outputfilename; -#include "SourceLocation.h" - -// Program main module and IR Builder -extern Module* mainmodule; -extern BasicBlock* global_alloc; -extern LLVMContext global_context; -extern std::unique_ptr> Builder; - -// Debug Info -extern bool debug_info; -extern std::unique_ptr DBuilder; -struct DebugInfo { - DICompileUnit *cunit; - DIType *types[__ldt_last]; - vector files; - vector scopes; - void emitLocation(SourceLocation *s); - void push_scope(DIFile *f, DIScope *); - void pop_scope(); - DIFile *currFile(); - DIScope *currScope(); -}; -extern struct DebugInfo RobDbgInfo; - // symbol table #include "RobSymbol.h" extern map> tabelasym; +static Node* getNodeForIntConst(int64_t i); // arduino functions extern Function *analogWrite; @@ -152,11 +101,11 @@ typedef struct { const char *triple; const char *cpu; const char *features; - const LanguageDataType pointerType; + const BasicDataType pointerType; } TargetInfo; enum SupportedTargets {native, avr328p, stm32f1, esp32, __last_target}; -extern enum SupportedTargets currentTargetId; +static enum SupportedTargets currentTargetId; #define currentTarget (supportedTargets[currentTargetId]) static TargetInfo supportedTargets[__last_target] = { @@ -166,6 +115,17 @@ static TargetInfo supportedTargets[__last_target] = { {"esp32", "xtensa", "", "", tint32}, }; +static void initTarget(const char *targetarch) { + currentTargetId = native; //native + for(int t = native; t < __last_target; t++) { + if (strcmp(targetarch, supportedTargets[t].name) == 0) { + currentTargetId = static_cast(t); + break; + } + } + buildTypes = make_unique(currentTarget.pointerType); +} + static string getTypeName(Type *ty) { string type_str; llvm::raw_string_ostream rso(type_str); @@ -173,25 +133,6 @@ static string getTypeName(Type *ty) { return rso.str(); } -static int yyerrorcpp(const string& s, SourceLocation *n) { - string e = COLOR_RED "semantic error: " COLOR_RESET + s; - if (n) { - yylloc.first_line = n->getLineNo(); - yylloc.first_column = n->getColNo(); - } - return yyerror(e.c_str()); -} - -static void yywarncpp(const string& s, SourceLocation *n) { - string e = COLOR_BLUE "semantic warning: " COLOR_RESET + s; - if (n) { - yylloc.first_line = n->getLineNo(); - yylloc.first_column = n->getColNo(); - } - fprintf(stderr, "%s:%d:%d %s\n", - build_filename, yylloc.first_line, yylloc.first_column, e.c_str()); -} - static RobSymbol *search_symbol(const string& ident, BasicBlock *firstb = NULL, BasicBlock *secondb = NULL) { BasicBlock *blocks[] = {firstb, secondb, global_alloc}; for(BasicBlock *b : blocks) { @@ -230,7 +171,7 @@ string string_format(const char *format, Args ... args) { #include "Float128.h" #include "FunctionCall.h" #include "FunctionDecl.h" -#include "FunctionDeclExtern.h" +#include "FunctionImpl.h" #include "FunctionParams.h" #include "If.h" #include "Int1.h" @@ -247,9 +188,9 @@ string string_format(const char *format, Args ... args) { #include "OutPort.h" #include "ParamsCall.h" #include "Print.h" +#include "Stmts.h" #include "Program.h" #include "Return.h" -#include "Stmts.h" #include "Scalar.h" #include "Semantic.h" #include "String.h" @@ -262,10 +203,23 @@ string string_format(const char *format, Args ... args) { #include "FlipOp.h" #include "Cast.h" #include "InlineAssembly.h" +#include "Interface.h" +#include "UserType.h" #include "Visitor.h" #include "RecursiveVisitor.h" #include "PrintAstVisitor.h" +static Node* getNodeForIntConst(int64_t i) { + if (i >= SCHAR_MIN && i <= SCHAR_MAX) + return new Int8(i); + else if (i >= SHRT_MIN && i <= SHRT_MAX) + return new Int16(i); + else if (i >= INT_MIN && i <= INT_MAX) + return new Int32(i); + else + return new Int64(i); +} + #endif diff --git a/src/InlineAssembly.cpp b/src/InlineAssembly.cpp index ace9a97..2c836a6 100644 --- a/src/InlineAssembly.cpp +++ b/src/InlineAssembly.cpp @@ -1,7 +1,7 @@ #include "Header.h" Value *InlineAssembly::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - Type *voidty = robTollvmDataType[tvoid]; + Type *voidty = buildTypes->llvmType(tvoid); std::vector arg_types; FunctionType *ftype = FunctionType::get(voidty, ArrayRef(arg_types), false); InlineAsm *asmcall = InlineAsm::get(ftype, assembly, "", false, false, InlineAsm::AD_ATT); diff --git a/src/Int1.h b/src/Int1.h index ab82125..a7fea4b 100644 --- a/src/Int1.h +++ b/src/Int1.h @@ -12,7 +12,7 @@ class Int1: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { return tbool; } }; diff --git a/src/Int16.h b/src/Int16.h index 5900bb3..fa91b7a 100644 --- a/src/Int16.h +++ b/src/Int16.h @@ -14,7 +14,7 @@ class Int16: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { return tint16; } }; diff --git a/src/Int32.h b/src/Int32.h index 5482849..725c62f 100644 --- a/src/Int32.h +++ b/src/Int32.h @@ -14,7 +14,7 @@ class Int32: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { return tint32; } }; diff --git a/src/Int64.h b/src/Int64.h index c94ece2..cac3f4c 100644 --- a/src/Int64.h +++ b/src/Int64.h @@ -13,7 +13,7 @@ class Int64: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { return tint64; } }; diff --git a/src/Int8.h b/src/Int8.h index 868a1cf..ae0e670 100644 --- a/src/Int8.h +++ b/src/Int8.h @@ -13,7 +13,7 @@ class Int8: public Node { virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { return true; } - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { return tint8; } }; diff --git a/src/Interface.cpp b/src/Interface.cpp new file mode 100644 index 0000000..419c8ee --- /dev/null +++ b/src/Interface.cpp @@ -0,0 +1,29 @@ + +#include "Header.h" + +Value *Interface::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + for(const auto n : symbols) { + printf("Symbol %s exists here!\n", n.first.c_str()); + } + return NULL; +} + +bool Interface::validateImplementation(UserType *ut) { + bool result = true; + for(const auto & [key, func_decl] : symbols) { + auto symb = ut->findSymbol(key, false); + FunctionImpl *fimpl = dynamic_cast(symb); + if (!symb) { + yyerrorcpp(string_format("Type %s doesn't implement %s.", ut->getName().c_str(), + key.c_str()), ut); + yyerrorcpp(string_format("%s is defined here.", key.c_str()), func_decl); + result = false; + } else if (!fimpl) { + yyerrorcpp(key + " must be a function.", symb); + result = false; + } else { + fimpl->validateImplementation(dynamic_cast(func_decl)); + } + } + return result; +} diff --git a/src/Interface.h b/src/Interface.h new file mode 100644 index 0000000..960ecf2 --- /dev/null +++ b/src/Interface.h @@ -0,0 +1,15 @@ + +#pragma once + +#include "Node.h" + +class Interface: public NamedNode { +public: + Interface(const string name): NamedNode(name) {} + + Interface(const string name, vector &&funcs): NamedNode(name, std::move(funcs)) {} + + virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + + bool validateImplementation(UserType *ut); +}; diff --git a/src/Language.l b/src/Language.l index 550e2b5..96fd24e 100644 --- a/src/Language.l +++ b/src/Language.l @@ -1,31 +1,35 @@ %{ #include "Header.h" -#include "bison.hpp" +#include "Language_gen_y.hpp" extern void unescape(char *s); -extern int yycolno; - -static void update_loc() { - yylloc.first_line = yylineno; - yylloc.last_line = yylineno; - yylloc.first_column = yycolno; - yylloc.last_column = yycolno + yyleng - 1; - yycolno += yyleng; +static void update_loc(location_t *yylloc, int lineno, int leng, char *text) { + yylloc->first_line = yylloc->last_line; + yylloc->last_line = yylloc->last_column; + if (yylloc->last_line == lineno) + yylloc->last_column += leng; + else { + yylloc->last_line = lineno; + yylloc->last_column = text + leng - strrchr(text, '\n'); + } } -#define YY_USER_ACTION update_loc(); +#define YY_USER_ACTION update_loc(yylloc, yylineno, yyleng, yytext); %} +%option noinput nounput noyywrap %option yylineno +%option reentrant bison-locations +%option prefix="MAIN" + %x COMMENT %% -[ \t\r] { /* ignore spaces */ } -[\n] { yycolno = 0; } +[ \t\r\n] { /* ignore spaces */ } "/*" { yymore(); BEGIN COMMENT; } [^*] { yymore(); } "*"/[^/] { yymore(); } @@ -52,6 +56,10 @@ static void update_loc() { "false" { return TOK_FALSE; } "at" { return TOK_AT; } "asm" { return TOK_ASM; } +"type" { return TOK_TYPE; } +"interface" { return TOK_INTF; } +"implements" { return TOK_IMPL; } +"use" { return TOK_USE; } "if" { return TOK_IF; } "else" { return TOK_ELSE; } @@ -61,15 +69,15 @@ static void update_loc() { "print" { return TOK_PRINT; } -"in"[0-9]+ { yylval.port = strndup(yytext+2, yyleng-2); +"in"[0-9]+ { yylval->port = strndup(yytext+2, yyleng-2); return TOK_IN; } -"out"[0-9]+ { yylval.port = strndup(yytext+3, yyleng-3); +"out"[0-9]+ { yylval->port = strndup(yytext+3, yyleng-3); return TOK_OUT; } -"stepper"[0-2]+ { yylval.nint = atoi(strndup(yytext+7, yyleng-7)); +"stepper"[0-2]+ { yylval->nint = atoi(strndup(yytext+7, yyleng-7)); return TOK_STEPPER; } @@ -115,45 +123,45 @@ static void update_loc() { "," { return ','; } ";" { return ';'; } -[a-zA-Z_][a-zA-Z0-9_]* { yylval.ident = strndup(yytext, yyleng); +[a-zA-Z_][a-zA-Z0-9_]* { yylval->ident = strndup(yytext, yyleng); return TOK_IDENTIFIER; } [0-9]+\.[0-9]+ { char *aux = strndup(yytext, yyleng); - yylval.nfloat = strtof(aux, NULL); + yylval->nfloat = strtof(aux, NULL); free(aux); return TOK_FLOAT; } [0-9]+\.[0-9]+D { char *aux = strndup(yytext, yyleng); - yylval.ndouble = strtod(aux, NULL); + yylval->ndouble = strtod(aux, NULL); free(aux); return TOK_DOUBLE; } [0-9]+\.[0-9]+LD { char *aux = strndup(yytext, yyleng); - yylval.nldouble = strtold(aux, NULL); + yylval->nldouble = strtold(aux, NULL); free(aux); return TOK_LDOUBLE; } "0x"[0-9a-fA-F]+ { char *aux = strndup(yytext, yyleng); - yylval.nint = strtoll(aux, NULL, 16); + yylval->nint = strtoll(aux, NULL, 16); free(aux); return TOK_INTEGER; } "0b"[0-1]+ { char *aux = strndup(yytext+2, yyleng-2); - yylval.nint = strtoll(aux, NULL, 2); + yylval->nint = strtoll(aux, NULL, 2); free(aux); return TOK_INTEGER; } [0-9]+ { char *aux = strndup(yytext, yyleng); - yylval.nint = strtoll(aux, NULL, 10); + yylval->nint = strtoll(aux, NULL, 10); free(aux); return TOK_INTEGER; } -\"([^\\\"]|\\.)*\" { yylval.str = strndup(yytext+1, yyleng-2); - unescape(yylval.str); +\"([^\\\"]|\\.)*\" { yylval->str = strndup(yytext+1, yyleng-2); + unescape(yylval->str); return TOK_STRING; } /* deixar por último. Caractere não reconhecido pelo alfabeto. */ -. { yyerror("lexical error, caractere nao pertence ao alfabeto da linguagem:"); } +. { yyerror(yylloc, NULL, COLOR_RED "lexical error:" COLOR_RED " caractere nao pertence ao alfabeto da linguagem:"); } %% diff --git a/src/Language.y b/src/Language.y index bff872b..a800686 100644 --- a/src/Language.y +++ b/src/Language.y @@ -1,59 +1,18 @@ -%{ - -#include -#include -#include "Header.h" -#include "2018arm/nodeh_ext.h" - -Node* getNodeForIntConst(int64_t i); -std::vector vectorglobal; - -extern int errorsfound; -%} - -%locations -%define api.location.type {location_t} -%define parse.error verbose - -%token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST TOK_ASM -%token TOK_IF TOK_ELSE -%token TOK_LOOP TOK_WHILE -%token TOK_PRINT -%token TOK_IN TOK_OUT TOK_STEPPER TOK_SERVO -%token TOK_DELAY TOK_AND TOK_OR -%token TOK_IDENTIFIER TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE -%token TOK_FINT8 TOK_FINT16 TOK_FINT32 TOK_FINT64 -%token TOK_FFLOAT TOK_FDOUBLE TOK_FCHAR TOK_FLONG TOK_FUNSIGNED TOK_FBOOL - -%token TOK_QUANDO TOK_ESTA -%token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT - -%union { - char *port; - char *ident; - char *str; - int64_t nint; - float nfloat; - double ndouble; - long double nldouble; - Node *node; - Stmts *stmt; - ArrayElement ae; - ArrayElements *aes; - MatrixElement me; - MatrixElements *mes; - FunctionParam fp; - FunctionParams *fps; - ParamsCall *pc; - LanguageDataType dt; - Field field; - Structure *structure; - ComplexIdentifier *complexIdent; + +%name-prefix="MAIN" +//%define api.prefix {MAIN} // not working in Bison 3.8.2 + +%code provides { + #define YY_DECL int MAINlex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) + YY_DECL; + void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); } %type term term2 expr factor stmt gstmt condblock elseblock whileblock logicexpr %type logicterm logicfactor TOK_AND TOK_OR printstmt fe eventblock unary -%type funcblock returnblock registerstmt cast +%type funcblock func_decl func_impl returnblock registerstmt cast +%type interfacestmt typestmt +%type typestmt_impls %type element %type elements relements %type funcparam @@ -75,21 +34,23 @@ extern int errorsfound; %type struct_fields %type complex_identifier %type error - -%start programa +%type intf_decls %% -programa : gstmts { Program p($1); +programa : gstmts { // interruptions setup for(AttachInterrupt *a : vectorglobal) { $1->prepend(a); } + Program p(std::move(*$1)); + /*std::fstream fs; fs.open("ast", std::fstream::out); PrintAstVisitor(fs).visit(p); fs.close();*/ + if (errorsfound == 0) p.generate(); }; @@ -106,6 +67,8 @@ gstmt : TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($1, $3, qnone); } | TOK_IDENTIFIER '=' relements ';' { $$ = new Array($1, $3); $$->setLocation(@1); } | TOK_IDENTIFIER '=' rmatrix ';' { $$ = new Matrix($1, $3);} | registerstmt { $$ = $1; } + | interfacestmt { $$ = $1; } + | typestmt { $$ = $1; } | fe { $$ = $1; } | error ';' { /* error recovery until next ';' */ $$ = new Int8(0); // evita falha de segmentacao @@ -115,12 +78,14 @@ fe : funcblock { $$ = $1; } | eventblock { $$ = $1; } ; -funcblock : type_f TOK_IDENTIFIER '(' funcparams ')' ';' { - $$ = new FunctionDeclExtern($1, $2, $4); +funcblock : func_decl | func_impl ; + +func_decl : type_f TOK_IDENTIFIER '(' funcparams ')' ';' { + $$ = new FunctionDecl($1, $2, $4); $$->setLocation(@type_f); } - | type_f TOK_IDENTIFIER '(' funcparams ')' '{' stmts '}'[ef] { - $$ = new FunctionDecl($1, $2, $4, $7, @ef); +func_impl : type_f TOK_IDENTIFIER '(' funcparams ')' '{' stmts '}'[ef] { + $$ = new FunctionImpl($1, $2, $4, $7, @ef); $$->setLocation(@type_f); } ; @@ -130,7 +95,7 @@ eventblock : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { snprintf(funcname, 100, "__callback_int_p%d_e%d", (int)$2, (int)$4); vectorglobal.push_back(new AttachInterrupt($2, funcname, $4)); FunctionParams *fps = new FunctionParams(); - $$ = new FunctionDecl(tvoid, funcname, fps, $6, @ef); + $$ = new FunctionImpl(tvoid, funcname, fps, $6, @ef); } ; @@ -156,8 +121,6 @@ stmt : gstmt { $$ = $1; } | returnblock ';' { $$ = $1; } | printstmt ';' { $$ = $1; } | asminline ';' { $$ = new InlineAssembly($1); $$->setLocation(@1); } - | TOK_STEPPER expr ';' { $$ = new StepperGoto($1, $2); } - | TOK_SERVO expr ';' { $$ = new ServoGoto($2); } | TOK_IDENTIFIER '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6);} | TOK_IDENTIFIER '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9); } @@ -213,7 +176,6 @@ funcparam : type_f TOK_IDENTIFIER[id] { $$ = FunctionParam{$id, $type_f}; } | TOK_IDENTIFIER[id1] TOK_IDENTIFIER[id2] { - yyerrorcpp(string_format("Invalid type name '%s' for parameter %s.", $id1, $id2), nullptr); $$ = FunctionParam{$2, tvoid}; } ; @@ -396,7 +358,7 @@ struct_fields : struct_fields struct_field { struct_field : type_f TOK_IDENTIFIER ';' { $$.fieldDataType = $1; $$.fieldName = $2; - $$.bitWidth = LanguageDataTypeBitWidth[$1]; + $$.bitWidth = buildTypes->bitWidth($1); } | type_f TOK_IDENTIFIER ':' TOK_INTEGER ';' { $$.fieldDataType = $1; @@ -407,30 +369,45 @@ struct_field : type_f TOK_IDENTIFIER ';' { asminline : TOK_ASM TOK_STRING { $$ = $2; } ; -%% -extern char *build_filename; +interfacestmt : TOK_INTF TOK_IDENTIFIER '{' intf_decls '}' { + $$ = new Interface($TOK_IDENTIFIER, std::move(*$intf_decls)); + $$->setLocation(@TOK_INTF); +}; + +interfacestmt : TOK_INTF TOK_IDENTIFIER '{' '}' { + $$ = new Interface($TOK_IDENTIFIER); + $$->setLocation(@TOK_INTF); +}; + +intf_decls : intf_decls func_decl { + $1->push_back($func_decl); + $$ = $1; +}; + +intf_decls : func_decl { + $$ = new vector(); + $$->push_back($func_decl); +}; + +typestmt : TOK_TYPE TOK_IDENTIFIER TOK_IMPL typestmt_impls '{' stmts '}' { + $$ = new UserType($TOK_IDENTIFIER, std::move(*$stmts), std::move(*$typestmt_impls)); + $$->setLocation(@TOK_TYPE); +} -int yyerror(const char *s) -{ - fprintf(stderr, "%s:%d:%d: %s\n", - build_filename, yylloc.first_line, yylloc.first_column, s); - errorsfound++; - return 0; +typestmt : TOK_TYPE TOK_IDENTIFIER '{' stmts '}' { + $$ = new UserType($TOK_IDENTIFIER, std::move(*$stmts)); + $$->setLocation(@TOK_TYPE); } -Node* getNodeForIntConst(int64_t i) { - if (i >= SCHAR_MIN && i <= SCHAR_MAX) - return new Int8(i); - else if (i >= SHRT_MIN && i <= SHRT_MAX) - return new Int16(i); - else if (i >= INT_MIN && i <= INT_MAX) - return new Int32(i); - else - return new Int64(i); +typestmt_impls : typestmt_impls ',' TOK_IDENTIFIER { + $1->push_back($TOK_IDENTIFIER); + $$ = $1; } -extern "C" int yywrap() { - return 1; +typestmt_impls : TOK_IDENTIFIER { + $$ = new vector(); + $$->push_back($1); } +%% diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y new file mode 100644 index 0000000..6dd3b06 --- /dev/null +++ b/src/LanguageHeader.y @@ -0,0 +1,59 @@ + +%locations +%define api.location.type {location_t} +%define api.pure full +%define parse.error verbose +%param {yyscan_t scanner} + +%code top { + #include + #include + #include "Header.h" +} + +%code provides { + #ifndef YYLTYPE + #define YYLTYPE location_t + #endif +} + +%token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST TOK_ASM +%token TOK_IF TOK_ELSE +%token TOK_LOOP TOK_WHILE +%token TOK_PRINT +%token TOK_IN TOK_OUT TOK_STEPPER TOK_SERVO +%token TOK_DELAY TOK_AND TOK_OR +%token TOK_IDENTIFIER TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE +%token TOK_FINT8 TOK_FINT16 TOK_FINT32 TOK_FINT64 +%token TOK_FFLOAT TOK_FDOUBLE TOK_FCHAR TOK_FLONG TOK_FUNSIGNED TOK_FBOOL +%token TOK_TYPE TOK_INTF TOK_IMPL TOK_USE + +%token TOK_QUANDO TOK_ESTA +%token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT + +%union { + char *port; + char *ident; + char *str; + int64_t nint; + float nfloat; + double ndouble; + long double nldouble; + Node *node; + Stmts *stmt; + ArrayElement ae; + ArrayElements *aes; + MatrixElement me; + MatrixElements *mes; + FunctionParam fp; + FunctionParams *fps; + ParamsCall *pc; + BasicDataType dt; + Field field; + Structure *structure; + ComplexIdentifier *complexIdent; + vector *nodes; + vector *strings; +} + +%start programa diff --git a/src/LanguageUse.y b/src/LanguageUse.y new file mode 100644 index 0000000..29bf29d --- /dev/null +++ b/src/LanguageUse.y @@ -0,0 +1,184 @@ + +%name-prefix="USE" +//%define api.prefix {USE} // not working in Bison 3.8.2 + +%code provides { + #define YY_DECL int USElex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) + YY_DECL; + void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); +} + +%type gstmts +%type gstmt register interface type +%type function function_decl function_impl +%type function_params +%type function_param +%type intf_decls +%type const_expr +%type TOK_IDENTIFIER +%type TOK_INTEGER +%type
type_f register_type +%type struct_fields +%type struct_field +%type type_impls + +%% + +programa : gstmts + ; + +gstmts : gstmts gstmt { $1->append($gstmt);} + | gstmt { $$ = new Stmts($gstmt); $gstmt->setLocation(@gstmt); } + ; + +gstmt : register { } + | interface { } + | type { } + | function { } + | ignore { } + ; + +function : function_decl | function_impl ; + +function_decl : type_f TOK_IDENTIFIER '(' function_params ')' ';' { + $$ = new FunctionDecl($1, $2, $4); + $$->setLocation(@type_f); +}; + +function_impl : type_f TOK_IDENTIFIER '(' function_params ')' '{' gstmt '}'[ef] { + $$ = new FunctionDecl($1, $2, $4); + $$->setLocation(@type_f); +}; + +function_params: function_params ',' function_param { + $1 -> append($3); + $$ = $1; +} + +function_params: function_param { + FunctionParams *fps = new FunctionParams(); + fps->append($1); + $$ = fps; +} + +function_params: %empty { + FunctionParams *fps = new FunctionParams(); + $$ = fps; +} + +function_param : type_f TOK_IDENTIFIER[id] { + $$ = FunctionParam{$id, $type_f}; + } + | TOK_IDENTIFIER[id1] TOK_IDENTIFIER[id2] { + $$ = FunctionParam{$2, tvoid}; + } + ; + +type_f : TOK_VOID { $$ = tvoid; } + | TOK_FCHAR { $$ = tchar; } + | TOK_FBOOL { $$ = tbool; } + | TOK_FINT8 { $$ = tint8; } + | TOK_FINT16 { $$ = tint16; } + | TOK_FINT32 { $$ = tint32; } + | TOK_FINT64 { $$ = tint64; } + | TOK_FUNSIGNED TOK_FINT8 { $$ = tint8u; } + | TOK_FUNSIGNED TOK_FINT16 { $$ = tint16u; } + | TOK_FUNSIGNED TOK_FINT32 { $$ = tint32u; } + | TOK_FUNSIGNED TOK_FINT64 { $$ = tint64u; } + | TOK_FFLOAT { $$ = tfloat; } + | TOK_FDOUBLE { $$ = tdouble; } + | TOK_FLONG TOK_FDOUBLE { $$ = tldouble; } +/* | TOK_IDENTIFIER[ident] { + yyerrok; + yyerrorcpp(string_format("Invalid type name '%s'.", $ident), nullptr); + $$ = tvoid; + }*/ + ; + +register : TOK_REGISTER register_type TOK_IDENTIFIER TOK_AT const_expr ';' { + $$ = new Pointer($3, $2, $5, true); + } + | TOK_REGISTER register_type TOK_IDENTIFIER TOK_AT const_expr '{' struct_fields '}' { + $$ = new Pointer($3, $2, $5, $7, true); + } + ; + +register_type : TOK_FINT8 { $$ = tint8; } + | TOK_FINT16 { $$ = tint16; } + | TOK_FINT32 { $$ = tint32; } + | TOK_FINT64 { $$ = tint64; } + ; + +struct_fields : struct_fields struct_field { + $2.startBit = $1->nextBit; + $1->fields[$2.fieldName] = $2; + $1->nextBit += $2.bitWidth; + $$ = $1; + } + | struct_field { + Structure *s = new Structure(); + $1.startBit = 0; + s->fields[$1.fieldName] = $1; + s->nextBit = $1.bitWidth; + $$ = s; + } + ; + +struct_field : type_f TOK_IDENTIFIER ';' { + $$.fieldDataType = $1; + $$.fieldName = $2; + $$.bitWidth = buildTypes->bitWidth($1); + } + | type_f TOK_IDENTIFIER ':' TOK_INTEGER ';' { + $$.fieldDataType = $1; + $$.fieldName = $2; + $$.bitWidth = (unsigned)$4; + } + ; + +interface : TOK_INTF TOK_IDENTIFIER '{' intf_decls '}' { + $$ = new Interface($TOK_IDENTIFIER, std::move(*$intf_decls)); + $$->setLocation(@TOK_INTF); +}; + +interface : TOK_INTF TOK_IDENTIFIER '{' '}' { + $$ = new Interface($TOK_IDENTIFIER); + $$->setLocation(@TOK_INTF); +}; + +intf_decls : intf_decls function_decl { + $1->push_back($function_decl); + $$ = $1; +}; + +intf_decls : function_decl { + $$ = new vector(); + $$->push_back($function_decl); +}; + +type : TOK_TYPE TOK_IDENTIFIER TOK_IMPL type_impls '{' gstmts '}' { + $$ = new UserType($TOK_IDENTIFIER, std::move(*$gstmts), std::move(*$type_impls)); + $$->setLocation(@TOK_TYPE); +} + +type : TOK_TYPE TOK_IDENTIFIER '{' gstmts '}' { + $$ = new UserType($TOK_IDENTIFIER, std::move(*$gstmts)); + $$->setLocation(@TOK_TYPE); +} + +type_impls : type_impls ',' TOK_IDENTIFIER { + $1->push_back($TOK_IDENTIFIER); + $$ = $1; +} + +type_impls : TOK_IDENTIFIER { + $$ = new vector(); + $$->push_back($1); +} + +const_expr : TOK_INTEGER { $$ = getNodeForIntConst($1); } + +ignore : error { yyerrok; }; + +%% + diff --git a/src/Load.cpp b/src/Load.cpp index 234995e..7f6fd63 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -1,6 +1,6 @@ #include "Header.h" -LanguageDataType Load::getResultType(BasicBlock *block, BasicBlock *allocblock) { +BasicDataType Load::getResultType(BasicBlock *block, BasicBlock *allocblock) { auto rsym = search_symbol(ident, allocblock, block); if (rsym) { if (complexIdent) { @@ -51,7 +51,7 @@ Value* Load::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) Builder->SetInsertPoint(block); bool vol = rsym->qualifier == qvolatile; - Type *ty = robTollvmDataType[rsym->dt]; + Type *ty = buildTypes->llvmType(rsym->dt); Value *v = Builder->CreateLoad(ty, sym, vol, ident); if (complexIdent) { @@ -59,12 +59,12 @@ Value* Load::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) * v = symbol->value << pointerbits - field_start - field_width * v = v >> pointer_bits - field_width */ - int bs = LanguageDataTypeBitWidth[rsym->dt] - field.bitWidth; + int bs = buildTypes->bitWidth(rsym->dt) - field.bitWidth; if (bs - field.startBit > 0) v = Builder->CreateShl(v, ConstantInt::get(ty, bs - field.startBit)); if (bs > 0) v = Builder->CreateAShr(v, ConstantInt::get(ty, bs)); - v = Builder->CreateTrunc(v, robTollvmDataType[field.fieldDataType]); + v = Builder->CreateTrunc(v, buildTypes->llvmType(field.fieldDataType)); } return v; diff --git a/src/Load.h b/src/Load.h index de59afa..d0bc191 100644 --- a/src/Load.h +++ b/src/Load.h @@ -18,7 +18,7 @@ class Load: public Node { virtual void accept(Visitor& v) override; - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index aa130fb..d1f3120 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -1,6 +1,6 @@ #include "Header.h" -LanguageDataType LoadArray::getResultType(BasicBlock *block, BasicBlock *allocblock) { +BasicDataType LoadArray::getResultType(BasicBlock *block, BasicBlock *allocblock) { if (!rsym) rsym = search_symbol(ident, allocblock, block); if (rsym) diff --git a/src/LoadArray.h b/src/LoadArray.h index fa3c0de..f659fa0 100644 --- a/src/LoadArray.h +++ b/src/LoadArray.h @@ -13,7 +13,7 @@ class LoadArray: public Node { Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock); + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock); virtual Node *getLoadIndex(RobSymbol *rsym, BasicBlock *block, BasicBlock *allocblock) { return position; diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 7387cfc..529c1f6 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -7,7 +7,7 @@ Value *Matrix::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc */ //Get Type of elements in Vector of Elements, and define as I. - Type* I = robTollvmDataType[melements->getMatrixType(block, allocblock)]; + Type* I = buildTypes->llvmType(melements->getMatrixType(block, allocblock)); // The matrix size unsigned int lines = melements->getLineCount(); diff --git a/src/MatrixElements.cpp b/src/MatrixElements.cpp index 7f75e0e..ee5fdeb 100644 --- a/src/MatrixElements.cpp +++ b/src/MatrixElements.cpp @@ -26,14 +26,14 @@ unsigned MatrixElements::getColumnCount() const { return biggest_r; } -LanguageDataType MatrixElements::getMatrixType(BasicBlock *block, BasicBlock *allocblock) const { +BasicDataType MatrixElements::getMatrixType(BasicBlock *block, BasicBlock *allocblock) const { unsigned intsize = 0; unsigned floatsize = 0; for(auto& j : elements) { for (auto& i : j.array->elements) { - LanguageDataType dt = i.value->getResultType(block, allocblock); - if (isIntegerDataType(dt) && intsize < LanguageDataTypeBitWidth[dt]) - intsize = LanguageDataTypeBitWidth[dt]; + BasicDataType dt = i.value->getResultType(block, allocblock); + if (buildTypes->isIntegerDataType(dt) && intsize < buildTypes->bitWidth(dt)) + intsize = buildTypes->bitWidth(dt); if (floatsize < 32 && dt == tfloat) floatsize = 32; diff --git a/src/MatrixElements.h b/src/MatrixElements.h index 6c8c20f..970911f 100644 --- a/src/MatrixElements.h +++ b/src/MatrixElements.h @@ -13,7 +13,7 @@ class MatrixElements { unsigned getColumnCount() const; unsigned getLineCount() const; unsigned getElementCount(int position) const; - LanguageDataType getMatrixType(BasicBlock *block, BasicBlock *allocblock) const; + BasicDataType getMatrixType(BasicBlock *block, BasicBlock *allocblock) const; }; #endif diff --git a/src/Node.h b/src/Node.h index e5b88d3..e04407a 100644 --- a/src/Node.h +++ b/src/Node.h @@ -1,12 +1,33 @@ -#ifndef NODE_H -#define NODE_H + +#pragma once class Visitor; +class NamedNode; +class UserType; class Node : public SourceLocation { protected: - std::vector node_children; + vector node_children; + map symbols; + Node *parent = nullptr; + bool update_names = false; + + virtual void updateNamedNodes() { + for(Node *n : node_children) { + if (n->hasName()) + symbols[n->getName()] = n; + } + } + public: + Node() {} + Node(vector &&children) : node_children(children) { + updateNamedNodes(); + update_names = false; + for(auto c : children) + c->setParent(this); + } + virtual ~Node(); virtual bool isFunctionDecl(); @@ -18,14 +39,61 @@ class Node : public SourceLocation { virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) = 0; virtual std::vector const& children() const; + virtual void accept(Visitor &); - virtual LanguageDataType getResultType(BasicBlock *block, BasicBlock *allocblock) { + virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) { /* this method should be overrided in descending classes * that define vars/consts */ return tvoid; } + + virtual bool hasName() { + return false; + } + + virtual string const getName() const { + return ""; + } + + Node *getParent() { + return parent; + } + + virtual void setParent(Node *p) { + parent = p; + } + + virtual Node* findSymbol(const string& name, bool recursive = true) { + auto it = symbols.find(name); + if (it != symbols.end()) { + return it->second; + } else if (recursive && parent) + return parent->findSymbol(name); + else + return nullptr; + } + + friend class UserType; + friend class Program; }; -#endif +class NamedNode: public Node { +protected: + string name; + +public: + NamedNode(const string &name) : name(name) {} + + NamedNode(const string &name, vector &&children) : + Node(std::move(children)), name(name) {} + + string const getName() const override { + return name; + } + + bool hasName() override { + return true; + } +}; diff --git a/src/Pointer.cpp b/src/Pointer.cpp index c51b1b0..2bece89 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -17,14 +17,14 @@ Value *Pointer::generate(Function *func, BasicBlock *block, BasicBlock *allocblo return NULL; } - Type *targetPointerType = robTollvmDataType[currentTarget.pointerType]; + Type *targetPointerType = buildTypes->llvmType(currentTarget.pointerType); Value *addrp = NULL; if (Constant *addrc = dyn_cast(addr)) addrp = ConstantExpr::getIntToPtr(addrc, targetPointerType); else addrp = new IntToPtrInst(addr, targetPointerType, name, allocblock); - Type *ty = robTollvmDataType[type]; + Type *ty = buildTypes->llvmType(type); DataQualifier vol = isVolatile ? qvolatile : qnone; RobSymbol *rs = new RobSymbol(addrp, vol); diff --git a/src/Pointer.h b/src/Pointer.h index bebfc27..6b2abc2 100644 --- a/src/Pointer.h +++ b/src/Pointer.h @@ -5,20 +5,20 @@ class Pointer: public Node { private: - LanguageDataType type; + BasicDataType type; Node *address; string name; bool isVolatile; Structure *structure; public: - Pointer(const char *name, LanguageDataType type, Node *address, bool isVolatile = false): + Pointer(const char *name, BasicDataType type, Node *address, bool isVolatile = false): name(name), type(type), address(address), isVolatile(isVolatile) {} - Pointer(const char *name, LanguageDataType type, Node *address, Structure *structure, + Pointer(const char *name, BasicDataType type, Node *address, Structure *structure, bool isVolatile = false): name(name), type(type), address(address), structure(structure), isVolatile(isVolatile) { - if (structure->nextBit > LanguageDataTypeBitWidth[type]) { + if (structure->nextBit > buildTypes->bitWidth(type)) { const char *emsg = "The sum of field sizes for %s (%d) is larger than its type size (%d)."; - yyerrorcpp(string_format(emsg, name, structure->nextBit, LanguageDataTypeBitWidth[type]), this); + yyerrorcpp(string_format(emsg, name, structure->nextBit, buildTypes->bitWidth(type)), this); } } virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; diff --git a/src/PrintAstVisitor.cpp b/src/PrintAstVisitor.cpp index 9242b08..aa17343 100644 --- a/src/PrintAstVisitor.cpp +++ b/src/PrintAstVisitor.cpp @@ -1,6 +1,7 @@ #include "Header.h" #include +#include "Language_gen_y.hpp" template char* get_typename(T& object) { diff --git a/src/Program.cpp b/src/Program.cpp index 242d875..9755a0f 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -1,11 +1,5 @@ #include "Header.h" -Program::Program(Stmts *stmts) { - this->stmts = stmts; - node_children.reserve(1); - node_children.push_back(stmts); -} - void Program::declara_auxiliary_c_funcs() { std::vector arg_types; FunctionType *ftype; @@ -97,22 +91,6 @@ Value *Program::generate(Function *func, BasicBlock *block, BasicBlock *allocblo void Program::generate() { - // conversion between robcmp data types to llvm data types - robTollvmDataType[tvoid] = Type::getVoidTy(global_context); - robTollvmDataType[tbool] = Type::getInt1Ty(global_context); - robTollvmDataType[tchar] = Type::getInt8Ty(global_context); - robTollvmDataType[tint8] = Type::getInt8Ty(global_context); - robTollvmDataType[tint16] = Type::getInt16Ty(global_context); - robTollvmDataType[tint32] = Type::getInt32Ty(global_context); - robTollvmDataType[tint64] = Type::getInt64Ty(global_context); - robTollvmDataType[tint8u] = Type::getInt8Ty(global_context); - robTollvmDataType[tint16u] = Type::getInt16Ty(global_context); - robTollvmDataType[tint32u] = Type::getInt32Ty(global_context); - robTollvmDataType[tint64u] = Type::getInt64Ty(global_context); - robTollvmDataType[tfloat] = Type::getFloatTy(global_context); - robTollvmDataType[tdouble] = Type::getDoubleTy(global_context); - robTollvmDataType[tldouble] = Type::getFP128Ty(global_context); - mainmodule = new Module(build_filename, global_context); Builder = make_unique>(global_context); @@ -126,20 +104,13 @@ void Program::generate() { // global scope RobDbgInfo.push_scope(RobDbgInfo.cunit->getFile(), RobDbgInfo.cunit); - - for(int t = 0; t < __ldt_last; t++) { - RobDbgInfo.types[t] = DBuilder->createBasicType( - LanguageDataTypeNames[t], - LanguageDataTypeBitWidth[t], - LanguageDataTypeDwarfEnc[t] - ); - } } global_alloc = BasicBlock::Create(global_context, "global"); // generate the program! - stmts->generate(NULL, NULL, global_alloc); + for(auto n: node_children) + n->generate(NULL, NULL, global_alloc); if (debug_info) DBuilder->finalize(); diff --git a/src/Program.h b/src/Program.h index 0516ecc..12589ea 100644 --- a/src/Program.h +++ b/src/Program.h @@ -1,18 +1,16 @@ -#ifndef __PROGRAM_H__ -#define __PROGRAM_H__ + +#pragma once + #include "Node.h" class Program : public Node { -private: - Stmts *stmts; public: - Program(Stmts *stmts); - + + Program(Stmts &&stmts): Node(std::move(stmts.node_children)) {} + void declara_auxiliary_c_funcs(); Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); void generate(); }; - -#endif diff --git a/src/RobSymbol.h b/src/RobSymbol.h index 58bc49f..99cfe1a 100644 --- a/src/RobSymbol.h +++ b/src/RobSymbol.h @@ -8,8 +8,8 @@ class RobSymbol: public SourceLocation { unsigned int matrixLines; unsigned int matrixCols; Structure *structure; - LanguageDataType dt; - LanguageDataType pointee_dt; + BasicDataType dt; + BasicDataType pointee_dt; FunctionParams *params; bool isDeclaration; diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 941e49e..51104bb 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -40,7 +40,7 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc if (symbol == NULL) { Value *ret, *leftv; Value *exprv = expr->generate(func, block, allocblock); - LanguageDataType dt = expr->getResultType(block, allocblock); + BasicDataType dt = expr->getResultType(block, allocblock); if (!exprv) return NULL; @@ -56,13 +56,13 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc if (qualifier == qconst) ret = leftv = exprvc; else { - GlobalVariable *gv = new GlobalVariable(*mainmodule, robTollvmDataType[dt], + GlobalVariable *gv = new GlobalVariable(*mainmodule, buildTypes->llvmType(dt), false, GlobalValue::CommonLinkage, exprvc, name); ret = leftv = gv; if (debug_info) { auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", - funit, lineno, RobDbgInfo.types[dt], false); + funit, getLineNo(), buildTypes->diType(dt), false); gv->addDebugInfo(d); } } @@ -75,14 +75,14 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc ret = Builder->CreateStore(exprv, leftv, qualifier == qvolatile); if (debug_info) { - llvm::DIType *dty = RobDbgInfo.types[dt]; + llvm::DIType *dty = buildTypes->diType(dt); if (qualifier == qvolatile) { dty = DBuilder->createQualifiedType(dwarf::DW_TAG_volatile_type, dty); } DILocalVariable *d = DBuilder->createAutoVariable( - sp, name, funit, lineno, dty, true); + sp, name, funit, getLineNo(), dty, true); DBuilder->insertDeclare(leftv, d, DBuilder->createExpression(), - DILocation::get(sp->getContext(), lineno, colno, sp), allocblock); + DILocation::get(sp->getContext(), getLineNo(), getColNo(), sp), allocblock); } } @@ -98,7 +98,7 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc return NULL; } - Type *leftvty = robTollvmDataType[symbol->dt]; + Type *leftvty = buildTypes->llvmType(symbol->dt); qualifier = symbol->qualifier; Value *exprv = expr->generate(func, block, allocblock); Value *nvalue; @@ -112,7 +112,7 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc */ // Coerce the left side to the field size - exprv = Coercion::Convert(exprv, robTollvmDataType[field.fieldDataType], block, expr); + exprv = Coercion::Convert(exprv, buildTypes->llvmType(field.fieldDataType), block, expr); // Expand to the left side size exprv = Coercion::Convert(exprv, leftvty, block, expr); diff --git a/src/Scanner.cpp b/src/Scanner.cpp new file mode 100644 index 0000000..4c87931 --- /dev/null +++ b/src/Scanner.cpp @@ -0,0 +1,67 @@ + +#include "Header.h" +#include "Language_gen_y.hpp" + +int errorsfound = 0; +char *build_filename; +char *build_outputfilename; + +int USElex(YYSTYPE *yylval_param, location_t *yylloc_param, yyscan_t yyscanner) { + return MAINlex(yylval_param, yylloc_param, yyscanner); +} + +int MAINlex_init(yyscan_t* scanner); +void MAINset_in(FILE *_in_str, yyscan_t yyscanner); +int MAINlex_destroy(yyscan_t yyscanner); + +void yyerror(location_t *loc, yyscan_t scanner, const char *s) +{ + fprintf(stderr, "%s:%d:%d: %s\n", + build_filename, loc->first_line, loc->first_column, s); + errorsfound++; +} + +void USEerror(location_t *loc, yyscan_t scanner, const char *s) { + yyerror(loc, scanner, s); +} + +void MAINerror(location_t *loc, yyscan_t scanner, const char *s) { + yyerror(loc, scanner, s); +} + +void yyerrorcpp(const string& s, SourceLocation *n) { + string e = COLOR_RED "semantic error: " COLOR_RESET + s; + fprintf(stderr, "%s:%d:%d: %s\n", + build_filename, n->getLineNo(), n->getColNo(), s.c_str()); + errorsfound++; +} + +void yywarncpp(const string& s, SourceLocation *n) { + string e = COLOR_BLUE "semantic warning: " COLOR_RESET + s; + fprintf(stderr, "%s:%d:%d %s\n", + build_filename, n->getLineNo(), n->getColNo(), e.c_str()); +} + +bool parseFile(const char *source) { + + FILE *f = fopen(source, "r"); + if (f == NULL) { + fprintf(stderr, "Could not open file %s.\n", source); + return false; + } + + yyscan_t scanner; + MAINlex_init(&scanner); + MAINset_in(f, scanner); + MAINparse(scanner); + MAINlex_destroy(scanner); + + if (f) + fclose(f); + + return true; +} + +bool parseUseFile(const char *use) { + return false; +} diff --git a/src/Scanner.h b/src/Scanner.h new file mode 100644 index 0000000..28c8ba8 --- /dev/null +++ b/src/Scanner.h @@ -0,0 +1,28 @@ + +#pragma once + +#include +#include "SourceLocation.h" + +using namespace std; + +#define COLOR_RED "\x1b[31m" +#define COLOR_GREEN "\x1b[32m" +#define COLOR_YELLOW "\x1b[33m" +#define COLOR_BLUE "\x1b[34m" +#define COLOR_MAGENTA "\x1b[35m" +#define COLOR_CYAN "\x1b[36m" +#define COLOR_RESET "\x1b[0m" + +typedef void* yyscan_t; +extern int errorsfound; +extern char *build_filename; + +void yyerror(location_t *loc, yyscan_t scanner, const char *s); +void USEerror(location_t *loc, yyscan_t scanner, const char *s); +void MAINerror(location_t *loc, yyscan_t scanner, const char *s); +void yyerrorcpp(const string& s, SourceLocation *n); +void yywarncpp(const string& s, SourceLocation *n); + +bool parseFile(const char *source); +bool parseUseFile(const char *use); diff --git a/src/SourceLocation.h b/src/SourceLocation.h index bf0cca8..29818e5 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -1,38 +1,42 @@ #pragma once -extern int yylineno; -extern int yycolno; +typedef struct { + int first_line; + int first_column; + int last_line; + int last_column; +} location_t; class SourceLocation { protected: - int lineno; - int colno; + location_t sloc; public: SourceLocation() { - lineno = yylineno; - colno = yycolno; + //TODO: sloc = yylloc; } SourceLocation(location_t l) { - setLocation(l); + sloc = l; } virtual int getLineNo() { - return lineno; + return sloc.first_line; } virtual int getColNo() { - return colno; + return sloc.first_column; } virtual void setLocation(location_t l) { - lineno = l.first_line; - colno = l.first_column; + sloc = l; } virtual void setLocation(SourceLocation *s) { - lineno = s->lineno; - colno = s->colno; + sloc = s->sloc; + } + + virtual location_t *getLoct() { + return &sloc; } }; diff --git a/src/Stmts.cpp b/src/Stmts.cpp index 47ccc92..4d61a33 100644 --- a/src/Stmts.cpp +++ b/src/Stmts.cpp @@ -1,35 +1,29 @@ #include "Header.h" - Stmts::Stmts(Node *s) { - this->stmts.push_back(s); - } - - std::vector const& Stmts::children() const { - return stmts; - } - - void Stmts::append(Node *s) { - stmts.push_back(s); - } +void Stmts::append(Node *s) { + node_children.push_back(s); + if (s->hasName()) + update_names = true; +} - void Stmts::prepend(Node *s) { - // put after function declarations - auto last_func = stmts.begin(); - auto iterator = stmts.begin(); - while (iterator != stmts.end()) { - if ((*iterator)->isFunctionDecl()) - last_func = iterator; - iterator = std::next(iterator); - } - last_func = std::next(last_func); - stmts.insert(last_func, s); +void Stmts::prepend(Node *s) { + // put after function declarations + auto last_func = node_children.begin(); + auto iterator = node_children.begin(); + while (iterator != node_children.end()) { + if ((*iterator)->isFunctionDecl()) + last_func = iterator; + iterator = next(iterator); } + last_func = next(last_func); + node_children.insert(last_func, s); +} - Value *Stmts::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - for(Node *n: stmts) { - Value *b = n->generate(func, block, allocblock); - if (b && b->getValueID() == Value::BasicBlockVal) - block = (BasicBlock*)b; - } - return block; +Value *Stmts::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + for(Node *n: node_children) { + Value *b = n->generate(func, block, allocblock); + if (b && b->getValueID() == Value::BasicBlockVal) + block = (BasicBlock*)b; } + return block; +} diff --git a/src/Stmts.h b/src/Stmts.h index f7a1ac0..4643fcf 100644 --- a/src/Stmts.h +++ b/src/Stmts.h @@ -1,15 +1,15 @@ -#ifndef __STMTS_H__ -#define __STMTS_H__ + +#pragma once + #include "Node.h" class Stmts: public Node { -private: - std::vector stmts; public: Stmts() {}; - Stmts(Node *s); - virtual std::vector const& children() const override; + Stmts(Node *s) { + node_children.push_back(s); + } void append(Node *s); @@ -17,5 +17,3 @@ class Stmts: public Node { Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; }; - -#endif diff --git a/src/UserType.cpp b/src/UserType.cpp new file mode 100644 index 0000000..805f7cc --- /dev/null +++ b/src/UserType.cpp @@ -0,0 +1,22 @@ + +#include "Header.h" + +Value *UserType::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + + // semantic analysis + for(auto n : implements) { + Node *inode = findSymbol(n); + Interface *intf = dynamic_cast(inode); + if (!intf) { + yyerrorcpp("Interface " + n + " not defined.", this); + return NULL; + } + if (!intf->validateImplementation(this)) + return NULL; + } + + for(const auto n : symbols) { + printf("Will generate %s_%s function!\n", name.c_str(), n.first.c_str()); + } + return NULL; +} diff --git a/src/UserType.h b/src/UserType.h new file mode 100644 index 0000000..8c6b8b9 --- /dev/null +++ b/src/UserType.h @@ -0,0 +1,19 @@ + +#pragma once + +#include "Node.h" + +class UserType: public NamedNode { +private: + vector implements; + +public: + + UserType(const string name, Stmts &&stmts): NamedNode(name, std::move(stmts.node_children)) {} + + UserType(const string name, Stmts &&stmts, vector &&implements): + NamedNode(name, std::move(stmts.node_children)), + implements(std::move(implements)) {} + + virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; +}; diff --git a/src/main.cpp b/src/main.cpp index 213399a..d66e7bf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,19 +4,9 @@ #include "Header.h" -int errorsfound = 0; -int yycolno = 0; -int yycolnew = 0; -extern int yyparse(); -extern FILE *yyin; void print_llvm_ir(char opt_level); Function *AttachInterrupt::fattach = NULL; - -// file name -char *build_filename; -char *build_outputfilename; bool debug_info; -enum SupportedTargets currentTargetId; int main(int argc, char *argv[]) { @@ -36,6 +26,7 @@ int main(int argc, char *argv[]) { } // Compila o arquivo passado como parâmetro + FILE *source = NULL; int i = 1; while (i < argc) { if (strncmp(argv[i], "-O", 2) == 0) { @@ -53,27 +44,15 @@ int main(int argc, char *argv[]) { } else { build_filename = argv[i]; - yyin = fopen(build_filename, "r"); - if (yyin == NULL) { - fprintf(stderr, "Could not open file %s.\n", build_filename); - exit(1); - } } i++; } - // set current target - currentTargetId = native; //native - for(int t = native; t < __last_target; t++) { - if (strcmp(targetarch, supportedTargets[t].name) == 0) { - currentTargetId = static_cast(t); - break; - } - } + // set current target and basic build types + initTarget(targetarch); - yyparse(); - if (yyin) - fclose(yyin); + if (!parseFile(build_filename)) + exit(1); if (errorsfound > 0) { fprintf(stderr, "%d error(s) found.\n", errorsfound); From d9571420f1620f218a1708c8e58374eb251fc9b0 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 6 Aug 2023 09:30:38 -0300 Subject: [PATCH 026/117] New language features and general refactoring. - New language features: user types, interfaces, char consts... - Moves symbol table to the AST tree - Improves build speed and implements build with cmake - New test folder: migration of older tests in progress --- .gitignore | 1 + CMakeLists.txt | 70 +++++ Makefile | 9 +- lib/Makefile | 1 + lib/avr328p.rob | 84 ++++-- lib/avr5.S | 33 +++ macbuild | 6 + .../syntaxes/rob.tmLanguage.json | 8 +- rob.vim | 6 +- src/2018arm/nodeh_ext.h | 4 +- src/Array.cpp | 40 ++- src/Array.h | 50 +++- src/ArrayElements.cpp | 23 +- src/ArrayElements.h | 32 ++- src/AttachInterrupt.h | 50 ---- src/BackLLVM.cpp | 24 +- src/BackLLVM.h | 36 +++ src/BinaryOp.cpp | 91 +++--- src/BinaryOp.h | 21 +- src/BuildTypes.cpp | 105 +++++++ src/BuildTypes.h | 122 ++++---- src/Capsule.cpp | 4 +- src/Capsule.h | 9 +- src/Cast.cpp | 18 +- src/Cast.h | 13 +- src/CmpOp.cpp | 15 +- src/CmpOp.h | 4 +- src/Coercion.cpp | 10 +- src/Coercion.h | 17 +- src/Colors.h | 10 + src/DebugInfo.cpp | 19 +- src/Delay.cpp | 18 +- src/Delay.h | 4 +- src/Double.cpp | 5 +- src/Double.h | 6 +- src/Field.cpp | 30 ++ src/Field.h | 20 +- src/FlexDependencies.h | 23 ++ src/FlipOp.cpp | 15 +- src/FlipOp.h | 11 +- src/Float.cpp | 5 +- src/Float.h | 7 +- src/Float128.cpp | 5 +- src/Float128.h | 6 +- src/FunctionCall.cpp | 119 +++++++- src/FunctionCall.h | 36 ++- src/FunctionDecl.cpp | 59 ++-- src/FunctionDecl.h | 57 ++-- src/FunctionImpl.cpp | 146 ++++++---- src/FunctionImpl.h | 53 ++-- src/FunctionParams.cpp | 15 +- src/FunctionParams.h | 39 ++- src/Header.h | 181 +----------- src/HeaderExternals.h | 31 ++ src/HeaderGlobals.h | 51 ++++ src/If.cpp | 38 +-- src/If.h | 11 +- src/InPort.cpp | 12 +- src/InPort.h | 2 +- src/InlineAssembly.cpp | 5 +- src/InlineAssembly.h | 4 +- src/Int1.cpp | 9 +- src/Int1.h | 31 +- src/Int16.cpp | 9 +- src/Int16.h | 13 +- src/Int32.cpp | 9 +- src/Int32.h | 19 +- src/Int64.cpp | 10 +- src/Int64.h | 20 +- src/Int8.cpp | 9 +- src/Int8.h | 37 +-- src/Interface.cpp | 22 +- src/Interface.h | 11 +- src/Language.l | 54 ++-- src/Language.y | 252 ++++++++--------- src/LanguageHeader.y | 18 +- src/LanguageUse.y | 267 ++++++++++++------ src/Load.cpp | 113 ++++---- src/Load.h | 26 +- src/LoadArray.cpp | 44 +-- src/LoadArray.h | 17 +- src/LoadMatrix.h | 14 +- src/Loop.cpp | 22 +- src/Loop.h | 8 +- src/Matrix.cpp | 52 ++-- src/Matrix.h | 25 +- src/MatrixElements.cpp | 25 +- src/MatrixElements.h | 31 +- src/Node.cpp | 107 ++++++- src/Node.h | 102 ++++--- src/OutPort.cpp | 39 +-- src/OutPort.h | 10 +- src/ParamsCall.cpp | 3 +- src/ParamsCall.h | 4 + src/Pointer.cpp | 77 +++-- src/Pointer.h | 32 +-- src/Print.cpp | 61 ++-- src/Print.h | 2 +- src/PrintAstVisitor.cpp | 58 ++-- src/PrintAstVisitor.h | 48 ++-- src/Program.cpp | 47 +-- src/Program.h | 10 +- src/RecursiveVisitor.cpp | 4 +- src/RecursiveVisitor.h | 13 +- src/Return.cpp | 24 +- src/Return.h | 15 +- src/RobSymbol.h | 27 -- src/Scalar.cpp | 179 +++++++----- src/Scalar.h | 42 ++- src/Scanner.cpp | 124 ++++++-- src/Scanner.h | 24 +- src/Semantic.cpp | 2 +- src/Semantic.h | 7 +- src/SourceLocation.h | 19 +- src/Stmts.cpp | 29 -- src/Stmts.h | 19 -- src/String.cpp | 5 - src/String.h | 13 - src/StringConst.cpp | 6 + src/StringConst.h | 12 + src/SymbolizeTree.h | 60 ++++ src/UpdateArray.cpp | 28 +- src/UpdateArray.h | 14 +- src/UpdateMatrix.h | 12 +- src/UserType.cpp | 71 ++++- src/UserType.h | 17 +- src/Variable.h | 40 +++ src/Visitor.cpp | 3 - src/Visitor.h | 114 +++++--- src/While.cpp | 35 +-- src/While.h | 14 +- src/main.cpp | 26 +- testnew/avr328p/Makefile | 46 +++ testnew/avr328p/aux/serial.rob | 79 ++++++ testnew/avr328p/itoa.rob | 128 +++++++++ testnew/avr328p/out/itoa | Bin 0 -> 6116 bytes testnew/avr328p/out/register | Bin 0 -> 5708 bytes testnew/avr328p/out/simple | Bin 0 -> 2940 bytes testnew/avr328p/register.c | 29 ++ testnew/avr328p/register.rob | 84 ++++++ testnew/avr328p/run_avr | 1 + testnew/avr328p/runtest.sh | 3 + testnew/avr328p/simple.rob | 5 + testnew/general/Makefile | 30 ++ testnew/general/bellmanford.rob | 78 +++++ testnew/general/bitstruct.rob | 35 +++ testnew/general/fibonacci.rob | 32 +++ testnew/general/itoa.rob | 123 ++++++++ testnew/general/out/bellmanford | Bin 0 -> 33088 bytes testnew/general/out/bitstruct | Bin 0 -> 16664 bytes testnew/general/out/fibonacci | Bin 0 -> 16600 bytes testnew/general/out/itoa | Bin 0 -> 33248 bytes testnew/general/out/simple | Bin 0 -> 16560 bytes testnew/general/out/simplescope | Bin 0 -> 16560 bytes testnew/general/out/sort | Bin 0 -> 33024 bytes testnew/general/out/type | Bin 0 -> 16744 bytes testnew/general/runtest.sh | 19 ++ testnew/general/simple.rob | 6 + testnew/general/simplescope.rob | 10 + testnew/general/sort.rob | 37 +++ testnew/general/type.rob | 38 +++ 161 files changed, 3690 insertions(+), 1807 deletions(-) create mode 100644 CMakeLists.txt create mode 100755 macbuild create mode 100644 src/BackLLVM.h create mode 100644 src/BuildTypes.cpp create mode 100644 src/Colors.h create mode 100644 src/Field.cpp create mode 100644 src/FlexDependencies.h create mode 100644 src/HeaderExternals.h create mode 100644 src/HeaderGlobals.h delete mode 100644 src/RobSymbol.h delete mode 100644 src/Stmts.cpp delete mode 100644 src/Stmts.h delete mode 100644 src/String.cpp delete mode 100644 src/String.h create mode 100644 src/StringConst.cpp create mode 100644 src/StringConst.h create mode 100644 src/SymbolizeTree.h create mode 100644 src/Variable.h delete mode 100644 src/Visitor.cpp create mode 100644 testnew/avr328p/Makefile create mode 100644 testnew/avr328p/aux/serial.rob create mode 100644 testnew/avr328p/itoa.rob create mode 100755 testnew/avr328p/out/itoa create mode 100755 testnew/avr328p/out/register create mode 100755 testnew/avr328p/out/simple create mode 100644 testnew/avr328p/register.c create mode 100644 testnew/avr328p/register.rob create mode 120000 testnew/avr328p/run_avr create mode 100755 testnew/avr328p/runtest.sh create mode 100644 testnew/avr328p/simple.rob create mode 100644 testnew/general/Makefile create mode 100644 testnew/general/bellmanford.rob create mode 100644 testnew/general/bitstruct.rob create mode 100644 testnew/general/fibonacci.rob create mode 100644 testnew/general/itoa.rob create mode 100755 testnew/general/out/bellmanford create mode 100755 testnew/general/out/bitstruct create mode 100755 testnew/general/out/fibonacci create mode 100755 testnew/general/out/itoa create mode 100755 testnew/general/out/simple create mode 100755 testnew/general/out/simplescope create mode 100755 testnew/general/out/sort create mode 100755 testnew/general/out/type create mode 100755 testnew/general/runtest.sh create mode 100644 testnew/general/simple.rob create mode 100644 testnew/general/simplescope.rob create mode 100644 testnew/general/sort.rob create mode 100644 testnew/general/type.rob diff --git a/.gitignore b/.gitignore index 3eab1e2..38bae9f 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,4 @@ llvm-ranlib avr-ld .vscode refdatasheets +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c234ba6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,70 @@ +cmake_minimum_required(VERSION 3.0.0) +cmake_policy(SET CMP0054 NEW) + +set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -fno-exceptions") +set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -flto -fno-exceptions") +add_compile_definitions() + +project(robcmp) + +set(CMAKE_CXX_STANDARD 17) + +message(STATUS "CC Compiler used: ${CC}") + +find_package(LLVM REQUIRED CONFIG) +find_package(FLEX 2.6 REQUIRED) +find_package(BISON 3.8 REQUIRED) + +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +include_directories(${LLVM_INCLUDE_DIRS} ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) +separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) +add_definitions(${LLVM_DEFINITIONS_LIST}) + +file(GLOB robcmp_SRC CONFIGURE_DEPENDS + "src/*.cpp" +) + +flex_target(lexer "${CMAKE_CURRENT_SOURCE_DIR}/src/Language.l" "${CMAKE_BINARY_DIR}/Language_l.cpp") +bison_target(scanner_main + "${CMAKE_BINARY_DIR}/Language_gen.y" + "${CMAKE_BINARY_DIR}/Language_gen.cpp" + DEFINES_FILE "${CMAKE_BINARY_DIR}/Language_gen_y.hpp" + COMPILE_FLAGS "-Wall -Wno-deprecated") +bison_target(scanner_use + "${CMAKE_BINARY_DIR}/LanguageUse_gen.y" + "${CMAKE_BINARY_DIR}/LanguageUse_gen.cpp" + COMPILE_FLAGS "-Wall -Wno-deprecated") + +# Language_gen.y +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/Language_gen.y + COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageHeader.y ${CMAKE_CURRENT_SOURCE_DIR}/src/Language.y > ${CMAKE_BINARY_DIR}/Language_gen.y + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageHeader.y ${CMAKE_CURRENT_SOURCE_DIR}/src/Language.y +) +# LanguageUse_gen.y +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/LanguageUse_gen.y + COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageHeader.y ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageUse.y > ${CMAKE_BINARY_DIR}/LanguageUse_gen.y + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageHeader.y ${CMAKE_CURRENT_SOURCE_DIR}/src/LanguageUse.y +) +add_custom_target(parsers + DEPENDS ${CMAKE_BINARY_DIR}/Language_gen.y ${CMAKE_BINARY_DIR}/LanguageUse_gen.y) + +add_executable(robcmp ${FLEX_lexer_OUTPUTS} ${BISON_scanner_main_OUTPUTS} ${BISON_scanner_use_OUTPUTS} ${robcmp_SRC}) +add_flex_bison_dependency(lexer scanner_main) +add_flex_bison_dependency(lexer scanner_use) +add_dependencies(robcmp parsers) + +llvm_map_components_to_libnames(llvm_libs support core irreader passes + armasmparser armcodegen + avrasmparser avrcodegen + x86asmparser x86codegen + xtensaasmparser xtensacodegen) + +target_link_libraries(robcmp ${llvm_libs}) + +set_target_properties(robcmp PROPERTIES + VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + VS_DEBUGGER_COMMAND_ARGUMENTS "-a avr328p -Oz ../platformio/samples/avr328p-blink/src/main.rob") diff --git a/Makefile b/Makefile index 2a20751..ec56055 100644 --- a/Makefile +++ b/Makefile @@ -41,11 +41,16 @@ all: src/out $(COMPILER_NAME) flex -o $@ $< .PRECIOUS : %_l.cpp %_y.cpp %_y.hpp +.SECONDARY : $(SCANNERS) + +-include $(CPPS:%.o=%.d) main.cpp : %_l.cpp %_y.cpp %_y.hpp %_gen.y : src/LanguageHeader.y %.y + -chmod u+w $@ cat $^ > $@ + chmod u-w $@ %_y.cpp: %.y bison -Wall --defines=$(patsubst %.cpp,%.hpp,$@) -o $@ $< @@ -54,10 +59,10 @@ main.cpp : %_l.cpp %_y.cpp %_y.hpp $(SED) 's/\"syntax\ error,/COLOR_RED\ \"syntax\ error:\"\ COLOR_RESET\"/' -i $@ $(COMPILER_NAME): ${YACS} ${LEXS} ${CPPS} - ${CC} -std=c++11 ${FLAGS} ${DFLAGS} ${SRC}/out/*.o ${LLVMLIBS} -o $(BIN)/$@ + ${CC} ${FLAGS} ${DFLAGS} -std=c++17 ${SRC}/out/*.o ${LLVMLIBS} -o $(BIN)/$@ src/out/%.o: src/%.cpp - ${CC} -std=c++11 ${LLVMFLAGS} ${FLAGS} ${DFLAGS} -c $< -o $@ + ${CC} ${LLVMFLAGS} ${FLAGS} ${DFLAGS} -MMD -std=c++17 -c $< -o $@ src/out: mkdir ${SRC}/out diff --git a/lib/Makefile b/lib/Makefile index 0d18991..82da0c3 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -5,5 +5,6 @@ avr5.o: avr5.s @#here we are interested in the fastest possible code, intead of size avr-gcc -mmcu=avr5 -O3 -c avr5.S + clean: rm -f avr5.o diff --git a/lib/avr328p.rob b/lib/avr328p.rob index 6f0cf38..21f3221 100644 --- a/lib/avr328p.rob +++ b/lib/avr328p.rob @@ -5,36 +5,38 @@ void main(); void __init(); void __bad_irq(); +void __do_copy_data(); +void __do_clear_bss(); void __vectors() { /* atmega328p has 26 interruptions */ /* FIXME: provide proper interrupt functions instead of __bad_irq after implementing "weak" attribute for functions */ - asm "jmp __init"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; - asm "jmp __bad_irq"; + asm "rjmp __init"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; + asm "rjmp __bad_irq"; } void __bad_irq() { @@ -42,15 +44,37 @@ void __bad_irq() { __vectors(); } -register int8 SREG at 0x3f; -register int16 STACK at 0x3d; +const offset = 0; +register int8 SREG at (0x3f + offset); +register int16 STACK at (0x3d + offset); void __init() { - // clear SREG, set STACK at RAM top and call main - // if main returns, reset. + // clear r1 (zero reg) + asm "eor r1, r1"; + + // clear SREG SREG = 0; + //asm "out 0x3f, r1"; + + // set STACK at RAM top and call main STACK = 0x0AFF; + /*asm "ldi r28, 0xFF"; + asm "ldi r29, 0x0A"; + asm "out 0x3e, r29"; + asm "out 0x3d, r28";*/ + + // copy global vars init data + //__do_copy_data(); + + // clear vars initialized as zero + //__do_clear_bss(); + main(); + + // if main returns, reset. __vectors(); } +void sleep_cpu() { + asm "sleep"; +} diff --git a/lib/avr5.S b/lib/avr5.S index fb82ec0..7afe9d3 100644 --- a/lib/avr5.S +++ b/lib/avr5.S @@ -324,3 +324,36 @@ __divmodhi4_neg2: __divmodhi4_exit: ret ENDF __divmodhi4 + +/* + * Clear the bss data + */ +DEFUN __do_clear_bss + ldi r17, hi8(__bss_end) + ldi r26, lo8(__bss_start) + ldi r27, hi8(__bss_start) + rjmp .do_clear_bss_start +.do_clear_bss_loop: + st X+, __zero_reg__ +.do_clear_bss_start: + cpi r26, lo8(__bss_end) + cpc r27, r17 + brne .do_clear_bss_loop +ENDF __do_clear_bss + + +DEFUN __do_copy_data + ldi r17, hi8(__data_end) + ldi r26, lo8(__data_start) + ldi r27, hi8(__data_start) + ldi r30, lo8(__data_load_start) + ldi r31, hi8(__data_load_start) + rjmp .do_copy_data_start +.do_copy_data_loop: + lpm r0, Z+ + st X+, r0 +.do_copy_data_start: + cpi r26, lo8(__data_end) + cpc r27, r17 + brne .do_copy_data_loop +ENDF __do_copy_data diff --git a/macbuild b/macbuild new file mode 100755 index 0000000..fb18575 --- /dev/null +++ b/macbuild @@ -0,0 +1,6 @@ +CXX=/usr/local/robllvm/bin/clang++ +CC=/usr/local/robllvm/bin/clang +export CXX +export CC +cmake -DCMAKE_BUILD_TYPE="Debug" .. +#cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_BUILD_TYPE="Debug" .. diff --git a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json index b5f19d6..1474363 100644 --- a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json +++ b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json @@ -42,7 +42,7 @@ "keywords": { "patterns": [{ "name": "keyword.control.rob", - "match": "\\b(while|loop|if|delay|print|return|register|at|volatile|const|type|interface|implements|use)\\b" + "match": "\\b(while|loop|if|else|delay|print|return|register|at|volatile|const|type|interface|implements|use|and|or)\\b" }] }, "types": { @@ -62,6 +62,12 @@ "patterns": [{ "name": "constant.numeric.rob", "match": "\\b(\\d+\\.\\d+L?D?|\\d+|0x[0-9a-fA-F]+|0b[0-1]+)\\b" + },{ + "name": "constant.numeric.rob", + "match": "'\\\\?.'" + },{ + "name": "constant.numeric.rob", + "match": "\\b(true|false)\\b" }] }, "functions": { diff --git a/rob.vim b/rob.vim index f528282..534b8c4 100644 --- a/rob.vim +++ b/rob.vim @@ -1,13 +1,13 @@ " Vim syntax file " Language: Robcmp Small LLVM Arduino Frontend " Maintainer: Thiago Borges de Oliveira -" Latest Revision: 1 July 2023 +" Latest Revision: 4 Aug 2023 if exists("b:current_syntax") finish endif -syn keyword keywords while loop if delay print return register at volatile const asm +syn keyword keywords while loop if else delay print return register at volatile const asm type syn keyword typeKeywords void char int8 int16 int32 int64 long unsigned float double bool syn keyword operatorKeywords and or quando esta servo syn keyword booleanKeyword true false @@ -15,6 +15,7 @@ syn keyword booleanKeyword true false syn match integerConstants "\<\d\+\>" syn match hexConstants "\<0x[0-9a-fA-F]\+\>" syn match floatConstants "\<\d\+\.\d\+L\?D\?\>" +syn match charConstants "'\\\?.'" syn match inPortKey "\" syn match outPortKey "\" syn match stringSpecial "\\." @@ -30,6 +31,7 @@ hi def link keywords Repeat hi def link integerConstants Constant hi def link hexConstants Constant hi def link floatConstants Constant +hi def link charConstants Constant hi def link stringConstant String hi def link stringSpecial Special hi def link inPortKey Identifier diff --git a/src/2018arm/nodeh_ext.h b/src/2018arm/nodeh_ext.h index d81e9a8..f748312 100644 --- a/src/2018arm/nodeh_ext.h +++ b/src/2018arm/nodeh_ext.h @@ -8,7 +8,7 @@ class ServoGoto: public Node { public: ServoGoto(Node *position): pos(position) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { // value for the two parameters vector args; args.push_back(pos->generate(func, block, allocblock)); @@ -37,7 +37,7 @@ class StepperGoto: public Node { public: StepperGoto(int stepper, Node *position): stp(stepper), pos(position) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { // value for the two parameters Int16 nstp(stp); diff --git a/src/Array.cpp b/src/Array.cpp index 9d51e79..2c6dfd1 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -1,13 +1,23 @@ -#include "Header.h" +#include "Array.h" +#include "ArrayElements.h" +#include "Coercion.h" +#include "BackLLVM.h" +#include "Visitor.h" +#include "Int16.h" -Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Array::Array(const char *n, ArrayElements *aes) : LinearDataStructure(n), elements(aes) { + NamedConst *nc = new NamedConst("size", getNodeForIntConst(aes->getArraySize())); + addChild(nc); +} + +Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { //Create an Array of Type Int8, and Size = size. size = elements->getArraySize(); Value *array_size = ConstantInt::get(Type::getInt8Ty(global_context), size); //Get Type of elements in Array of Elements, and define as I. - BasicDataType pointee_dt = elements->getArrayType(block, allocblock); - Type* I = buildTypes->llvmType(pointee_dt); + element_dt = elements->getArrayType(func); + Type* I = buildTypes->llvmType(element_dt); //Declare array type. ArrayType* arrayType = ArrayType::get(I, size); @@ -42,7 +52,6 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock auto funit = RobDbgInfo.currFile(); //Allocate array. - Value* var; if (allocblock == global_alloc) { // when alloc is global vector constantValues; constantValues.reserve(elementValues.size()); @@ -51,10 +60,12 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock ArrayRef constantRefs(constantValues); GlobalVariable *gv = new GlobalVariable(*mainmodule, arrayType, false, GlobalValue::ExternalLinkage, ConstantArray::get(arrayType, constantRefs), name); - var = gv; + //gv->setDSOLocal(true); + gv->setAlignment(Align(2)); + alloc = gv; if (debug_info) { - auto di_ptr = DBuilder->createPointerType(buildTypes->diType(pointee_dt), + auto di_ptr = DBuilder->createPointerType(buildTypes->diType(getElementDt()), buildTypes->bitWidth(currentTarget.pointerType)); auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", funit, this->getLineNo(), di_ptr, false); @@ -63,7 +74,7 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock } else { Builder->SetInsertPoint(allocblock); - var = Builder->CreateAlloca(arrayType, 0, name); + alloc = Builder->CreateAlloca(arrayType, globalAddrSpace, 0, name); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); @@ -73,16 +84,15 @@ Value *Array::generate(Function *func, BasicBlock *block, BasicBlock *allocblock for(unsigned index = 0; index < elementValues.size(); index++) { Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), index); Value* indexList[2] = {zero, idx}; - Value* gep = Builder->CreateGEP(arrayType, var, + Value* gep = Builder->CreateGEP(arrayType, alloc, ArrayRef(indexList), "elem"); store = Builder->CreateStore(elementValues[index], gep, false); } } - //Add array to table of symbols. - RobSymbol *rs = new RobSymbol(var); - rs->dt = tarray; - rs->pointee_dt = pointee_dt; - tabelasym[allocblock][name] = rs; - return var; + return alloc; +} + +void Array::accept(Visitor& v) { + v.visit(*this); } diff --git a/src/Array.h b/src/Array.h index 1ad92dd..66efe1a 100644 --- a/src/Array.h +++ b/src/Array.h @@ -1,12 +1,54 @@ #pragma once -class Array: public Node { +#include "Node.h" +#include "Variable.h" +#include "ArrayElements.h" + +class ArrayElements; + +class NamedConst: public NamedNode { +protected: + Node *value; +public: + NamedConst(const char *name, Node *value) : NamedNode(name), value(value) { + dt = value->getDataType(); + } + virtual Value *getLLVMValue(Node *stem) override { + return value->generate(NULL, NULL, NULL); //FIXME + } + virtual bool isConstExpr() override { + return true; + } +}; + +class LinearDataStructure: public Variable { +protected: + DataType element_dt = BuildTypes::undefinedType; +public: + LinearDataStructure(const char *n): Variable(n) {} + virtual Node *getElementIndex(Node *p1, Node *p2) = 0; + virtual DataType getElementDt() { + return element_dt; + } +}; + +class Array: public LinearDataStructure { private: - string name; unsigned int size; ArrayElements *elements; public: - Array(const char *n, ArrayElements *aes) : name(n), elements(aes) { } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + Array(const char *n, ArrayElements *aes); + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual Node *getElementIndex(Node *p1, Node *p2) override { + return p1; + } + + std::vector getElements() { + return elements->getElements(); + } + + virtual void accept(Visitor& v) override; }; diff --git a/src/ArrayElements.cpp b/src/ArrayElements.cpp index c635316..35a32e8 100644 --- a/src/ArrayElements.cpp +++ b/src/ArrayElements.cpp @@ -1,27 +1,28 @@ -#include "Header.h" + +#include "ArrayElements.h" ArrayElements::ArrayElements() {}; -void ArrayElements::append(ArrayElement& e) { +void ArrayElements::append(ArrayElement *e) { elements.push_back(e); }; -unsigned ArrayElements::getArraySize() const { +unsigned ArrayElements::getArraySize() { unsigned r = 0; for(auto& i : elements) - r += i.count; + r += i->count; return r; }; -unsigned ArrayElements::getStructSize() const { +unsigned ArrayElements::getStructSize() { return elements.size(); } -BasicDataType ArrayElements::getArrayType(BasicBlock *block, BasicBlock *allocblock) const { +DataType ArrayElements::getArrayType(FunctionImpl *func) { unsigned intsize = 0; unsigned floatsize = 0; for(auto& i : elements) { - BasicDataType dt = i.value->getResultType(block, allocblock); + DataType dt = i->value->getDataType(); if (buildTypes->isIntegerDataType(dt) && intsize < buildTypes->bitWidth(dt)) intsize = buildTypes->bitWidth(dt); @@ -53,10 +54,10 @@ BasicDataType ArrayElements::getArrayType(BasicBlock *block, BasicBlock *allocbl } } -Node *ArrayElements::getStructElement(int position) const { - return elements[position].value; +Node *ArrayElements::getStructElement(int position) { + return elements[position]->value; } -unsigned ArrayElements::getElementCount(int position) const { - return elements[position].count; +unsigned ArrayElements::getElementCount(int position) { + return elements[position]->count; } diff --git a/src/ArrayElements.h b/src/ArrayElements.h index 24232dd..64dfe40 100644 --- a/src/ArrayElements.h +++ b/src/ArrayElements.h @@ -1,21 +1,29 @@ -#ifndef __ARRAY_ELEMENT_H__ -#define __ARRAY_ELEMENT_H__ + +#pragma once #include "Node.h" +class ArrayElement { +public: + Node *value; + unsigned count; + ArrayElement(Node *value, unsigned count): value(value), count(count) {} +}; + class ArrayElements { private: + std::vector elements; public: - std::vector elements; ArrayElements(); - void append(ArrayElement& e); + void append(ArrayElement *e); - unsigned getArraySize() const; - unsigned getStructSize () const; - unsigned getElementCount (int position) const; - Node *getStructElement (int position) const; - BasicDataType getArrayType(BasicBlock *block, BasicBlock *allocblock) const; + unsigned getArraySize(); + unsigned getStructSize (); + unsigned getElementCount (int position); + Node *getStructElement (int position); + DataType getArrayType(FunctionImpl *func); + + std::vector const& getElements() { + return elements; + } }; - -#endif - diff --git a/src/AttachInterrupt.h b/src/AttachInterrupt.h index 2e024a1..43081a7 100644 --- a/src/AttachInterrupt.h +++ b/src/AttachInterrupt.h @@ -1,55 +1,5 @@ #ifndef __ATTACHINTERRUPT_H__ #define __ATTACHINTERRUPT_H__ -#include "Node.h" -class AttachInterrupt: public Node { -private: - string fname; - int port; - int event; - static Function *fattach; -public: - AttachInterrupt(int _port, string _fname, int _event) { - this->fname = _fname; - this->port = _port; - this->event = _event; - } - - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - - auto symbol = search_symbol(fname); - assert(symbol != NULL); - Value *cfunc = symbol->value; - - // called func type (the function that is attached to interruption) - std::vector arg_types; - FunctionType *fcalledtype = FunctionType::get(Type::getVoidTy(global_context), - arg_types, false); - - // setup arduino attachInterrupt function - if (!fattach) { - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - arg_types.push_back(fcalledtype->getPointerTo()); - arg_types.push_back(Type::getInt16Ty(global_context)); - - FunctionType *ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - - fattach = Function::Create(ftype, Function::ExternalLinkage, "attachInterrupt", mainmodule); - fattach->setCallingConv(CallingConv::C); - } - - vector args; - args.push_back(ConstantInt::get(Type::getInt8Ty(global_context), port)); - args.push_back(cfunc); - args.push_back(ConstantInt::get(Type::getInt16Ty(global_context), event)); - - ArrayRef argsRef(args); - return CallInst::Create(fattach, argsRef, "", block); - } -}; - -extern std::vector vectorglobal; #endif diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index e6d18d8..c628aa9 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -1,4 +1,6 @@ + #include + #include #include #include @@ -10,17 +12,15 @@ #include #include #include - #include #include - #include #include #include #include #include -#include "Header.h" +#include "BackLLVM.h" using namespace llvm; @@ -33,20 +33,9 @@ std::unique_ptr DBuilder; struct DebugInfo RobDbgInfo; std::unique_ptr buildTypes; -// interruptions -std::vector vectorglobal; - -// symbol table -std::map> tabelasym; - -// arduino functions -Function *analogWrite; -Function *analogRead; -Function *delay; -Function *delayMicroseconds; -Function *init; -Function *print; -Function *i16div; +unsigned int globalAddrSpace = 0; +enum SupportedTargets currentTargetId; +extern char *build_outputfilename; void print_llvm_ir(char opt_level) { @@ -116,6 +105,7 @@ void print_llvm_ir(char opt_level) { } legacy::PassManager pass_codegen; targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, llvm::CGFT_ObjectFile); + //targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, llvm::CGFT_AssemblyFile); pass_codegen.run(*mainmodule); dest.flush(); } else { diff --git a/src/BackLLVM.h b/src/BackLLVM.h new file mode 100644 index 0000000..0d7ffda --- /dev/null +++ b/src/BackLLVM.h @@ -0,0 +1,36 @@ + +#pragma once + +#include "BuildTypes.h" + +extern std::unique_ptr> Builder; + +typedef struct { + const char *name; + const char *triple; + const char *cpu; + const char *features; + const DataType pointerType; +} TargetInfo; + +extern unsigned int globalAddrSpace; +enum SupportedTargets {native, avr328p, stm32f1, esp32, __last_target}; +extern enum SupportedTargets currentTargetId; +#define currentTarget (supportedTargets[currentTargetId]) + +static TargetInfo supportedTargets[__last_target] = { + {"", "", "", "", tint64}, // default target + {"avr328p", "avr", "atmega328p", "+avr5", tint16}, + {"stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, + {"esp32", "xtensa", "", "", tint32}, +}; + +static void initTarget(const char *targetarch) { + currentTargetId = native; //native + for(int t = native; t < __last_target; t++) { + if (strcmp(targetarch, supportedTargets[t].name) == 0) { + currentTargetId = static_cast(t); + break; + } + } +} diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index b860369..544b070 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -1,18 +1,20 @@ -#include "Header.h" -#include "Int8.h" +#include "FlexDependencies.h" #include "Language_gen_y.hpp" +#include "BinaryOp.h" +#include "Int8.h" +#include "Coercion.h" + BinaryOp::BinaryOp(Node *l, int op, Node *r) { this->lhsn = l; this->rhsn = r; this->op = op; - this->node_children.reserve(2); - this->node_children.push_back(lhsn); - this->node_children.push_back(rhsn); + this->addChild(lhsn); + this->addChild(rhsn); } Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, - Function *func, BasicBlock *block, BasicBlock *allocblock) { + FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { Value *lhs = lhsn->generate(func, block, allocblock); Value *rhs = rhsn->generate(func, block, allocblock); @@ -22,7 +24,7 @@ Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, } Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, - enum Instruction::BinaryOps opflt, Function *func, BasicBlock *block, BasicBlock *allocblock) { + enum Instruction::BinaryOps opflt, FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { Value *lhs = lhsn->generate(func, block, allocblock); Value *rhs = rhsn->generate(func, block, allocblock); @@ -49,7 +51,7 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, if (opint == Instruction::Shl || opint == Instruction::LShr) { // zext the left operator if we know the rside bitwidth Constant *c = NULL; - if (rhsn->isConstExpr(block, allocblock)) { + if (rhsn->isConstExpr()) { Value *v = rhsn->generate(NULL, block, allocblock); c = dyn_cast(v); } @@ -109,42 +111,45 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, return Builder->CreateBinOp(llvmop, lhs, rhs, "binop"); } -BasicDataType BinaryOp::getResultType(BasicBlock *block, BasicBlock *allocblock) { - BasicDataType lty = lhsn->getResultType(block, allocblock); - BasicDataType rty = rhsn->getResultType(block, allocblock); - if (buildTypes->isIntegerDataType(lty) && buildTypes->isIntegerDataType(rty)) { - if (op == TOK_LSHIFT || op == TOK_RSHIFT) { - // zext the left operator if we know the rside bitwidth - Constant *c = NULL; - if (rhsn->isConstExpr(block, allocblock)) { - Value *v = rhsn->generate(NULL, block, allocblock); - c = dyn_cast(v); - } - if (c) { - int64_t v = c->getUniqueInteger().getZExtValue(); - if (buildTypes->bitWidth(lty) < v) { - if (v >= 8 && v <= 15) - return tint16; - else if (v >= 16 && v <= 31) - return tint32; - else if (v >= 32 && v <= 63) - return tint64; - else - return tvoid; +DataType BinaryOp::getDataType() { + if (dt == BuildTypes::undefinedType) { + DataType lty = lhsn->getDataType(); + DataType rty = rhsn->getDataType(); + if (buildTypes->isIntegerDataType(lty) && buildTypes->isIntegerDataType(rty)) { + if (op == TOK_LSHIFT || op == TOK_RSHIFT) { + // zext the left operator if we know the rside bitwidth + Constant *c = NULL; + if (rhsn->isConstExpr()) { + Value *v = rhsn->generate(NULL, NULL, NULL); + c = dyn_cast(v); + } + if (c) { + int64_t v = c->getUniqueInteger().getZExtValue(); + if (buildTypes->bitWidth(lty) < v) { + if (v >= 8 && v <= 15) + dt = tint16; + else if (v >= 16 && v <= 31) + dt = tint32; + else if (v >= 32 && v <= 63) + dt = tint64; + else + dt = tvoid; + } } } + dt = buildTypes->bitWidth(lty) > buildTypes->bitWidth(rty) ? lty : rty; + + } else { + if (buildTypes->isIntegerDataType(lty)) + dt = rty; + else + dt = lty; } - return buildTypes->bitWidth(lty) > buildTypes->bitWidth(rty) ? lty : rty; - - } else { - if (buildTypes->isIntegerDataType(lty)) - return rty; - else - return lty; } + return dt; } -Value *BinaryOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *BinaryOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { RobDbgInfo.emitLocation(this); switch (op) { case '+' : return binary_operator(Instruction::Add, Instruction::FAdd, func, block, allocblock); @@ -163,11 +168,7 @@ Value *BinaryOp::generate(Function *func, BasicBlock *block, BasicBlock *allocbl } } -void BinaryOp::accept(Visitor& v) { - v.visit(*this); -} - -bool BinaryOp::isConstExpr(BasicBlock *block, BasicBlock *allocblock) { - return lhsn->isConstExpr(block, allocblock) && - rhsn->isConstExpr(block, allocblock); +bool BinaryOp::isConstExpr() { + return lhsn->isConstExpr() && + rhsn->isConstExpr(); } diff --git a/src/BinaryOp.h b/src/BinaryOp.h index eb23193..cf6413b 100644 --- a/src/BinaryOp.h +++ b/src/BinaryOp.h @@ -1,5 +1,6 @@ -#ifndef __BINARYOP_H__ -#define __BINARYOP_H__ + +#pragma once + #include "Node.h" class BinaryOp: public Node { @@ -7,24 +8,22 @@ class BinaryOp: public Node { int op; Node *lhsn; Node *rhsn; + public: BinaryOp(Node *l, int op, Node *r); Value *logical_operator(enum Instruction::BinaryOps op, - Function *func, BasicBlock *block, BasicBlock *allocblock); + FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); Value *binary_operator(enum Instruction::BinaryOps opint, - enum Instruction::BinaryOps opflt, Function *func, BasicBlock *block, BasicBlock *allocblock); + enum Instruction::BinaryOps opflt, FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - - virtual void accept(Visitor &v) override; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; int getOperator() const { return op; }; - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; + virtual DataType getDataType() override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; + virtual bool isConstExpr() override; + }; - -#endif diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp new file mode 100644 index 0000000..9b15614 --- /dev/null +++ b/src/BuildTypes.cpp @@ -0,0 +1,105 @@ + +#include "BuildTypes.h" +#include "Node.h" +#include "Variable.h" + +BuildTypes::BuildTypes(DataType targetPointerType) { + tinfo[tvoid] = {"void", 0, Type::getVoidTy(global_context), dwarf::DW_ATE_address}; + tinfo[tbool] = {"bool", 1, Type::getInt1Ty(global_context), dwarf::DW_ATE_boolean}; + tinfo[tchar] = {"char", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned_char}; + tinfo[tint2] = {"int2", 2, Type::getIntNTy(global_context, 2), dwarf::DW_ATE_signed}; + tinfo[tint8] = {"int8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint16] = {"int16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint32] = {"int32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint64] = {"int64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint8u] = {"unsigned8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint16u] = {"unsigned16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint32u] = {"unsigned32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint64u] = {"unsigned64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tfloat] = {"float", 32, Type::getFloatTy(global_context), dwarf::DW_ATE_float}; + tinfo[tdouble] = {"double", 64, Type::getDoubleTy(global_context), dwarf::DW_ATE_float}; + tinfo[tldouble] = {"long double", 128, Type::getFP128Ty(global_context), dwarf::DW_ATE_float}; + + unsigned pts = tinfo[targetPointerType].bitWidth; + Type *pty = tinfo[targetPointerType].llvmType; + tinfo[tarray] = {"array", pts, pty, dwarf::DW_ATE_address}; + + const DataLayout &dl = mainmodule->getDataLayout(); + for(int t = 0; t < __bdt_last; t++) { + DataTypeInfo &info = tinfo[t]; + namedTypes[info.name] = t; + if (debug_info) { + unsigned bitWidth = 0; + if (t > 0) // no void + bitWidth = dl.getTypeAllocSizeInBits(info.llvmType); + info.diType = DBuilder->createBasicType(info.name, bitWidth, info.dwarfEnc); + } + } +} + +DataType BuildTypes::getType(const string& name, bool createUndefined) { + auto ut = namedTypes.find(name); + if (ut == namedTypes.end()) { + if (createUndefined) + return addDataType(DataTypeInfo(name)); + } else if (tinfo[ut->second].isDefined) { + return ut->second; + } + return undefinedType; +} + +DataType BuildTypes::addDataType(Node* userType, Type* llvmType) { + const string& name = userType->getName(); + auto udt = namedTypes.find(name); + DataType id; + + const DataLayout &dl = mainmodule->getDataLayout(); + uint64_t bitWidth = dl.getTypeAllocSizeInBits(llvmType); + uint32_t align = dl.getABITypeAlign(llvmType).value(); + + if (udt == namedTypes.end()) { + DataTypeInfo info(name.c_str(), bitWidth, llvmType, 0); + id = addDataType(info); + } else { + id = udt->second; + } + DataTypeInfo &info = tinfo[id]; + info.sl = userType; + info.llvmType = llvmType; + info.isDefined = true; + info.isComplex = true; + info.dwarfEnc = 0; + + if (debug_info) { + unsigned offset = 0; + vector elems; + vector members; + for(auto& [key, m] : userType->getSymbols()) { + if (Node *n = dynamic_cast(m)) + members.push_back(n); + } + + assert((members.size() == llvmType->getNumContainedTypes()) && + "Number of fields differ between LLVM Type and Node."); + + int i = 0; + elems.reserve(members.size()); + for(Node *m : members) { + Type *memberTy = llvmType->getContainedType(i); + uint64_t memberBitWidth = dl.getTypeSizeInBits(memberTy); + uint32_t memberAlign = dl.getABITypeAlign(memberTy).value(); + DIType *di = DBuilder->createMemberType(RobDbgInfo.currScope(), m->getName(), + RobDbgInfo.currFile(), m->getLineNo(), + memberBitWidth, memberAlign, offset, DINode::DIFlags::FlagZero, + diType(m->getDataType())); + elems.push_back(di); + offset += memberBitWidth; + i++; + } + auto dielems = DBuilder->getOrCreateArray(elems); + info.diType = DBuilder->createClassType(RobDbgInfo.currScope(), name, + RobDbgInfo.currFile(), userType->getLineNo(), bitWidth, align, 0, + DINode::DIFlags::FlagZero, nullptr, dielems); + } + return id; +} diff --git a/src/BuildTypes.h b/src/BuildTypes.h index aaaea1d..bc2cbf2 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -1,101 +1,119 @@ #pragma once -enum BasicDataType {tvoid, tbool, tchar, tint8, tint16, tint32, tint64, +#include +#include "HeaderGlobals.h" + +typedef int DataType; + +enum BasicDataType {tvoid, tbool, tchar, tint2, tint8, tint16, tint32, tint64, tint8u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, tarray, /* new types here! */ __bdt_last}; enum DataQualifier {qnone, qconst, qvolatile}; +typedef DataQualifier DataQualifier; struct DataTypeInfo { - const char *name; + string name; unsigned bitWidth; Type *llvmType; unsigned dwarfEnc; DIType *diType; + SourceLocation *sl; + bool isDefined; + bool isComplex; + + DataTypeInfo() {} + + DataTypeInfo(string name) { + this->name = name; + this->bitWidth = 0; + this->llvmType = NULL; + this->dwarfEnc = 0; + this->diType = NULL; + this->isDefined = false; + this->isComplex = false; + } + + DataTypeInfo(const char* name, unsigned bitWidth, Type *llvmType, unsigned dwarfEnc): + name(name), bitWidth(bitWidth), llvmType(llvmType), dwarfEnc(dwarfEnc), diType(NULL), + sl(NULL), isDefined(true), isComplex(false) {}; }; class BuildTypes { private: - map tinfo; - unsigned nextt = __bdt_last; -public: - BuildTypes(unsigned targetPointerType) { - tinfo[tvoid] = {"void", 0, Type::getVoidTy(global_context), dwarf::DW_ATE_address}; - tinfo[tbool] = {"boolean", 1, Type::getInt1Ty(global_context), dwarf::DW_ATE_boolean}; - tinfo[tchar] = {"char", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned_char}; - tinfo[tint8] = {"int8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_signed}; - tinfo[tint16] = {"int16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_signed}; - tinfo[tint32] = {"int32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_signed}; - tinfo[tint64] = {"int64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_signed}; - tinfo[tint8u] = {"unsigned8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; - tinfo[tint16u] = {"unsigned16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; - tinfo[tint32u] = {"unsigned32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; - tinfo[tint64u] = {"unsigned64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_unsigned}; - tinfo[tfloat] = {"float", 32, Type::getFloatTy(global_context), dwarf::DW_ATE_float}; - tinfo[tdouble] = {"double", 64, Type::getDoubleTy(global_context), dwarf::DW_ATE_float}; - tinfo[tldouble] = {"long double", 128, Type::getFP128Ty(global_context), dwarf::DW_ATE_float}; - - unsigned pts = tinfo[targetPointerType].bitWidth; - Type *pty = tinfo[targetPointerType].llvmType; - tinfo[tarray] = {"array", pts, pty, dwarf::DW_ATE_address}; - - if (debug_info) { - for(int t = 0; t < __bdt_last; t++) { - DataTypeInfo &info = tinfo[t]; - info.diType = DBuilder->createBasicType(info.name, info.bitWidth, info.dwarfEnc); - } - } - } - - unsigned addUserDataType(char *name, unsigned bitWidth, Type* llvmType) { - DataTypeInfo info; - info.name = name; - info.bitWidth = bitWidth; - info.llvmType = llvmType; - info.dwarfEnc = dwarf::DW_ATE_address; - //TODO: info.dwarfEnc = DBuilder->createClassType(); - - unsigned result = nextt; - tinfo[nextt++] = info; + map tinfo; + map namedTypes; + DataType nextt = __bdt_last; + + DataType addDataType(const DataTypeInfo& udt) { + DataType result = nextt++; + tinfo[result] = udt; + namedTypes[udt.name] = result; return result; } +public: + static const DataType undefinedType = -1; + + BuildTypes(DataType targetPointerType); + + DataType addDataType(Node* userType, Type* llvmType); + + DataType getType(const string& name, bool createUndefined = false); + const char *name(unsigned tid) { - return tinfo[tid].name; + assert(tid != -1 && "Undefined type"); + return tinfo[tid].name.c_str(); } const unsigned bitWidth(unsigned tid) { + assert(tid != -1 && "Undefined type"); return tinfo[tid].bitWidth; } - unsigned dwarfEnc(unsigned tid) { - return tinfo[tid].dwarfEnc; - } - Type *llvmType(unsigned tid) { + assert(tid != -1 && "Undefined type"); return tinfo[tid].llvmType; } DIType *diType(unsigned tid) { + assert(tid != -1 && "Undefined type"); return tinfo[tid].diType; } - bool isIntegerDataType(unsigned tid) { + SourceLocation *location(unsigned tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].sl; + } + + bool isIntegerDataType(unsigned tid) const { return tid >= tint8 && tid <= tint64u; } - bool isSignedDataType(unsigned tid) { + bool isSignedDataType(unsigned tid) const { return tid >= tint8 && tid <= tint64; } - bool isUnsignedDataType(unsigned tid) { + bool isUnsignedDataType(unsigned tid) const { return tid >= tint8u && tid <= tint64u; } - bool isFloatDataType(unsigned tid) { + bool isFloatDataType(unsigned tid) const { return tid >= tfloat && tid <= tldouble; } + bool isComplex(unsigned tid) { + return tinfo[tid].isComplex; + } + }; + +// TODO: Replace all places with buildType::name +static string getTypeName(Type *ty) { + string type_str; + llvm::raw_string_ostream rso(type_str); + ty->print(rso); + return rso.str(); +} diff --git a/src/Capsule.cpp b/src/Capsule.cpp index 6ee260e..50cdb61 100644 --- a/src/Capsule.cpp +++ b/src/Capsule.cpp @@ -1,7 +1,7 @@ -#include "Header.h" +#include "Capsule.h" -Value *Capsule::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *Capsule::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return node->generate(func, block, allocblock); } diff --git a/src/Capsule.h b/src/Capsule.h index b22e387..544de26 100644 --- a/src/Capsule.h +++ b/src/Capsule.h @@ -1,5 +1,6 @@ -#ifndef __CAPSULE_H__ -#define __CAPSULE_H__ + +#pragma once + #include "Node.h" class Capsule: public Node { @@ -7,7 +8,5 @@ class Capsule: public Node { Node *node; public: Capsule (Node *n) : node(n) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); }; - -#endif diff --git a/src/Cast.cpp b/src/Cast.cpp index 4def6b9..9c79e3c 100644 --- a/src/Cast.cpp +++ b/src/Cast.cpp @@ -1,11 +1,8 @@ -#include "Header.h" +#include "Cast.h" +#include "Coercion.h" -BasicDataType Cast::getResultType(BasicBlock *block, BasicBlock *allocblock) { - return dt; -} - -Value *Cast::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) +Value *Cast::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { Value *exprv = expr->generate(func, block, allocblock); if (!exprv) @@ -15,14 +12,11 @@ Value *Cast::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) Value *ret = Coercion::Convert(exprv, destty, block, expr, true); if (ret == NULL) { - yyerrorcpp("Can't cast from '" + getTypeName(exprv->getType()) + "' to '" + - buildTypes->name(dt), this); + yyerrorcpp(string_format("Can't cast from '%s' to '%s'.", + buildTypes->name(expr->getDataType()), + buildTypes->name(dt)), this); return NULL; } return ret; } - -void Cast::accept(Visitor &v) { - v.visit(*this); -} diff --git a/src/Cast.h b/src/Cast.h index 6578f39..4a46b00 100644 --- a/src/Cast.h +++ b/src/Cast.h @@ -1,15 +1,16 @@ #pragma once -#include "Header.h" +#include "Node.h" class Cast: public Node { private: Node *expr; - BasicDataType dt; + public: - Cast(BasicDataType dt, Node *expr): dt(dt), expr(expr) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; + Cast(DataType dt, Node *expr): expr(expr) { + this->dt = dt; + } + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + }; diff --git a/src/CmpOp.cpp b/src/CmpOp.cpp index 155c83c..7345f32 100644 --- a/src/CmpOp.cpp +++ b/src/CmpOp.cpp @@ -1,15 +1,16 @@ -#include "Header.h" +#include "CmpOp.h" +#include "FlexDependencies.h" #include "Language_gen_y.hpp" +#include "Coercion.h" CmpOp::CmpOp (Node *l, int op, Node *r) : lexpn(l), rexpn(r) { this->op = op; - node_children.reserve(2); - node_children.push_back(lexpn); - node_children.push_back(rexpn); + addChild(lexpn); + addChild(rexpn); } -Value *CmpOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *CmpOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { CmpInst::Predicate predicate; Value *lexp = lexpn->generate(func, block, allocblock); @@ -68,7 +69,3 @@ Value *CmpOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock return Builder->CreateICmp(predicate, lexp, rexp, "cmpi"); } } - -void CmpOp::accept(Visitor& v) { - v.visit(*this); -} diff --git a/src/CmpOp.h b/src/CmpOp.h index 013b2c6..22af857 100644 --- a/src/CmpOp.h +++ b/src/CmpOp.h @@ -7,11 +7,11 @@ class CmpOp: public Node { Node *lexpn; Node *rexpn; int op; + public: CmpOp (Node *l, int op, Node *r); int getOperator() const { return op; }; - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/Coercion.cpp b/src/Coercion.cpp index 0c47f36..85d6955 100644 --- a/src/Coercion.cpp +++ b/src/Coercion.cpp @@ -1,4 +1,6 @@ -#include "Header.h" +#include "Coercion.h" +#include "HeaderGlobals.h" +#include "BuildTypes.h" unsigned Coercion::GetFloatingPointBitwidth(Type *ty) { switch (ty->getTypeID()) { @@ -68,8 +70,10 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati r = ConstantExpr::getTrunc(c, destty); else r = Builder->CreateTrunc(v, destty, "trunc"); - if (!isCast) - yywarncpp("Integer value truncated.", loc); + if (!isCast) { + yywarncpp(string_format("Integer value truncated from int%d to int%d.", + wty, wdestty), loc); + } } else if (wty < wdestty) { if (Constant *c = dyn_cast(v)) diff --git a/src/Coercion.h b/src/Coercion.h index 38920bd..20348cf 100644 --- a/src/Coercion.h +++ b/src/Coercion.h @@ -1,11 +1,12 @@ -#ifndef __COERCION_H__ -#define __COERCION_H__ + +#pragma once + +#include "HeaderExternals.h" +#include "SourceLocation.h" class Coercion{ - public: - static Value *Convert(Value *v, Type *destty, BasicBlock *block, SourceLocation *loc, - bool isCast = false); - static unsigned GetFloatingPointBitwidth(Type *ty); +public: + static Value *Convert(Value *v, Type *destty, BasicBlock *block, SourceLocation *loc, + bool isCast = false); + static unsigned GetFloatingPointBitwidth(Type *ty); }; - -#endif diff --git a/src/Colors.h b/src/Colors.h new file mode 100644 index 0000000..03b22a1 --- /dev/null +++ b/src/Colors.h @@ -0,0 +1,10 @@ + +#pragma once + +#define COLOR_RED "\x1b[31m" +#define COLOR_GREEN "\x1b[32m" +#define COLOR_YELLOW "\x1b[33m" +#define COLOR_BLUE "\x1b[34m" +#define COLOR_MAGENTA "\x1b[35m" +#define COLOR_CYAN "\x1b[36m" +#define COLOR_RESET "\x1b[0m" diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index 9eac38f..c697c8d 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -1,4 +1,6 @@ -#include "Header.h" +#include "HeaderGlobals.h" +#include "SourceLocation.h" +#include "Node.h" void DebugInfo::emitLocation(SourceLocation *s) { if (!debug_info) @@ -7,11 +9,13 @@ void DebugInfo::emitLocation(SourceLocation *s) { return Builder->SetCurrentDebugLocation(DebugLoc()); if (s->getLineNo() == 0) return; + DIScope *scope; if (scopes.empty()) scope = cunit; else scope = scopes.back(); + Builder->SetCurrentDebugLocation(DILocation::get( scope->getContext(), s->getLineNo(), s->getColNo(), scope)); } @@ -38,3 +42,16 @@ DIScope* DebugInfo::currScope() { return scopes.back(); } +void DebugInfo::declareVar(Node *n, Value *alloc, BasicBlock *allocblock) { + DataType dt = n->getDataType(); + llvm::DIType *dty = buildTypes->diType(dt); + if (n->hasQualifier(qvolatile)) { + dty = DBuilder->createQualifiedType(dwarf::DW_TAG_volatile_type, dty); + } + auto sp = RobDbgInfo.currScope(); + auto funit = RobDbgInfo.currFile(); + DILocalVariable *d = DBuilder->createAutoVariable( + sp, n->getName(), funit, n->getLineNo(), dty, true); + DBuilder->insertDeclare(alloc, d, DBuilder->createExpression(), + DILocation::get(sp->getContext(), n->getLineNo(), n->getColNo(), sp), allocblock); +} diff --git a/src/Delay.cpp b/src/Delay.cpp index ea61c52..d798bd3 100644 --- a/src/Delay.cpp +++ b/src/Delay.cpp @@ -1,21 +1,19 @@ -#include "Header.h" + +#include "Delay.h" Delay::Delay(Node *mseg) : ms(mseg) { - node_children.reserve(1); - node_children.push_back(ms); + addChild(ms); } -Value *Delay::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - Value *msv = ms->generate(func, block, allocblock); +Value *Delay::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + /*Value *msv = ms->generate(func, block, allocblock); Value *msv32 = new SExtInst(msv, Type::getInt32Ty(global_context), "conv", block); vector args; args.push_back(msv32); ArrayRef argsRef(args); - return CallInst::Create(delay, argsRef, "", block); -} + return CallInst::Create(delay, argsRef, "", block);*/ -void Delay::accept(Visitor& v) { - v.visit(*this); + // TODO: Implement a new delay without C depedency + return NULL; } - diff --git a/src/Delay.h b/src/Delay.h index fccc7d1..ca05f00 100644 --- a/src/Delay.h +++ b/src/Delay.h @@ -6,10 +6,10 @@ class Delay: public Node { private: Node *ms; + public: Delay (Node *mseg); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/Double.cpp b/src/Double.cpp index 442f440..9e869b8 100644 --- a/src/Double.cpp +++ b/src/Double.cpp @@ -1,6 +1,7 @@ -#include "Header.h" -Value *Double::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +#include "Double.h" + +Value *Double::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return ConstantFP::get(Type::getDoubleTy(global_context), number); } diff --git a/src/Double.h b/src/Double.h index 005c58e..2001c46 100644 --- a/src/Double.h +++ b/src/Double.h @@ -7,11 +7,11 @@ class Double: public Node { float number; public: Double(float n): number(n) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual bool isConstExpr() override { return true; } - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual DataType getDataType() override { return tdouble; } }; diff --git a/src/Field.cpp b/src/Field.cpp new file mode 100644 index 0000000..de83eaf --- /dev/null +++ b/src/Field.cpp @@ -0,0 +1,30 @@ + +#include "Field.h" + +Node* Identifier::getSymbol(Node *scope, bool validate) { + + Node *result = scope; + stringstream ss(ident); + string ci; + + // first symbol + getline(ss, ci, '.'); + result = result->findSymbol(ci); + if (result) { + while (!ss.eof() && result != NULL) { + getline(ss, ci, '.'); + result = result->findMember(ci); + } + } + + if (!result && validate) { + yyerrorcpp("Symbol " + ci + " not found.", this); + } + return result; +} + +Identifier Identifier::getStem() { + assert(complex && "identifier is not complex."); + size_t last = ident.find_last_of('.'); + return ident.substr(0, last); +} diff --git a/src/Field.h b/src/Field.h index 457a465..4f4514a 100644 --- a/src/Field.h +++ b/src/Field.h @@ -1,22 +1,20 @@ #pragma once -#include "Header.h" +#include "HeaderGlobals.h" +#include "Variable.h" -typedef struct { - BasicDataType fieldDataType; - char *fieldName; +class Field : public Variable { +public: unsigned startBit; unsigned bitWidth; -} Field; + Field(const string& Name, DataType dt) : Variable(name) { + setDataType(dt); + } +}; class Structure { public: int nextBit; - map fields; -}; - -class ComplexIdentifier { -public: - vector names; + map fields; }; diff --git a/src/FlexDependencies.h b/src/FlexDependencies.h new file mode 100644 index 0000000..c59fe15 --- /dev/null +++ b/src/FlexDependencies.h @@ -0,0 +1,23 @@ + +#pragma once + +#include +#include +using namespace std; + +class Node; +class Stmts; +class ArrayElements; +class MatrixElements; +class FunctionParams; +class ParamsCall; +class Structure; +class ArrayElement; +class MatrixElement; +class FunctionParam; +class Field; + +#include "SourceLocation.h" +#include "Colors.h" + +typedef void* yyscan_t; diff --git a/src/FlipOp.cpp b/src/FlipOp.cpp index 704ebb4..4ff469f 100644 --- a/src/FlipOp.cpp +++ b/src/FlipOp.cpp @@ -1,12 +1,11 @@ -#include "Header.h" +#include "FlipOp.h" FlipOp::FlipOp(Node *value) : value(value) { - this->node_children.reserve(1); - this->node_children.push_back(value); + this->addChild(value); }; -Value *FlipOp::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *FlipOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { // generate code to produce the value to flip Value *exprv = value->generate(func, block, allocblock); if (exprv == NULL) @@ -18,10 +17,6 @@ Value *FlipOp::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc Constant::getAllOnesValue(exprv->getType()), "neg", block); } -void FlipOp::accept(Visitor& v) { - v.visit(*this); -} - -bool FlipOp::isConstExpr(BasicBlock *block, BasicBlock *allocblock) { - return value->isConstExpr(block, allocblock); +bool FlipOp::isConstExpr() { + return value->isConstExpr(); } diff --git a/src/FlipOp.h b/src/FlipOp.h index a7f7767..565a90f 100644 --- a/src/FlipOp.h +++ b/src/FlipOp.h @@ -7,18 +7,17 @@ class FlipOp: public Node { private: Node *value; + public: FlipOp(Node *value); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - - virtual void accept(Visitor &v) override; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { - return value->getResultType(block, allocblock); + virtual DataType getDataType() override { + return value->getDataType(); } - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; + virtual bool isConstExpr() override; }; #endif diff --git a/src/Float.cpp b/src/Float.cpp index c511871..1705876 100644 --- a/src/Float.cpp +++ b/src/Float.cpp @@ -1,6 +1,7 @@ -#include "Header.h" -Value *Float::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +#include "Float.h" + +Value *Float::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return ConstantFP::get(Type::getFloatTy(global_context), number); } diff --git a/src/Float.h b/src/Float.h index 612b658..3cfb2f4 100644 --- a/src/Float.h +++ b/src/Float.h @@ -7,11 +7,12 @@ class Float: public Node { float number; public: Float(float n): number(n) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual bool isConstExpr() override { return true; } - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + + virtual DataType getDataType() override { return tfloat; } }; diff --git a/src/Float128.cpp b/src/Float128.cpp index e412399..4c946af 100644 --- a/src/Float128.cpp +++ b/src/Float128.cpp @@ -1,6 +1,7 @@ -#include "Header.h" -Value *Float128::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +#include "Float128.h" + +Value *Float128::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return ConstantFP::get(Type::getFP128Ty(global_context), number); } diff --git a/src/Float128.h b/src/Float128.h index d81ca6d..7bcb58f 100644 --- a/src/Float128.h +++ b/src/Float128.h @@ -7,13 +7,13 @@ class Float128: public Node { float number; public: Float128(float n): number(n) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + virtual bool isConstExpr() override { return true; } - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + virtual DataType getDataType() override { return tldouble; } }; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 3969e66..80c7863 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -1,40 +1,126 @@ -#include "Header.h" +#include "FunctionCall.h" +#include "Cast.h" +#include "FunctionDecl.h" +#include "FunctionImpl.h" +#include "HeaderGlobals.h" +#include "Coercion.h" +#include "Load.h" +#include "Visitor.h" +#include "BackLLVM.h" -BasicDataType FunctionCall::getResultType(BasicBlock *block, BasicBlock *allocblock) { - auto symbol = search_symbol(name); - if (symbol) - return symbol->dt; - return tvoid; +DataType FunctionCall::getDataType() { + + if (dt == BuildTypes::undefinedType) { + // is a cast? + dt = buildTypes->getType(ident.getFullName()); + if (parameters->getNumParams() <= 1 && dt != BuildTypes::undefinedType) { + return dt; + } + + if (!symbol) + symbol = ident.getSymbol(getScope()); + + if (symbol) + dt = symbol->getDataType(); + } + return dt; } -Value *FunctionCall::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +void FunctionCall::loadFunctionStem(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + +} + +Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + string name = ident.getFullName(); + + // check if it is a cast call + DataType adt = buildTypes->getType(name); + if (adt != BuildTypes::undefinedType) { + dt = adt; + unsigned p = parameters->getNumParams(); + + // call with only one parameter is a cast + if (p == 1) { + Cast ca(dt, parameters->getParamElement(0)); + return ca.generate(func, block, allocblock); + + } else if (p == 0) { // it's a constructor + RobDbgInfo.emitLocation(this); + + // alloc + Value *var = leftValue; + if (leftValue == NULL) { + Builder->SetInsertPoint(allocblock); + var = Builder->CreateAlloca(buildTypes->llvmType(dt), globalAddrSpace, 0, leftName); + } + vector args; + args.push_back(var); + + // call #init + Node *type = findSymbol(name); + Node *fsymbol = type->findMember("init"); + FunctionImpl *initfunc = dynamic_cast(fsymbol); + Builder->SetInsertPoint(block); + Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); + return var; + } + } + + if (!symbol) + symbol = ident.getSymbol(getScope(), false); - auto symbol = search_symbol(name); if (symbol == NULL) { yyerrorcpp("Function " + name + " not defined.", this); return NULL; } - Function *cfunc = dyn_cast(symbol->value); - if (cfunc == NULL) { + FunctionBase *fsymbol = dynamic_cast(symbol); + Function *cfunc = dyn_cast(symbol->getLLVMValue(func)); + if (fsymbol == NULL || cfunc == NULL) { yyerrorcpp("Symbol " + name + " is not a function.", this); return NULL; } - if (symbol->params->getNumParams() != parameters->getNumParams()) { + dt = fsymbol->getDataType(); + + bool this_param = false; + Value *stem = NULL; + if (ident.isComplex()) { + Identifier istem = ident.getStem(); + Node *n = istem.getSymbol(getScope()); + stem = n->getLLVMValue(func); + + // TODO: When accessing a.x.func(), need to load a and gep x + //Load loadstem(ident.getStem()); + //loadstem.setParent(this->parent); + //stem = loadstem.generate(func, block, allocblock); + + this_param = true; + } + + if (fsymbol->getNumParams() != parameters->getNumParams() + this_param) { yyerrorcpp(string_format("Function %s has %d argument(s) but was called with %d.", - name.c_str(), symbol->params->getNumParams(), parameters->getNumParams()), this); - yyerrorcpp("The function declaration is here.", symbol); + name.c_str(), fsymbol->getNumParams(), parameters->getNumParams()), this); + yywarncpp("The function declaration is here.", symbol); return NULL; } vector args; for (int i = 0; i < parameters->getNumParams(); i++){ Value *valor = parameters->getParamElement(i)->generate(func, block, allocblock); - Type *pty = buildTypes->llvmType(symbol->params->getParamType(i)); - valor = Coercion::Convert(valor, pty, block, this); + DataType pdt = fsymbol->getParameters().getParamType(i); + if (!buildTypes->isComplex(pdt)) { + //TODO: we don't support cohercion between user types yet + Type *pty = buildTypes->llvmType(pdt); + valor = Coercion::Convert(valor, pty, block, this); + } args.push_back(valor); } + + if (this_param) + args.push_back(stem); + ArrayRef argsRef(args); RobDbgInfo.emitLocation(this); @@ -42,3 +128,6 @@ Value *FunctionCall::generate(Function *func, BasicBlock *block, BasicBlock *all return Builder->CreateCall(cfunc, argsRef); } +void FunctionCall::accept(Visitor& v) { + v.visit(*this); +} diff --git a/src/FunctionCall.h b/src/FunctionCall.h index 2f16200..3529103 100644 --- a/src/FunctionCall.h +++ b/src/FunctionCall.h @@ -1,19 +1,35 @@ -#ifndef __FUNCTIONCALL_H__ -#define __FUNCTIONCALL_H__ + +#pragma once + #include "Node.h" +#include "ParamsCall.h" +#include "Field.h" class FunctionCall: public Node { private: - string name; + Identifier ident; ParamsCall *parameters; + Node *symbol = NULL; + Value *leftValue = NULL; + string leftName; + public: - FunctionCall(string name, ParamsCall *pc) { - this->name = name; - this->parameters = pc; + FunctionCall(const char *name, ParamsCall *pc): ident(name) { + parameters = pc; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + void loadFunctionStem(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); - BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; -}; + virtual DataType getDataType() override; -#endif + virtual void setLeftValue(Value *lv, const string& name) override { + leftValue = lv; + leftName = name; + } + + std::vector const& getParameters() { + return parameters->getParameters(); + } + + void accept(Visitor& v) override; +}; diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 5a08517..9232f99 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -1,31 +1,50 @@ -#include "Header.h" -Value *FunctionDecl::generate(Function *, BasicBlock *, BasicBlock *allocblock) { - auto sym = search_symbol(name); - if (sym != NULL) { +#include "FunctionDecl.h" +#include "BackLLVM.h" + +bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { + bool valid = true; + Type *xtype = buildTypes->llvmType(dt); + if (!xtype) { + yyerrorcpp(string_format("Type %s not defined.", buildTypes->name(dt)), this); + valid = false; + } + for (int i = 0; i < parameters->getNumParams(); i++) { + DataType dt = parameters->getParamType(i); + Type *atype = buildTypes->llvmType(dt); + if (buildTypes->isComplex(dt)) { + atype = atype->getPointerTo(); + } + if (!atype) { + yyerrorcpp(string_format("Type %s for argument %s not defined.", + buildTypes->name(dt), parameters->getParamName(i).c_str()), this); + valid = false; + } else { + argsty.push_back(atype); + } + } + return valid; +} + +Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocblock) { + + Node *symbol = findSymbol(name); + if (symbol != NULL && symbol != this) { yyerrorcpp("Function/symbol " + name + " already defined.", this); - yyerrorcpp(name + " was first defined here.", sym); + yyerrorcpp(name + " was first defined here.", symbol); return NULL; } std::vector arg_types; - if (parameters->getNumParams() != 0) - for (int i = 0; i < parameters->getNumParams(); i++) - arg_types.push_back(buildTypes->llvmType(parameters->getParamType(i))); + if (!validateAndGetArgsTypes(arg_types)) + return NULL; - Type *xtype = buildTypes->llvmType(tipo); + Type *xtype = buildTypes->llvmType(dt); FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, 1, name, mainmodule); - nfunc->setDSOLocal(true); + Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, globalAddrSpace, name, mainmodule); + //nfunc->setDSOLocal(true); nfunc->setCallingConv(CallingConv::C); - RobSymbol *rs = new RobSymbol(nfunc); - rs->params = parameters; - rs->setLocation(this); - rs->isDeclaration = true; - rs->dt = tipo; - tabelasym[allocblock][name] = rs; - - return nfunc; + func = nfunc; + return func; } - diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index dbd6bfb..0eaed04 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -1,32 +1,57 @@ -#ifndef __FUNCTIONDECLEXTERN_H__ -#define __FUNCTIONDECLEXTERN_H__ +#pragma once #include "Node.h" +#include "FunctionParams.h" +#include "Variable.h" -class FunctionDecl: public NamedNode { -private: - BasicDataType tipo; +class FunctionBase: public NamedNode { +protected: FunctionParams *parameters; + Function *func = NULL; + bool declaration = true; + + bool validateAndGetArgsTypes(std::vector &args); + public: - FunctionDecl(BasicDataType tipo, string name, FunctionParams *fp) : NamedNode(name) { - this->tipo = tipo; + FunctionBase(DataType dt, string name, FunctionParams *fp) : NamedNode(name) { + this->dt = dt; this->parameters = fp; } - - virtual bool isFunctionDecl() override { - return true; - } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + FunctionBase(DataType dt, string name, FunctionParams *fp, vector &&stmts, + bool constructor = false) : + NamedNode(name, std::move(stmts), constructor) { + this->dt = dt; + this->parameters = fp; + } - FunctionParams const& getParameters() { + FunctionParams& getParameters() { return *parameters; } - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { - return tipo; + virtual Value *getLLVMValue(Node *) override { + return func; + } + + virtual Function *getLLVMFunction() { + return func; + } + + unsigned getNumParams() const { + return parameters->getNumParams(); + } + + bool isDeclaration() { + return declaration; } }; -#endif +class FunctionDecl: public FunctionBase { +public: + FunctionDecl(DataType dt, string name, FunctionParams *fp) : + FunctionBase(dt, name, fp) { + declaration = true; + } + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; +}; diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 29d1eb6..50297b2 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -1,75 +1,97 @@ -#include "Header.h" +#include "FunctionImpl.h" +#include "Visitor.h" +#include "BackLLVM.h" + +FunctionImpl::FunctionImpl(DataType dt, string name, FunctionParams *fp, vector &&stmts, + location_t ef, bool constructor) : + FunctionBase(dt, name, fp, std::move(stmts), constructor) { + this->declaration = false; + this->endfunction = ef; + + // params needs to be the first inserted children + // to fill the symbols table prior to their use in stmts + for(auto p: fp->getParameters()) { + node_children.insert(node_children.begin(), p); + } +} -Value *FunctionImpl::generate(Function *, BasicBlock *, BasicBlock *allocblock) { - auto sym = search_symbol(name); - if (sym != NULL && !sym->isDeclaration) { +Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblock) { + + Node *symbol = findSymbol(name); + FunctionDecl *fsymbol = dynamic_cast(symbol); + if (symbol != NULL && symbol != this && fsymbol != NULL && !fsymbol->isDeclaration()) { yyerrorcpp("Function/symbol " + name + " already defined.", this); - yyerrorcpp(name + " was first defined here.", sym); + yyerrorcpp(name + " was first defined here.", symbol); return NULL; } - Function *nfunc; - Type *xtype = buildTypes->llvmType(tipo); - if (sym && sym->isDeclaration) { - //TODO: validateImplementation(); - nfunc = mainmodule->getFunction(name); + Type *xtype = buildTypes->llvmType(dt); + if (fsymbol) { + validateImplementation(fsymbol); + func = mainmodule->getFunction(name); + func->setName(getFinalName()); } else { std::vector arg_types; - if (parameters->getNumParams() != 0) - for (int i = 0; i < parameters->getNumParams(); i++) - arg_types.push_back(buildTypes->llvmType(parameters->getParamType(i))); + if (!validateAndGetArgsTypes(arg_types)) + return NULL; FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - nfunc = Function::Create(ftype, Function::ExternalLinkage, 1, name, mainmodule); + func = Function::Create(ftype, Function::ExternalLinkage, globalAddrSpace, getFinalName(), mainmodule); } - nfunc->setDSOLocal(true); + //func->setDSOLocal(true); llvm::AttrBuilder attrs(global_context); - attrs.addAttribute(Attribute::MinSize); + //attrs.addAttribute(Attribute::MinSize); + attrs.addAttribute("target-cpu", currentTarget.cpu); + //attrs.addAttribute("frame-pointer", "all"); + + if (name == "init") // inline constructors + attrs.addAttribute(Attribute::InlineHint); if (name == "__vectors") { // FIXME: remove after adding functions attributes to language - nfunc->setSection(".vectors"); + func->setSection(".vectors"); } - nfunc->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); - nfunc->setCallingConv(CallingConv::C); - - if (!sym) - sym = new RobSymbol(nfunc); - sym->dt = tipo; - sym->params = parameters; - sym->isDeclaration = false; - tabelasym[allocblock][name] = sym; + func->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); + func->setCallingConv(CallingConv::C); DIFile *funit; DISubprogram *sp; if (debug_info) { funit = DBuilder->createFile(RobDbgInfo.cunit->getFilename(), RobDbgInfo.cunit->getDirectory()); DIScope *fcontext = funit; - sp = DBuilder->createFunction(fcontext, name, StringRef(), funit, this->getLineNo(), + sp = DBuilder->createFunction(fcontext, getFinalName(), StringRef(), funit, this->getLineNo(), getFunctionDIType(), this->getLineNo(), DINode::FlagPrototyped, DISubprogram::SPFlagDefinition); - nfunc->setSubprogram(sp); + func->setSubprogram(sp); RobDbgInfo.push_scope(funit, sp); } - BasicBlock *falloc = BasicBlock::Create(global_context, "entry", nfunc); - BasicBlock *fblock = BasicBlock::Create(global_context, "body", nfunc); + BasicBlock *falloc = BasicBlock::Create(global_context, "entry", func); + BasicBlock *fblock = BasicBlock::Create(global_context, "body", func); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(falloc); unsigned Idx = 0; - for (auto &Arg : nfunc->args()) - { - const char *argname = parameters->getParamElement(Idx); - BasicDataType ptype = parameters->getParamType(Idx); - + for (auto &Arg : func->args()) { + FunctionParam *fp = parameters->getParameters()[Idx]; + DataType ptype = fp->getDataType(); + const string& argname = fp->getName(); + Arg.setName(argname); - AllocaInst* variable = Builder->CreateAlloca(buildTypes->llvmType(ptype), 0, argname); - RobSymbol *rs = new RobSymbol(variable); - rs->dt = ptype; - tabelasym[falloc][argname] = rs; - StoreInst *val = Builder->CreateStore(&Arg, variable, false); + + Value *variable = &Arg; + if (!buildTypes->isComplex(ptype)) + variable = Builder->CreateAlloca(buildTypes->llvmType(ptype), globalAddrSpace, 0, argname); + + if (argname == "#this") { + thisArg = variable; + } + + fp->setAlloca(variable); + + if (!buildTypes->isComplex(ptype)) + Builder->CreateStore(&Arg, variable, false); if (debug_info) { DILocalVariable *d = DBuilder->createParameterVariable(sp, argname, Idx+1, funit, @@ -82,8 +104,7 @@ Value *FunctionImpl::generate(Function *, BasicBlock *, BasicBlock *allocblock) Idx++; } - RobDbgInfo.emitLocation(stmts); - Value *last_block = stmts->generate(nfunc, fblock, falloc); + Value *last_block = generateChildren(this, fblock, falloc); if (!last_block) last_block = fblock; @@ -105,45 +126,54 @@ Value *FunctionImpl::generate(Function *, BasicBlock *, BasicBlock *allocblock) if (debug_info) RobDbgInfo.pop_scope(); - - return nfunc; + + return func; } DISubroutineType *FunctionImpl::getFunctionDIType() { SmallVector Tys; - Tys.push_back(buildTypes->diType(tipo)); // return type - for(FunctionParam &p : parameters->parameters) { - Tys.push_back(buildTypes->diType(p.type)); + Tys.push_back(buildTypes->diType(dt)); // return type + for(FunctionParam *p : parameters->getParameters()) { + Tys.push_back(buildTypes->diType(p->getDataType())); } return DBuilder->createSubroutineType(DBuilder->getOrCreateTypeArray(Tys)); } bool FunctionImpl::validateImplementation(FunctionDecl *decl) { bool result = true; - const FunctionParams& decl_parameters = decl->getParameters(); + FunctionParams& decl_parameters = decl->getParameters(); if (parameters->getNumParams() != decl_parameters.getNumParams()) { yyerrorcpp(string_format("The number of arguments differs between function declaration(%d) and definition(%d).", decl_parameters.getNumParams(), parameters->getNumParams()), this); - yyerrorcpp("The function declaration is here.", decl); + yywarncpp("The function declaration is here.", decl); result = false; } int compareno = std::min(parameters->getNumParams(), decl_parameters.getNumParams()); for(int i = 0; i < compareno; i++) { - const FunctionParam &p = decl_parameters.parameters[i]; - if (p.type != parameters->parameters[i].type) { + FunctionParam *p = decl_parameters.getParameters()[i]; + if (p->getDataType() != parameters->getParamType(i)) { yyerrorcpp(string_format("Argument %s has distinct type in declaration '%s' and definition '%s'.", - parameters->parameters[i].name, buildTypes->name(p.type), - buildTypes->name(parameters->parameters[i].type)), this); - yyerrorcpp("The function declaration is here.", decl); + parameters->getParamName(i).c_str(), buildTypes->name(p->getDataType()), + buildTypes->name(parameters->getParamType(i))), this); + yywarncpp("The function declaration is here.", decl); result = false; } } - BasicDataType decl_type = decl->getResultType(NULL, NULL); - if (tipo != decl_type) { + DataType decl_type = decl->getDataType(); + if (dt != decl_type) { yyerrorcpp(string_format("Function return type has distinct type in declaration '%s' and definition '%s'.", - buildTypes->name(decl_type), buildTypes->name(tipo)), this); - yyerrorcpp("The function declaration is here.", decl); + buildTypes->name(decl_type), buildTypes->name(dt)), this); + yywarncpp("The function declaration is here.", decl); result = false; } return result; } + +void FunctionImpl::addThisArgument(DataType dt) { + thisArgDt = dt; + parameters->append(new FunctionParam("#this", dt)); +} + +void FunctionImpl::accept(Visitor& v) { + v.visit(*this); +} diff --git a/src/FunctionImpl.h b/src/FunctionImpl.h index bf46c6e..7b5f26c 100644 --- a/src/FunctionImpl.h +++ b/src/FunctionImpl.h @@ -2,35 +2,48 @@ #pragma once #include "Node.h" +#include "FunctionDecl.h" -class FunctionImpl: public NamedNode { +class Visitor; + +class FunctionImpl: public FunctionBase { private: - Node *stmts; - BasicDataType tipo; - FunctionParams *parameters; SourceLocation endfunction; + DataType thisArgDt = BuildTypes::undefinedType; + Value *thisArg = NULL; + string userTypeName; + public: - FunctionImpl(BasicDataType tipo, string name, FunctionParams *fp, Node *stmts, SourceLocation ef) : - NamedNode(name) - { - this->tipo = tipo; - this->stmts = stmts; - this->parameters = fp; - this->endfunction = ef; - this->node_children.push_back(stmts); - } + FunctionImpl(DataType dt, string name, FunctionParams *fp, vector &&stmts, location_t ef, + bool constructor = false); - virtual bool isFunctionDecl() override { - return true; - } - - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; DISubroutineType *getFunctionDIType(); bool validateImplementation(FunctionDecl *decl); - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { - return tipo; + void addThisArgument(DataType dt); + + Value *getThisArg() const { + return thisArg; + } + + DataType getThisArgDt() const { + return thisArgDt; + } + + void setUserTypeName(const string& ut) { + userTypeName = ut; } + + string getFinalName() { + if (userTypeName == "") + return name; + else + return userTypeName + "#" + name; + } + + virtual void accept(Visitor& v) override; + }; diff --git a/src/FunctionParams.cpp b/src/FunctionParams.cpp index 6460f71..8d0193f 100644 --- a/src/FunctionParams.cpp +++ b/src/FunctionParams.cpp @@ -1,19 +1,20 @@ -#include "Header.h" + +#include "FunctionParams.h" FunctionParams::FunctionParams() {}; -void FunctionParams::append(FunctionParam& e) { +void FunctionParams::append(FunctionParam *e) { parameters.push_back(e); }; -unsigned FunctionParams::getNumParams() const { +unsigned FunctionParams::getNumParams() { return parameters.size(); }; -BasicDataType FunctionParams::getParamType(int position) const { - return parameters[position].type; +DataType FunctionParams::getParamType(int position) { + return parameters[position]->getDataType(); } -const char *FunctionParams::getParamElement(int position) const { - return parameters[position].name; +const string FunctionParams::getParamName(int position) { + return parameters[position]->getName(); } diff --git a/src/FunctionParams.h b/src/FunctionParams.h index 26adf85..7042c94 100644 --- a/src/FunctionParams.h +++ b/src/FunctionParams.h @@ -1,19 +1,38 @@ -#ifndef __FUNCTION_PARAMS_H__ -#define __FUNCTION_PARAMS_H__ +#pragma once #include "Node.h" +#include "Variable.h" + +class FunctionParam: public Variable { +public: + FunctionParam(const char *name, DataType dt): Variable(name) { + this->dt = dt; + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + return NULL; + } + + void setAlloca(Value *alloc) { + this->alloc = alloc; + } + + friend class FunctionImpl; +}; class FunctionParams { private: + std::vector parameters; + public: - std::vector parameters; FunctionParams(); - void append(FunctionParam& fp); + void append(FunctionParam *fp); - unsigned getNumParams() const; - BasicDataType getParamType (int position) const; - const char *getParamElement (int position) const; -}; - -#endif + unsigned getNumParams(); + DataType getParamType (int position); + const string getParamName (int position); + std::vector const& getParameters() { + return parameters; + } +}; diff --git a/src/Header.h b/src/Header.h index 0885224..a37b6d3 100644 --- a/src/Header.h +++ b/src/Header.h @@ -1,163 +1,17 @@ -#ifndef __HEADER_H__ -#define __HEADER_H__ -//#define ENABLE_ARDUINO -//#define ENABLE_PRINT +#pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace llvm; +#ifndef SCANNER_OR_VISITOR +#error Please include this file only on .y or visitor files +#endif -// Program main module and IR Builder -extern Module* mainmodule; -extern BasicBlock* global_alloc; -extern LLVMContext global_context; -extern std::unique_ptr> Builder; +//#define ENABLE_ARDUINO +//#define ENABLE_PRINT +#include "HeaderGlobals.h" #include "SourceLocation.h" - -// Debug Info -extern bool debug_info; -extern std::unique_ptr DBuilder; -struct DebugInfo { - DICompileUnit *cunit; - vector files; - vector scopes; - void emitLocation(SourceLocation *s); - void push_scope(DIFile *f, DIScope *); - void pop_scope(); - DIFile *currFile(); - DIScope *currScope(); -}; -extern struct DebugInfo RobDbgInfo; - -#include "BuildTypes.h" -extern std::unique_ptr buildTypes; - #include "Scanner.h" - -class Node; -class Stmts; -class ArrayElements; -class MatrixElements; -class FunctionParams; -class ParamsCall; - -typedef struct { - Node *value; - unsigned count; -} ArrayElement; - -typedef struct { - const char *name; - BasicDataType type; -} FunctionParam; - -typedef struct { - ArrayElements *array; - unsigned count; -} MatrixElement; - #include "Field.h" - -extern char* build_filename; -extern char* build_outputfilename; - -// symbol table -#include "RobSymbol.h" -extern map> tabelasym; -static Node* getNodeForIntConst(int64_t i); - -// arduino functions -extern Function *analogWrite; -extern Function *analogRead; -extern Function *delay; -extern Function *delayMicroseconds; -extern Function *init; -extern Function *print; -extern Function *i16div; - -typedef struct { - const char *name; - const char *triple; - const char *cpu; - const char *features; - const BasicDataType pointerType; -} TargetInfo; - -enum SupportedTargets {native, avr328p, stm32f1, esp32, __last_target}; -static enum SupportedTargets currentTargetId; -#define currentTarget (supportedTargets[currentTargetId]) - -static TargetInfo supportedTargets[__last_target] = { - {"", "", "", "", tint64}, // default target - {"avr328p", "avr-atmel-none", "atmega328p", "+avr5", tint16}, - {"stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, - {"esp32", "xtensa", "", "", tint32}, -}; - -static void initTarget(const char *targetarch) { - currentTargetId = native; //native - for(int t = native; t < __last_target; t++) { - if (strcmp(targetarch, supportedTargets[t].name) == 0) { - currentTargetId = static_cast(t); - break; - } - } - buildTypes = make_unique(currentTarget.pointerType); -} - -static string getTypeName(Type *ty) { - string type_str; - llvm::raw_string_ostream rso(type_str); - ty->print(rso); - return rso.str(); -} - -static RobSymbol *search_symbol(const string& ident, BasicBlock *firstb = NULL, BasicBlock *secondb = NULL) { - BasicBlock *blocks[] = {firstb, secondb, global_alloc}; - for(BasicBlock *b : blocks) { - if (b == NULL) - continue; - auto blocksym = tabelasym[b]; - auto var = blocksym.find(ident); - if (var != blocksym.end()) - return var->second; - } - return NULL; -} - -template -string string_format(const char *format, Args ... args) { - int size_s = std::snprintf(nullptr, 0, format, args ...) + 1; - if( size_s <= 0 ) { - return ""; - } - auto size = static_cast(size_s); - unique_ptr buf(new char[ size ]); - snprintf(buf.get(), size, format, args ...); - return string(buf.get(), buf.get() + size - 1); -} - #include "Node.h" #include "ArrayElements.h" #include "AttachInterrupt.h" @@ -188,12 +42,11 @@ string string_format(const char *format, Args ... args) { #include "OutPort.h" #include "ParamsCall.h" #include "Print.h" -#include "Stmts.h" #include "Program.h" #include "Return.h" #include "Scalar.h" #include "Semantic.h" -#include "String.h" +#include "StringConst.h" #include "UpdateArray.h" #include "UpdateMatrix.h" #include "Array.h" @@ -206,20 +59,4 @@ string string_format(const char *format, Args ... args) { #include "Interface.h" #include "UserType.h" -#include "Visitor.h" -#include "RecursiveVisitor.h" -#include "PrintAstVisitor.h" - -static Node* getNodeForIntConst(int64_t i) { - if (i >= SCHAR_MIN && i <= SCHAR_MAX) - return new Int8(i); - else if (i >= SHRT_MIN && i <= SHRT_MAX) - return new Int16(i); - else if (i >= INT_MIN && i <= INT_MAX) - return new Int32(i); - else - return new Int64(i); -} - -#endif - +extern Node* getNodeForIntConst(int64_t i); diff --git a/src/HeaderExternals.h b/src/HeaderExternals.h new file mode 100644 index 0000000..cb8cf79 --- /dev/null +++ b/src/HeaderExternals.h @@ -0,0 +1,31 @@ + +#pragma once + +/* Add only std cpp library related includes */ + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +/* Add only llvm related includes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; diff --git a/src/HeaderGlobals.h b/src/HeaderGlobals.h new file mode 100644 index 0000000..fcb1e34 --- /dev/null +++ b/src/HeaderGlobals.h @@ -0,0 +1,51 @@ + +#pragma once + +#include "HeaderExternals.h" + +// Program main module and IR Builder +extern Module* mainmodule; +extern BasicBlock* global_alloc; +extern LLVMContext global_context; +extern unique_ptr> Builder; + +class BuildTypes; +extern unique_ptr buildTypes; + +class SourceLocation; +class Node; + +// Debug Info +extern bool debug_info; +extern unique_ptr DBuilder; +struct DebugInfo { + DICompileUnit *cunit; + vector files; + vector scopes; + void emitLocation(SourceLocation *s); + void push_scope(DIFile *f, DIScope *); + void pop_scope(); + DIFile *currFile(); + DIScope *currScope(); + void declareVar(Node *n, Value *alloc, BasicBlock *allocblock); +}; +extern struct DebugInfo RobDbgInfo; + +// Error messages +void yyerrorcpp(const string& s, SourceLocation *n); +void yywarncpp(const string& s, SourceLocation *n); + +template +string string_format(const char *format, Args ... args) { + int size_s = snprintf(nullptr, 0, format, args ...) + 1; + if( size_s <= 0 ) { + return ""; + } + auto size = static_cast(size_s); + unique_ptr buf(new char[ size ]); + snprintf(buf.get(), size, format, args ...); + return string(buf.get(), buf.get() + size - 1); +} + +class Node; +extern Node* getNodeForIntConst(int64_t i); diff --git a/src/If.cpp b/src/If.cpp index bcf5f87..1f408fe 100644 --- a/src/If.cpp +++ b/src/If.cpp @@ -1,30 +1,37 @@ -#include "Header.h" - -If::If(Node *e, Node *tst, Node *est) : expr(e), thenst(tst), elsest(est) { - node_children.reserve(3); - node_children.push_back(expr); - node_children.push_back(thenst); +#include "If.h" +#include "FunctionImpl.h" +#include "Visitor.h" + +If::If(Node *e, vector &&tst): expr(e) { + addChild(expr); + thenst = new Node(std::move(tst)); + addChild(thenst); +} - if (est != NULL) - node_children.push_back(elsest); +If::If(Node *e, vector &&tst, vector &&est): If(e, std::move(tst)) { + elsest = new Node(std::move(est)); + addChild(elsest); } -Value *If::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *If::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { Value *exprv = expr->generate(func, block, allocblock); - BasicBlock *thenb = BasicBlock::Create(global_context, "if_then", func, 0); - Value *thennewb = thenst->generate(func, thenb, allocblock); + BasicBlock *thenb = BasicBlock::Create(global_context, "if_then", + func->getLLVMFunction(), 0); + Value *thennewb = thenst->generateChildren(func, thenb, allocblock); Value *elsenewb = NULL; - BasicBlock *elseb = BasicBlock::Create(global_context, "if_else", func, 0); + BasicBlock *elseb = BasicBlock::Create(global_context, "if_else", + func->getLLVMFunction(), 0); if (elsest != 0) { - elsenewb = elsest->generate(func, elseb, allocblock); + elsenewb = elsest->generateChildren(func, elseb, allocblock); } BranchInst::Create(thenb, elseb, exprv, block); - BasicBlock *mergb = BasicBlock::Create(global_context, "if_cont", func, 0); + BasicBlock *mergb = BasicBlock::Create(global_context, "if_cont", + func->getLLVMFunction(), 0); // identify last then block BasicBlock *lastthen = thenb; @@ -49,5 +56,4 @@ Value *If::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { void If::accept(Visitor& v) { v.visit(*this); -} - +} \ No newline at end of file diff --git a/src/If.h b/src/If.h index 62a3c52..a0d2398 100644 --- a/src/If.h +++ b/src/If.h @@ -1,5 +1,5 @@ -#ifndef __IF_H__ -#define __IF_H__ +#pragma once + #include "Node.h" class If: public Node { @@ -8,9 +8,8 @@ class If: public Node { Node *thenst; Node *elsest; public: - If(Node *e, Node *tst, Node *est); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + If(Node *e, vector &&tst); + If(Node *e, vector &&tst, vector &&est); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; virtual void accept(Visitor& v) override; }; - -#endif diff --git a/src/InPort.cpp b/src/InPort.cpp index c9e7a29..182f6f3 100644 --- a/src/InPort.cpp +++ b/src/InPort.cpp @@ -1,7 +1,8 @@ -#include "Header.h" -Value *InPort::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - vector args; +#include "InPort.h" + +Value *InPort::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + /*vector args; Int8 prt(atoi(port.c_str())); Value *v = prt.generate(func, block, allocblock); @@ -9,6 +10,9 @@ Value *InPort::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc args.push_back(v); ArrayRef argsRef(args); - return CallInst::Create(analogRead, argsRef, "", block); + return CallInst::Create(analogRead, argsRef, "", block);*/ + + //TODO: Implement a new way of reading ports + return NULL; } diff --git a/src/InPort.h b/src/InPort.h index 9871392..b0c3db1 100644 --- a/src/InPort.h +++ b/src/InPort.h @@ -9,7 +9,7 @@ class InPort: public Node { public: InPort(const char *p): port(p) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); }; diff --git a/src/InlineAssembly.cpp b/src/InlineAssembly.cpp index 2c836a6..db36abf 100644 --- a/src/InlineAssembly.cpp +++ b/src/InlineAssembly.cpp @@ -1,6 +1,7 @@ -#include "Header.h" -Value *InlineAssembly::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +#include "InlineAssembly.h" + +Value *InlineAssembly::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { Type *voidty = buildTypes->llvmType(tvoid); std::vector arg_types; FunctionType *ftype = FunctionType::get(voidty, ArrayRef(arg_types), false); diff --git a/src/InlineAssembly.h b/src/InlineAssembly.h index 98242a4..9dae37d 100644 --- a/src/InlineAssembly.h +++ b/src/InlineAssembly.h @@ -1,12 +1,12 @@ #pragma once -#include "Header.h" +#include "Node.h" class InlineAssembly: public Node { private: string assembly; public: InlineAssembly(const char *a): assembly(a) { } - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/Int1.cpp b/src/Int1.cpp index c5c65e8..a19f7ff 100644 --- a/src/Int1.cpp +++ b/src/Int1.cpp @@ -1,12 +1,7 @@ -#include "Header.h" +#include "Int1.h" -Value *Int1::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) +Value *Int1::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return ConstantInt::get(Type::getInt1Ty(global_context), number); } - -void Int1::accept(Visitor &v) { - v.visit(*this); -} - diff --git a/src/Int1.h b/src/Int1.h index a7fea4b..06874c1 100644 --- a/src/Int1.h +++ b/src/Int1.h @@ -1,18 +1,23 @@ #pragma once +#include "Node.h" + class Int1: public Node { - private: - char number; - public: - Int1(char n): number(n) {} - char getNumber() const { return number; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { - return true; - } - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { - return tbool; - } +private: + char number; + +public: + Int1(char n): number(n) {} + char getNumber() const { return number; } + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tbool; + } + }; diff --git a/src/Int16.cpp b/src/Int16.cpp index c6bfc73..8acf1a9 100644 --- a/src/Int16.cpp +++ b/src/Int16.cpp @@ -1,11 +1,6 @@ -#include "Header.h" + #include "Int16.h" -Value *Int16::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *Int16::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return ConstantInt::get(Type::getInt16Ty(global_context), number, IsSigned); } - -void Int16::accept(Visitor &v) { - v.visit(*this); -} - diff --git a/src/Int16.h b/src/Int16.h index fa91b7a..6f427a5 100644 --- a/src/Int16.h +++ b/src/Int16.h @@ -6,17 +6,22 @@ class Int16: public Node { private: short number; bool IsSigned; + public: Int16(short n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + short getNumber() const { return number; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { return true; } - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + + virtual DataType getDataType() override { return tint16; } + }; #endif diff --git a/src/Int32.cpp b/src/Int32.cpp index 3d8a1bf..84b7a67 100644 --- a/src/Int32.cpp +++ b/src/Int32.cpp @@ -1,9 +1,6 @@ -#include "Header.h" -Value *Int32::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt32Ty(global_context), number, IsSigned); -} +#include "Int32.h" -void Int32::accept(Visitor &v) { - v.visit(*this); +Value *Int32::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt32Ty(global_context), number, IsSigned); } diff --git a/src/Int32.h b/src/Int32.h index 725c62f..a80bb25 100644 --- a/src/Int32.h +++ b/src/Int32.h @@ -1,22 +1,25 @@ -#ifndef __INT32_H__ -#define __INT32_H__ + +#pragma once + +#include "Node.h" class Int32: public Node { private: int number; bool IsSigned; + public: Int32(int n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + int getNumber() const { return number; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { return true; } - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + + virtual DataType getDataType() override { return tint32; } }; - -#endif diff --git a/src/Int64.cpp b/src/Int64.cpp index edbb58e..86523dd 100644 --- a/src/Int64.cpp +++ b/src/Int64.cpp @@ -1,10 +1,6 @@ -#include "Header.h" -Value *Int64::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt64Ty(global_context), number, IsSigned); -} +#include "Int64.h" -void Int64::accept(Visitor &v) { - v.visit(*this); +Value *Int64::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt64Ty(global_context), number, IsSigned); } - diff --git a/src/Int64.h b/src/Int64.h index cac3f4c..4f323c7 100644 --- a/src/Int64.h +++ b/src/Int64.h @@ -1,21 +1,25 @@ -#ifndef __INT64_H__ -#define __INT64_H__ + +#pragma once + +#include "Node.h" class Int64: public Node { private: int number; bool IsSigned; + public: Int64(int n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + int getNumber() const { return number; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { return true; } - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { + + virtual DataType getDataType() override { return tint64; } }; - -#endif diff --git a/src/Int8.cpp b/src/Int8.cpp index 1545edd..a14087c 100644 --- a/src/Int8.cpp +++ b/src/Int8.cpp @@ -1,12 +1,7 @@ -#include "Header.h" +#include "Int8.h" -Value *Int8::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) +Value *Int8::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return ConstantInt::get(Type::getInt8Ty(global_context), number, IsSigned); } - -void Int8::accept(Visitor &v) { - v.visit(*this); -} - diff --git a/src/Int8.h b/src/Int8.h index ae0e670..96273d7 100644 --- a/src/Int8.h +++ b/src/Int8.h @@ -1,21 +1,22 @@ -#ifndef __INT8_H__ -#define __INT8_H__ + +#pragma once + +#include "Node.h" class Int8: public Node { - private: - char number; - bool IsSigned; - public: - Int8(char n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} - char getNumber() const { return number; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override { - return true; - } - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override { - return tint8; - } -}; +private: + char number; + bool IsSigned; -#endif +public: + Int8(char n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + char getNumber() const { return number; } + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tint8; + } +}; diff --git a/src/Interface.cpp b/src/Interface.cpp index 419c8ee..affc9da 100644 --- a/src/Interface.cpp +++ b/src/Interface.cpp @@ -1,16 +1,28 @@ -#include "Header.h" +#include "Interface.h" +#include "UserType.h" +#include "FunctionImpl.h" -Value *Interface::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - for(const auto n : symbols) { - printf("Symbol %s exists here!\n", n.first.c_str()); +void Interface::createDataType() { + StructType *intftype = StructType::create(global_context, name); + unsigned dt = buildTypes->addDataType(this, intftype); + if (dt == BuildTypes::undefinedType) { + yyerrorcpp("Type " + name + " alread defined.", this); + yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); } +} + +Value *Interface::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + /*printf("Interface %s defined with:\n", name.c_str()); + for(const auto n : getSymbols()) { + printf("\t%s\n", n.first.c_str()); + }*/ return NULL; } bool Interface::validateImplementation(UserType *ut) { bool result = true; - for(const auto & [key, func_decl] : symbols) { + for(const auto & [key, func_decl] : getSymbols()) { auto symb = ut->findSymbol(key, false); FunctionImpl *fimpl = dynamic_cast(symb); if (!symb) { diff --git a/src/Interface.h b/src/Interface.h index 960ecf2..c9a21d9 100644 --- a/src/Interface.h +++ b/src/Interface.h @@ -4,12 +4,17 @@ #include "Node.h" class Interface: public NamedNode { +private: + void createDataType(); + public: - Interface(const string name): NamedNode(name) {} + Interface(const string& name) : NamedNode(name) {} - Interface(const string name, vector &&funcs): NamedNode(name, std::move(funcs)) {} + Interface(const string& name, vector stmts): NamedNode(name, std::move(stmts)) { + createDataType(); + } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; bool validateImplementation(UserType *ut); }; diff --git a/src/Language.l b/src/Language.l index 96fd24e..fdf72bb 100644 --- a/src/Language.l +++ b/src/Language.l @@ -1,23 +1,11 @@ %{ - -#include "Header.h" +#include #include "Language_gen_y.hpp" extern void unescape(char *s); +void update_loc(location_t *yylloc, int lineno, int leng, char *text); -static void update_loc(location_t *yylloc, int lineno, int leng, char *text) { - yylloc->first_line = yylloc->last_line; - yylloc->last_line = yylloc->last_column; - if (yylloc->last_line == lineno) - yylloc->last_column += leng; - else { - yylloc->last_line = lineno; - yylloc->last_column = text + leng - strrchr(text, '\n'); - } -} - #define YY_USER_ACTION update_loc(yylloc, yylineno, yyleng, yytext); - %} %option noinput nounput noyywrap @@ -27,6 +15,10 @@ static void update_loc(location_t *yylloc, int lineno, int leng, char *text) { %x COMMENT +A [a-zA-Z_] +D [0-9] +ID {A}({A}|{D})* + %% [ \t\r\n] { /* ignore spaces */ } @@ -40,17 +32,6 @@ static void update_loc(location_t *yylloc, int lineno, int leng, char *text) { "register" { return TOK_REGISTER; } "volatile" { return TOK_VOLATILE; } "const" { return TOK_CONST; } -"void" { return TOK_VOID; } -"bool" { return TOK_FBOOL; } -"char" { return TOK_FCHAR; } -"int8" { return TOK_FINT8; } -"int16" { return TOK_FINT16; } -"int32" { return TOK_FINT32; } -"int64" { return TOK_FINT64; } -"float" { return TOK_FFLOAT; } -"double" { return TOK_FDOUBLE; } -"long" { return TOK_FLONG; } -"unsigned" { return TOK_FUNSIGNED; } "return" { return TOK_RETURN; } "true" { return TOK_TRUE; } "false" { return TOK_FALSE; } @@ -123,9 +104,13 @@ static void update_loc(location_t *yylloc, int lineno, int leng, char *text) { "," { return ','; } ";" { return ';'; } -[a-zA-Z_][a-zA-Z0-9_]* { yylval->ident = strndup(yytext, yyleng); +{ID} { yylval->ident = strndup(yytext, yyleng); return TOK_IDENTIFIER; } +{ID}(\.{ID})+ { yylval->ident = strndup(yytext, yyleng); + return TOK_XIDENTIFIER; + } + [0-9]+\.[0-9]+ { char *aux = strndup(yytext, yyleng); yylval->nfloat = strtof(aux, NULL); free(aux); @@ -160,9 +145,24 @@ static void update_loc(location_t *yylloc, int lineno, int leng, char *text) { unescape(yylval->str); return TOK_STRING; } +'\\?.' { char *aux = strndup(yytext+1, yyleng-2); + unescape(aux); + yylval->nint = aux[0]; + free(aux); + return TOK_INTEGER; } + /* deixar por último. Caractere não reconhecido pelo alfabeto. */ . { yyerror(yylloc, NULL, COLOR_RED "lexical error:" COLOR_RED " caractere nao pertence ao alfabeto da linguagem:"); } %% - +void update_loc(location_t *loc, int lineno, int leng, char *text) { + loc->first_line = loc->last_line; + loc->last_line = loc->last_column; + if (loc->last_line == lineno) + loc->last_column += leng; + else { + loc->last_line = lineno; + loc->last_column = text + leng - strrchr(text, '\n'); + } +} diff --git a/src/Language.y b/src/Language.y index a800686..b7e193c 100644 --- a/src/Language.y +++ b/src/Language.y @@ -1,6 +1,7 @@ %name-prefix="MAIN" //%define api.prefix {MAIN} // not working in Bison 3.8.2 +%define parse.error verbose %code provides { #define YY_DECL int MAINlex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) @@ -8,10 +9,10 @@ void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); } -%type term term2 expr factor stmt gstmt condblock elseblock whileblock logicexpr +%type term term2 expr factor stmt gstmt condblock whileblock logicexpr %type logicterm logicfactor TOK_AND TOK_OR printstmt fe eventblock unary -%type funcblock func_decl func_impl returnblock registerstmt cast -%type interfacestmt typestmt +%type funcblock func_decl func_impl returnblock registerstmt +%type interfacestmt typestmt attribution %type typestmt_impls %type element %type elements relements @@ -19,53 +20,54 @@ %type funcparams %type paramscall %type melement -%type matrix rmatrix -%type stmts gstmts +%type matrix +%type stmts gstmts elseblock %type TOK_OUT TOK_IN -%type TOK_INTEGER +%type TOK_INTEGER qualifier %type TOK_FLOAT %type TOK_DOUBLE %type TOK_LDOUBLE -%type TOK_IDENTIFIER +%type TOK_IDENTIFIER TOK_XIDENTIFIER ident_or_xident %type TOK_STRING asminline %type TOK_STEPPER -%type
type_f registertype %type struct_field %type struct_fields -%type complex_identifier %type error %type intf_decls %% -programa : gstmts { - // interruptions setup - for(AttachInterrupt *a : vectorglobal) { - $1->prepend(a); - } - - Program p(std::move(*$1)); - - /*std::fstream fs; - fs.open("ast", std::fstream::out); - PrintAstVisitor(fs).visit(p); - fs.close();*/ - - if (errorsfound == 0) - p.generate(); - }; - ; +programa : gstmts { + for(auto stmt : *($gstmts)) { + program->addChild(stmt); + } -gstmts : gstmts gstmt { $1->append($gstmt);} - | gstmt { $$ = new Stmts($gstmt); $gstmt->setLocation(@gstmt); } - ; + /*std::fstream fs; + fs.open("ast", std::fstream::out); + PrintAstVisitor(fs).visit(p); + fs.close();*/ + + if (errorsfound == 0) + program->generate(); +}; + +gstmts : gstmts gstmt { + $1->push_back($gstmt); + //$gstmt->setScope(program); +} + +gstmts : gstmt { + $$ = new vector(); + if ($gstmt) { + $$->push_back($gstmt); + //$gstmt->setScope(program); + $gstmt->setLocation(@gstmt); + } +} -gstmt : TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($1, $3, qnone); } - | complex_identifier '=' expr ';' { $$ = new Scalar($1, $3, qnone); } - | TOK_CONST TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qconst); } - | TOK_VOLATILE TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($2, $4, qvolatile); } - | TOK_IDENTIFIER '=' relements ';' { $$ = new Array($1, $3); $$->setLocation(@1); } - | TOK_IDENTIFIER '=' rmatrix ';' { $$ = new Matrix($1, $3);} +gstmt : TOK_USE TOK_IDENTIFIER ';' { parseUseFile($2, @TOK_USE); $$ = NULL; } + | attribution ';' { $$ = $1; } + | qualifier attribution ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } | registerstmt { $$ = $1; } | interfacestmt { $$ = $1; } | typestmt { $$ = $1; } @@ -74,38 +76,64 @@ gstmt : TOK_IDENTIFIER '=' expr ';' { $$ = new Scalar($1, $3, qnone); } $$ = new Int8(0); // evita falha de segmentacao }; +attribution : ident_or_xident[id] '=' expr { + $$ = new Scalar($id, $expr); + $$->setLocation(@id); +} + +attribution : ident_or_xident[id] '=' '{' elements '}' { + $$ = new Array($id, $elements); + $$->setLocation(@id); +} + +attribution : ident_or_xident[id] '=' '{' matrix '}' { + $$ = new Matrix($id, $matrix); + $$->setLocation(@id); +} + +qualifier : TOK_CONST { $$ = qconst; } + | TOK_VOLATILE { $$ = qvolatile; } + fe : funcblock { $$ = $1; } | eventblock { $$ = $1; } ; funcblock : func_decl | func_impl ; -func_decl : type_f TOK_IDENTIFIER '(' funcparams ')' ';' { - $$ = new FunctionDecl($1, $2, $4); - $$->setLocation(@type_f); +func_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' funcparams ')' ';' { + $$ = new FunctionDecl(buildTypes->getType($type, true), $id, $funcparams); + $$->setLocation(@type); } -func_impl : type_f TOK_IDENTIFIER '(' funcparams ')' '{' stmts '}'[ef] { - $$ = new FunctionImpl($1, $2, $4, $7, @ef); - $$->setLocation(@type_f); +func_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' funcparams ')' '{' stmts '}'[ef] { + $$ = new FunctionImpl(buildTypes->getType($type, true), $id, $funcparams, + std::move(*$stmts), @ef); + $$->setLocation(@type); } ; eventblock : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { - char funcname[100]; + /*char funcname[100]; snprintf(funcname, 100, "__callback_int_p%d_e%d", (int)$2, (int)$4); vectorglobal.push_back(new AttachInterrupt($2, funcname, $4)); FunctionParams *fps = new FunctionParams(); - $$ = new FunctionImpl(tvoid, funcname, fps, $6, @ef); + $$ = new FunctionImpl(tvoid, funcname, fps, $6, @ef);*/ + return 0; } ; -stmts : stmts stmt { $1->append($stmt); } - | stmt { $$ = new Stmts($stmt); $stmt->setLocation(@stmt); } - ; +stmts : stmts stmt { + $1->push_back($stmt); +} + +stmts : stmt { + $$ = new vector(); + $$->push_back($stmt); + $stmt->setLocation(@stmt); +} stmt : gstmt { $$ = $1; } | TOK_OUT '=' expr ';' { $$ = new OutPort($1, $3); } - | TOK_IDENTIFIER '(' paramscall ')' ';' { $$ = new FunctionCall($1, $3); } + | ident_or_xident[id] '(' paramscall ')' ';' { $$ = new FunctionCall($id, $3); $$->setLocation(@id);} | TOK_IDENTIFIER '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '+', new Int8(1))); } | TOK_IDENTIFIER '-' '-' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '-', new Int8(1))); } | TOK_IDENTIFIER '+' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '+', $4)); } @@ -124,8 +152,6 @@ stmt : gstmt { $$ = $1; } | TOK_IDENTIFIER '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6);} | TOK_IDENTIFIER '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9); } -rmatrix : '{' matrix '}' { $$ = $2; } - ; matrix : matrix ',' melement { $1->append($3); $$ = $1; } @@ -135,10 +161,8 @@ matrix : matrix ',' melement { $1->append($3); ; -melement : relements ':' TOK_INTEGER { MatrixElement me {$1, (unsigned)$3}; - $$ = me; } - | relements { MatrixElement me {$1, 1}; - $$ = me; } +melement : relements ':' TOK_INTEGER { $$ = new MatrixElement($1, (unsigned)$3); } + | relements { $$ = new MatrixElement($1, 1);} ; relements : '{' elements '}' { $$ = $2; } @@ -151,10 +175,8 @@ elements : elements ',' element { $1->append($3); $$ = aes; } ; -element : factor ':' TOK_INTEGER { ArrayElement ae{$1, (unsigned)$3}; - $$ = ae; } - | factor { ArrayElement ae{$1, 1}; - $$ = ae; } +element : factor ':' TOK_INTEGER { $$ = new ArrayElement($1, (unsigned)$3); } + | factor { $$ = new ArrayElement($1, 1); } ; funcparams: funcparams ',' funcparam { @@ -172,34 +194,9 @@ funcparams: funcparams ',' funcparam { } ; -funcparam : type_f TOK_IDENTIFIER[id] { - $$ = FunctionParam{$id, $type_f}; +funcparam : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] { + $$ = new FunctionParam($id, buildTypes->getType($type, true)); } - | TOK_IDENTIFIER[id1] TOK_IDENTIFIER[id2] { - $$ = FunctionParam{$2, tvoid}; - } - ; - -type_f : TOK_VOID { $$ = tvoid; } - | TOK_FCHAR { $$ = tchar; } - | TOK_FBOOL { $$ = tbool; } - | TOK_FINT8 { $$ = tint8; } - | TOK_FINT16 { $$ = tint16; } - | TOK_FINT32 { $$ = tint32; } - | TOK_FINT64 { $$ = tint64; } - | TOK_FUNSIGNED TOK_FINT8 { $$ = tint8u; } - | TOK_FUNSIGNED TOK_FINT16 { $$ = tint16u; } - | TOK_FUNSIGNED TOK_FINT32 { $$ = tint32u; } - | TOK_FUNSIGNED TOK_FINT64 { $$ = tint64u; } - | TOK_FFLOAT { $$ = tfloat; } - | TOK_FDOUBLE { $$ = tdouble; } - | TOK_FLONG TOK_FDOUBLE { $$ = tldouble; } -/* | TOK_IDENTIFIER[ident] { - yyerrok; - yyerrorcpp(string_format("Invalid type name '%s'.", $ident), nullptr); - $$ = tvoid; - }*/ - ; paramscall : paramscall ',' expr {$1 -> append($3); $$ = $1;} @@ -213,40 +210,35 @@ paramscall : paramscall ',' expr {$1 -> append($3); returnblock : TOK_RETURN expr { $$ = new Return($2); } | TOK_RETURN logicexpr { $$ = new Return($2); } + | TOK_RETURN { $$ = new Return(); } ; condblock : TOK_IF logicexpr '{' stmts '}' { $logicexpr->setLocation(@logicexpr); - $stmts->setLocation(@stmts); - $$ = new If($logicexpr, $stmts, NULL); + $$ = new If($logicexpr, std::move(*$stmts)); $$->setLocation(@TOK_IF); } | TOK_IF logicexpr '{' stmts '}' elseblock { $logicexpr->setLocation(@logicexpr); - $stmts->setLocation(@stmts); - $$ = new If($logicexpr, $stmts, $elseblock); + $$ = new If($logicexpr, std::move(*$stmts), std::move(*$elseblock)); $$->setLocation(@TOK_IF); } ; -elseblock : TOK_ELSE '{' stmts '}' { - $$ = $stmts; - $$->setLocation(@stmts); - } - ; +elseblock : TOK_ELSE '{' stmts '}' { $$ = $stmts; } whileblock : TOK_WHILE logicexpr '{' stmts '}' { $logicexpr->setLocation(@logicexpr); - $$ = new While($logicexpr, $stmts); + $$ = new While($logicexpr, std::move(*$stmts)); $$->setLocation(@TOK_WHILE); } | TOK_WHILE logicexpr ';' { $logicexpr->setLocation(@logicexpr); - $$ = new While($logicexpr, new Stmts()); + $$ = new While($logicexpr); $$->setLocation(@TOK_WHILE); } | TOK_LOOP '{' stmts '}' { - $$ = new Loop($stmts); + $$ = new Loop(std::move(*$stmts)); $$->setLocation(@TOK_LOOP); } ; @@ -288,10 +280,9 @@ term2 : term2 '&' factor { $$ = new BinaryOp($1, '&', $3); } ; factor : '(' expr ')' { $$ = $2; } - | TOK_IDENTIFIER { $$ = new Load($1); } + | ident_or_xident { $$ = new Load($1); } | TOK_IDENTIFIER '[' expr ']' { $$ = new LoadArray($1, $3);} | TOK_IDENTIFIER '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6);} - | complex_identifier { $$ = new Load($1); } | TOK_TRUE { $$ = new Int1(1); } | TOK_FALSE { $$ = new Int1(0); } | TOK_INTEGER { $$ = getNodeForIntConst($1); } @@ -299,71 +290,54 @@ factor : '(' expr ')' { $$ = $2; } | TOK_DOUBLE { $$ = new Double($1); } | TOK_LDOUBLE { $$ = new Float128($1); } | TOK_IN { $$ = new InPort($1); } - | TOK_IDENTIFIER '(' paramscall ')' { $$ = new FunctionCall($1, $3); } + | ident_or_xident[id] '(' paramscall ')' { $$ = new FunctionCall($id, $paramscall); $$->setLocation(@id); } | unary { $$ = $1; } ; -complex_identifier : complex_identifier '.' TOK_IDENTIFIER { - $1->names.push_back($3); - $$ = $1; - } - | TOK_IDENTIFIER '.' TOK_IDENTIFIER { - ComplexIdentifier *complexIdent = new ComplexIdentifier(); - complexIdent->names.push_back($1); - complexIdent->names.push_back($3); - $$ = complexIdent; - } - ; +ident_or_xident: TOK_IDENTIFIER | TOK_XIDENTIFIER unary : '-' factor { $$ = new BinaryOp($2, '*', getNodeForIntConst(-1)); } | '~' factor { $$ = new FlipOp($2); } - | cast { $$ = $1; } ; -cast : '(' type_f ')' factor { $$ = new Cast($2, $4); } - ; - -printstmt : TOK_PRINT TOK_STRING { $$ = new Print(new String($2)); } +printstmt : TOK_PRINT TOK_STRING { $$ = new Print(new StringConst($2)); } | TOK_PRINT expr { $$ = new Print($2); } -registerstmt : TOK_REGISTER registertype TOK_IDENTIFIER TOK_AT expr ';' { - $$ = new Pointer($3, $2, $5, true); +registerstmt : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT expr ';' { + $$ = new Pointer($name, buildTypes->getType($type, true), $5); + $$->setQualifier(qvolatile); + $$->setLocation(@name); } - | TOK_REGISTER registertype TOK_IDENTIFIER TOK_AT expr '{' struct_fields '}' { - $$ = new Pointer($3, $2, $5, $7, true); + | TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT expr '{' struct_fields '}' { + $$ = new Pointer($name, buildTypes->getType($type, true), $5, $7); + $$->setLocation(@name); } ; -registertype : TOK_FINT8 { $$ = tint8; } - | TOK_FINT16 { $$ = tint16; } - | TOK_FINT32 { $$ = tint32; } - | TOK_FINT64 { $$ = tint64; } - ; - struct_fields : struct_fields struct_field { - $2.startBit = $1->nextBit; - $1->fields[$2.fieldName] = $2; - $1->nextBit += $2.bitWidth; + $2->startBit = $1->nextBit; + $1->fields[$2->getName()] = $2; + $1->nextBit += $2->bitWidth; $$ = $1; } | struct_field { Structure *s = new Structure(); - $1.startBit = 0; - s->fields[$1.fieldName] = $1; - s->nextBit = $1.bitWidth; + $1->startBit = 0; + s->fields[$1->getName()] = $1; + s->nextBit = $1->bitWidth; $$ = s; } ; -struct_field : type_f TOK_IDENTIFIER ';' { - $$.fieldDataType = $1; - $$.fieldName = $2; - $$.bitWidth = buildTypes->bitWidth($1); +struct_field : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] ';' { + Field *s = new Field($id, buildTypes->getType($type, true)); + s->bitWidth = buildTypes->bitWidth(s->getDataType()); + $$ = s; } - | type_f TOK_IDENTIFIER ':' TOK_INTEGER ';' { - $$.fieldDataType = $1; - $$.fieldName = $2; - $$.bitWidth = (unsigned)$4; + | TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] ':' TOK_INTEGER[bit] ';' { + Field *s = new Field($id, buildTypes->getType($type, true)); + s->bitWidth = (unsigned)$bit; + $$ = s; } ; diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index 6dd3b06..a66de44 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -2,12 +2,13 @@ %locations %define api.location.type {location_t} %define api.pure full -%define parse.error verbose +%define parse.lac full %param {yyscan_t scanner} %code top { #include #include + #define SCANNER_OR_VISITOR #include "Header.h" } @@ -15,6 +16,7 @@ #ifndef YYLTYPE #define YYLTYPE location_t #endif + #include "FlexDependencies.h" } %token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST TOK_ASM @@ -23,7 +25,8 @@ %token TOK_PRINT %token TOK_IN TOK_OUT TOK_STEPPER TOK_SERVO %token TOK_DELAY TOK_AND TOK_OR -%token TOK_IDENTIFIER TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE +%token TOK_IDENTIFIER TOK_XIDENTIFIER +%token TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE %token TOK_FINT8 TOK_FINT16 TOK_FINT32 TOK_FINT64 %token TOK_FFLOAT TOK_FDOUBLE TOK_FCHAR TOK_FLONG TOK_FUNSIGNED TOK_FBOOL %token TOK_TYPE TOK_INTF TOK_IMPL TOK_USE @@ -40,20 +43,17 @@ double ndouble; long double nldouble; Node *node; - Stmts *stmt; - ArrayElement ae; ArrayElements *aes; - MatrixElement me; MatrixElements *mes; - FunctionParam fp; FunctionParams *fps; ParamsCall *pc; - BasicDataType dt; - Field field; Structure *structure; - ComplexIdentifier *complexIdent; vector *nodes; vector *strings; + ArrayElement *ae; + MatrixElement *me; + FunctionParam *fp; + Field *field; } %start programa diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 29bf29d..2f54a1b 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -1,54 +1,78 @@ %name-prefix="USE" //%define api.prefix {USE} // not working in Bison 3.8.2 +%define parse.error verbose +//%define parse.trace %code provides { #define YY_DECL int USElex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) YY_DECL; void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); + //#define YYDEBUG 1 } -%type gstmts -%type gstmt register interface type -%type function function_decl function_impl +%type gstmts +%type gstmt register interface type ignores ignore_once ignore use +%type function function_decl function_impl var_decl %type function_params %type function_param %type intf_decls %type const_expr %type TOK_IDENTIFIER %type TOK_INTEGER -%type
type_f register_type %type struct_fields -%type struct_field -%type type_impls +%type struct_field +%type type_impls +%type error; %% -programa : gstmts - ; +programa : gstmts { + for(auto stmt : *($gstmts)) { + program->addChild(stmt); + } +} + +gstmts : gstmts gstmt { + $1->push_back($gstmt); + //$gstmt->setScope(program); +} -gstmts : gstmts gstmt { $1->append($gstmt);} - | gstmt { $$ = new Stmts($gstmt); $gstmt->setLocation(@gstmt); } - ; +gstmts : gstmt { + $$ = new vector(); + if ($gstmt) { + $$->push_back($gstmt); + //$gstmt->setScope(program); + $gstmt->setLocation(@gstmt); + } +} -gstmt : register { } - | interface { } - | type { } - | function { } - | ignore { } - ; +gstmt : register + | interface + | type + | function + | var_decl + | ignore_once + | use -function : function_decl | function_impl ; +use : TOK_USE TOK_IDENTIFIER ';' { + parseUseFile($2, @TOK_USE); + $$ = NULL; +} -function_decl : type_f TOK_IDENTIFIER '(' function_params ')' ';' { - $$ = new FunctionDecl($1, $2, $4); - $$->setLocation(@type_f); -}; +function : function_decl | function_impl -function_impl : type_f TOK_IDENTIFIER '(' function_params ')' '{' gstmt '}'[ef] { - $$ = new FunctionDecl($1, $2, $4); - $$->setLocation(@type_f); -}; +function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER '(' function_params ')' ';' { + $$ = new FunctionDecl(buildTypes->getType($type, true), $2, $4); + $$->setLocation(@type); +} + +function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' '{' ignores '}'[ef] { + vector auxvec; + $$ = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, + std::move(auxvec), @ef); + $$->setLocation(@type); +} function_params: function_params ',' function_param { $1 -> append($3); @@ -66,95 +90,66 @@ function_params: %empty { $$ = fps; } -function_param : type_f TOK_IDENTIFIER[id] { - $$ = FunctionParam{$id, $type_f}; - } - | TOK_IDENTIFIER[id1] TOK_IDENTIFIER[id2] { - $$ = FunctionParam{$2, tvoid}; - } - ; - -type_f : TOK_VOID { $$ = tvoid; } - | TOK_FCHAR { $$ = tchar; } - | TOK_FBOOL { $$ = tbool; } - | TOK_FINT8 { $$ = tint8; } - | TOK_FINT16 { $$ = tint16; } - | TOK_FINT32 { $$ = tint32; } - | TOK_FINT64 { $$ = tint64; } - | TOK_FUNSIGNED TOK_FINT8 { $$ = tint8u; } - | TOK_FUNSIGNED TOK_FINT16 { $$ = tint16u; } - | TOK_FUNSIGNED TOK_FINT32 { $$ = tint32u; } - | TOK_FUNSIGNED TOK_FINT64 { $$ = tint64u; } - | TOK_FFLOAT { $$ = tfloat; } - | TOK_FDOUBLE { $$ = tdouble; } - | TOK_FLONG TOK_FDOUBLE { $$ = tldouble; } -/* | TOK_IDENTIFIER[ident] { - yyerrok; - yyerrorcpp(string_format("Invalid type name '%s'.", $ident), nullptr); - $$ = tvoid; - }*/ - ; - -register : TOK_REGISTER register_type TOK_IDENTIFIER TOK_AT const_expr ';' { - $$ = new Pointer($3, $2, $5, true); - } - | TOK_REGISTER register_type TOK_IDENTIFIER TOK_AT const_expr '{' struct_fields '}' { - $$ = new Pointer($3, $2, $5, $7, true); - } - ; +function_param : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] { + $$ = new FunctionParam($id, buildTypes->getType($type, true)); +} -register_type : TOK_FINT8 { $$ = tint8; } - | TOK_FINT16 { $$ = tint16; } - | TOK_FINT32 { $$ = tint32; } - | TOK_FINT64 { $$ = tint64; } - ; +register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT const_expr ';' { + $$ = new Pointer($name, buildTypes->getType($type, true), $5); + $$->setQualifier(qvolatile); + $$->setLocation(@name); +} + +register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT const_expr '{' struct_fields '}' { + $$ = new Pointer($name, buildTypes->getType($type, true), $5, $7); + $$->setLocation(@name); +} struct_fields : struct_fields struct_field { - $2.startBit = $1->nextBit; - $1->fields[$2.fieldName] = $2; - $1->nextBit += $2.bitWidth; + $2->startBit = $1->nextBit; + $1->fields[$2->getName()] = $2; + $1->nextBit += $2->bitWidth; $$ = $1; } | struct_field { Structure *s = new Structure(); - $1.startBit = 0; - s->fields[$1.fieldName] = $1; - s->nextBit = $1.bitWidth; + $1->startBit = 0; + s->fields[$1->getName()] = $1; + s->nextBit = $1->bitWidth; $$ = s; } ; -struct_field : type_f TOK_IDENTIFIER ';' { - $$.fieldDataType = $1; - $$.fieldName = $2; - $$.bitWidth = buildTypes->bitWidth($1); +struct_field : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] ';' { + Field *s = new Field($id, buildTypes->getType($type, true)); + s->bitWidth = buildTypes->bitWidth(s->getDataType()); + $$ = s; } - | type_f TOK_IDENTIFIER ':' TOK_INTEGER ';' { - $$.fieldDataType = $1; - $$.fieldName = $2; - $$.bitWidth = (unsigned)$4; + | TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] ':' TOK_INTEGER[bit] ';' { + Field *s = new Field($id, buildTypes->getType($type, true)); + s->bitWidth = (unsigned)$bit; + $$ = s; } - ; interface : TOK_INTF TOK_IDENTIFIER '{' intf_decls '}' { $$ = new Interface($TOK_IDENTIFIER, std::move(*$intf_decls)); $$->setLocation(@TOK_INTF); -}; +} interface : TOK_INTF TOK_IDENTIFIER '{' '}' { $$ = new Interface($TOK_IDENTIFIER); $$->setLocation(@TOK_INTF); -}; +} intf_decls : intf_decls function_decl { $1->push_back($function_decl); $$ = $1; -}; +} intf_decls : function_decl { $$ = new vector(); $$->push_back($function_decl); -}; +} type : TOK_TYPE TOK_IDENTIFIER TOK_IMPL type_impls '{' gstmts '}' { $$ = new UserType($TOK_IDENTIFIER, std::move(*$gstmts), std::move(*$type_impls)); @@ -176,9 +171,107 @@ type_impls : TOK_IDENTIFIER { $$->push_back($1); } +var_decl : TOK_IDENTIFIER '=' const_expr ';' { $$ = new Scalar($1, $3); }; + const_expr : TOK_INTEGER { $$ = getNodeForIntConst($1); } -ignore : error { yyerrok; }; +ignores : ignores ignore_once + | ignore_once + +ignore_once : ignore ';' { $$ = NULL; } + | error ';' { $$ = NULL; } + | error '}' { $$ = NULL; } + +/* put here any symbol that can start a stmt (except globals) + * to be precise, the FIRST(stmt) + */ +ignore : TOK_IDENTIFIER { YYERROR; } + | TOK_WHILE { YYERROR; } + | TOK_RETURN { YYERROR; } + | TOK_CONST { YYERROR; } + | TOK_VOLATILE { YYERROR; } + | TOK_IF { YYERROR; } + | TOK_LOOP { YYERROR; } + | TOK_ASM { YYERROR; } + | TOK_PRINT { YYERROR; } + | TOK_DELAY { YYERROR; } %% +/*static const char * +error_format_string (int argc) +{ + switch (argc) + { + default: // Avoid compiler warnings. + case 0: return "%@: syntax error"; + case 1: return "%@: syntax error: unexpected %u"; + // TRANSLATOR '%@' is a location in a file, '%u' is an + // "unexpectetoken", and '%0e', '%1e'... are expected tokens + // at this pot. + // + // For instan on the expression "1 + * 2", you'd get + // + // 1.5: syntaerror: expected - or ( or number or function or variable before * + case 2: return "%@: syntax error: expected %0e before %u"; + case 3: return "%@: syntax error: expected %0e or %1e before %u"; + case 4: return "%@: syntax error: expected %0e or %1e or %2e before %u"; + case 5: return "%@: syntax error: expected %0e or %1e or %2e or %3e before %u"; + case 6: return "%@: syntax error: expected %0e or %1e or %2e or %3e or %4e before %u"; + case 7: return "%@: syntax error: expected %0e or %1e or %2e or %3e or %4e or %5e before %u"; + case 8: return "%@: syntax error: expected %0e or %1e or %2e or %3e or %4e or %5e etc., before %u"; + } +} + +static int yyreport_syntax_error (const yypcontext_t *ctx, yyscan_t scanner) { + enum { ARGS_MAX = 6 }; + yysymbol_kind_t arg[ARGS_MAX]; + + int argsize = yypcontext_expected_tokens (ctx, arg, ARGS_MAX); + if (argsize < 0) + return argsize; + + const int too_many_expected_tokens = argsize == 0 && arg[0] != YYSYMBOL_YYEMPTY; + if (too_many_expected_tokens) + argsize = ARGS_MAX; + + const char *format = error_format_string (1 + argsize + too_many_expected_tokens); + + const YYLTYPE *loc = yypcontext_location (ctx); + while (*format) { + // %@: location. + if (format[0] == '%' && format[1] == '@') { + fprintf(stderr, "%s:%d:%d:", build_filename(), + loc->first_line, loc->first_column); + format += 2; + } + // %u: unexpected token. + else if (format[0] == '%' && format[1] == 'u') { + fputs (yysymbol_name (yypcontext_token (ctx)), stderr); + format += 2; + } + // %0e, %1e...: expected token. + else if (format[0] == '%' && isdigit ((unsigned char) format[1]) + && format[2] == 'e' && (format[1] - '0') < argsize) { + + int i = format[1] - '0'; + fputs (yysymbol_name (arg[i]), stderr); + format += 3; + } else { + fputc (*format, stderr); + ++format; + } + } + fputc ('\n', stderr); + + // Quote the source line. + { + fprintf (stderr, "%5d | %s\n", loc->first_line, uctx->line); + fprintf (stderr, "%5s | %*s", "", loc->first_column, "^"); + for (int i = loc->last_column - loc->first_column - 1; 0 < i; --i) + putc ('~', stderr); + putc ('\n', stderr); + } + + return 0; +}*/ diff --git a/src/Load.cpp b/src/Load.cpp index 7f6fd63..47aae6c 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -1,80 +1,85 @@ -#include "Header.h" -BasicDataType Load::getResultType(BasicBlock *block, BasicBlock *allocblock) { - auto rsym = search_symbol(ident, allocblock, block); - if (rsym) { - if (complexIdent) { - auto it = rsym->structure->fields.find(complexIdent->names[1]); - if (it != rsym->structure->fields.end()) { - return it->second.fieldDataType; - } - } else - return rsym->dt; - } - return tvoid; -} - -Value* Load::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - auto rsym = search_symbol(ident, allocblock, block); - if (rsym == NULL) { - yyerrorcpp("Variable " + ident + " not defined.", this); - return NULL; - } - Field field; +#include "Load.h" +#include "HeaderExternals.h" +#include "Scalar.h" +#include "FunctionImpl.h" +#include "Variable.h" - // semantic validation of complexIdent - if (complexIdent) { - string idfield = complexIdent->names[1]; - auto fieldit = rsym->structure->fields.find(idfield); - if (fieldit == rsym->structure->fields.end()) { - yyerrorcpp("Field " + idfield + " not declared in " + ident, this); - return NULL; - } else { - field = fieldit->second; +DataType Load::getDataType() { + if (dt == BuildTypes::undefinedType) { + Node *rsym = ident.getSymbol(getScope()); + if (rsym) { + dt = rsym->getDataType(); } } + return dt; +} + +Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - auto sym = rsym->value; - if (rsym->qualifier == qconst) - return sym; + Node *isymbol = ident.getSymbol(getScope()); + if (isymbol->isConstExpr()) + return isymbol->getLLVMValue(func); + + Variable *symbol = dynamic_cast(isymbol); + if (!symbol) + return NULL; if (block == NULL && (allocblock == NULL || allocblock == global_alloc)) { // trying to load a variable to initialize a global one. // permitted only for const globals - if (rsym->qualifier != qconst) { - yyerrorcpp("Can't not use '" + ident + "' to define another var/const in global context.", this); + if (!symbol->hasQualifier(qconst)) { + yyerrorcpp("Can not use '" + ident.getFullName() + "' to define another var/const in global context.", this); return NULL; } } RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); + + Value *alloc; + if (ident.isComplex()) { + Identifier istem = ident.getStem(); + Node *stem = istem.getSymbol(getScope()); + alloc = symbol->getLLVMValue(stem); + + if (stem->hasQualifier(qvolatile)) + symbol->setQualifier(qvolatile); + + // TODO: When accessing a.x.func(), need to load a and gep x + //Load loadstem(ident.getStem()); + //loadstem.setParent(this->parent); + //stem = loadstem.generate(func, block, allocblock); + } else { + alloc = symbol->getLLVMValue(func); + } + + if (!alloc) + return NULL; // Caused by an error on previous statement that defines the symbol + + if (buildTypes->isComplex(symbol->getDataType())) + return alloc; + else { + Type *ty = buildTypes->llvmType(symbol->getDataType()); + return Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), ident.getFullName()); + } - bool vol = rsym->qualifier == qvolatile; - Type *ty = buildTypes->llvmType(rsym->dt); - Value *v = Builder->CreateLoad(ty, sym, vol, ident); + /*if (complexIdent) { + // this code does: + // v = symbol->value << pointerbits - field_start - field_width + // v = v >> pointer_bits - field_width + // - if (complexIdent) { - /* this code does: - * v = symbol->value << pointerbits - field_start - field_width - * v = v >> pointer_bits - field_width - */ int bs = buildTypes->bitWidth(rsym->dt) - field.bitWidth; if (bs - field.startBit > 0) v = Builder->CreateShl(v, ConstantInt::get(ty, bs - field.startBit)); if (bs > 0) v = Builder->CreateAShr(v, ConstantInt::get(ty, bs)); v = Builder->CreateTrunc(v, buildTypes->llvmType(field.fieldDataType)); - } - - return v; -} - -void Load::accept(Visitor &v) { - v.visit(*this); + }*/ } -bool Load::isConstExpr(BasicBlock *block, BasicBlock *allocblock) { - RobSymbol *rsym = search_symbol(ident, block, allocblock); - return rsym && (dyn_cast(rsym->value) != NULL); +bool Load::isConstExpr() { + Variable *symbol = dynamic_cast(ident.getSymbol(getScope())); + return symbol && symbol->isConstExpr(); } diff --git a/src/Load.h b/src/Load.h index d0bc191..e99e715 100644 --- a/src/Load.h +++ b/src/Load.h @@ -1,25 +1,19 @@ -#ifndef __LOAD_H__ -#define __LOAD_H__ +#pragma once + #include "Node.h" +#include "Field.h" class Load: public Node { private: - string ident; - ComplexIdentifier *complexIdent; + Identifier ident; public: - Load(const string i): ident(i), complexIdent(nullptr) {} - Load(ComplexIdentifier *ci): complexIdent(ci) { - this->ident = complexIdent->names[0]; - } - - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - - string getIdent() const { return ident; }; + Load(const char* i): ident(i) { } + Load(Identifier i): ident(i) { } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; + virtual DataType getDataType() override; - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) override; + virtual bool isConstExpr() override; - bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) override; }; -#endif diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index d1f3120..7135439 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -1,21 +1,31 @@ -#include "Header.h" -BasicDataType LoadArray::getResultType(BasicBlock *block, BasicBlock *allocblock) { - if (!rsym) - rsym = search_symbol(ident, allocblock, block); - if (rsym) - return rsym->pointee_dt; - return tvoid; +#include "LoadArray.h" +#include "Array.h" +#include "FunctionImpl.h" + +LoadArray::LoadArray(const char *i, Node *pos): ident(i), position(pos) { + addChild(pos); +} + +DataType LoadArray::getDataType() { + if (dt == BuildTypes::undefinedType) { + if (!rsym) + rsym = dynamic_cast(ident.getSymbol(getScope())); + if (rsym) + dt = rsym->getElementDt(); + } + return dt; } -Value *LoadArray::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - rsym = search_symbol(ident, allocblock, block); - /* TODO */ +Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + if (!rsym) + rsym = dynamic_cast(ident.getSymbol(getScope())); if (rsym == NULL) { - yyerrorcpp("Variable " + ident + " not defined.", this); + yyerrorcpp("Variable " + ident.getFullName() + " not defined or not an array/matrix.", this); return NULL; } - auto sym = rsym->value; + auto sym = rsym->getLLVMValue(func); // sym type can be GlobalVariable or AllocInst Type *ty = NULL; @@ -29,21 +39,21 @@ Value *LoadArray::generate(Function *func, BasicBlock *block, BasicBlock *allocb arrayTy = (ArrayType*)ty; } else { - yyerrorcpp("Symbol " + ident + " is not an array.", this); + yyerrorcpp("LLVM Symbol " + ident.getFullName() + " is not an array.", this); return NULL; } - Node *indn = getLoadIndex(rsym, block, allocblock); + Node *indn = getElementIndex(rsym); Value *indice = indn->generate(func, block, allocblock); - if (!indice->getType()->isIntegerTy()){ - yyerrorcpp("Index to update " + ident + " elements should be of type integer.", this); + if (!indice || !indice->getType()->isIntegerTy()){ + yyerrorcpp("Index to access " + ident.getFullName() + " elements must be of type integer.", this); return NULL; } Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); Value* indexList[2] = {zero, indice}; GetElementPtrInst* ptr = GetElementPtrInst::Create(arrayTy, sym, ArrayRef(indexList), "", block); - LoadInst *ret = new LoadInst(ptr->getResultElementType(), ptr, ident, false, block); + LoadInst *ret = new LoadInst(ptr->getResultElementType(), ptr, ident.getFullName(), false, block); return ret; } diff --git a/src/LoadArray.h b/src/LoadArray.h index f659fa0..7be9323 100644 --- a/src/LoadArray.h +++ b/src/LoadArray.h @@ -2,21 +2,22 @@ #pragma once #include "Node.h" +#include "Array.h" +#include "Field.h" class LoadArray: public Node { protected: - string ident; + Identifier ident; Node *position; - RobSymbol *rsym = NULL; + LinearDataStructure *rsym = NULL; public: - LoadArray(const char *i, Node *pos): ident(i), position(pos) {} + LoadArray(const char *i, Node *pos); - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock); - - virtual Node *getLoadIndex(RobSymbol *rsym, BasicBlock *block, BasicBlock *allocblock) { - return position; + virtual Node *getElementIndex(LinearDataStructure *arr) { + return arr->getElementIndex(position, NULL); } + virtual DataType getDataType() override; }; diff --git a/src/LoadMatrix.h b/src/LoadMatrix.h index 787cd73..3c83911 100644 --- a/src/LoadMatrix.h +++ b/src/LoadMatrix.h @@ -1,18 +1,20 @@ #pragma once #include "Node.h" +#include "Array.h" +#include "LoadArray.h" class LoadMatrix: public LoadArray { private: Node *position2; public: - LoadMatrix(const char *i, Node *pos_1, Node *pos_2): LoadArray(i, pos_1) { - this->position2 = pos_2; + LoadMatrix(const char *i, Node *p1, Node *p2): LoadArray(i, p1) { + this->position2 = p2; + addChild(p2); } - virtual Node *getLoadIndex(RobSymbol *rsym, BasicBlock *block, BasicBlock *allocblock) override { - //Generate index of element - Node *mcols = getNodeForIntConst(rsym->matrixCols); - return new BinaryOp(new BinaryOp(position, '*', mcols), '+', position2); + virtual Node *getElementIndex(LinearDataStructure *arr) override { + return arr->getElementIndex(position, position2); } + }; diff --git a/src/Loop.cpp b/src/Loop.cpp index 13bbf26..98e03db 100644 --- a/src/Loop.cpp +++ b/src/Loop.cpp @@ -1,12 +1,13 @@ -#include "Header.h" -Loop::Loop(Node *stms) : stmts(stms) { - node_children.reserve(1); - node_children.push_back(stms); +#include "Loop.h" +#include "FunctionImpl.h" + +Loop::Loop(vector &&stms) : Node(std::move(stms)) { } -Value *Loop::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - BasicBlock *bodyloop = BasicBlock::Create(global_context, "loop_body", func, 0); +Value *Loop::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + BasicBlock *bodyloop = BasicBlock::Create(global_context, "loop_body", + func->getLLVMFunction(), 0); RobDbgInfo.emitLocation(this); @@ -15,7 +16,7 @@ Value *Loop::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) Builder->CreateBr(bodyloop); // alloc instructions inside bodyloop should go to allocblock to prevent repeatedly allocation - Value *newb = stmts->generate(func, bodyloop, allocblock); + Value *newb = generateChildren(func, bodyloop, allocblock); // identify last while body block BasicBlock *endbody = bodyloop; @@ -28,10 +29,7 @@ Value *Loop::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) Builder->CreateBr(bodyloop); } - BasicBlock *endloop = BasicBlock::Create(global_context, "loop_end", func, 0); + BasicBlock *endloop = BasicBlock::Create(global_context, "loop_end", + func->getLLVMFunction(), 0); return endloop; } - -void Loop::accept(Visitor& v) { - v.visit(*this); -} diff --git a/src/Loop.h b/src/Loop.h index 4e6ca97..ddf8cef 100644 --- a/src/Loop.h +++ b/src/Loop.h @@ -4,12 +4,10 @@ #include "Node.h" class Loop: public Node { -private: - Node *stmts; public: - Loop(Node *stms); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; + Loop(vector &&stmts); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + }; #endif diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 529c1f6..93c1c50 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -1,13 +1,32 @@ -#include "Header.h" +#include "Matrix.h" +#include "Coercion.h" +#include "Array.h" +#include "BinaryOp.h" +#include "Visitor.h" +#include "Int16.h" -Value *Matrix::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Matrix::Matrix(const char *n, MatrixElements *me) : LinearDataStructure(n), melements(me) { + NamedConst *rows = new NamedConst("rows", getNodeForIntConst(me->getLineCount())); + NamedConst *cols = new NamedConst("cols", getNodeForIntConst(me->getColumnCount())); + addChild(rows); + addChild(cols); +} + +Node* Matrix::getElementIndex(Node *p1, Node *p2) { + //Generate index of element + Node *mcols = getNodeForIntConst(melements->getColumnCount()); + return new BinaryOp(new BinaryOp(p1, '*', mcols), '+', p2); +} + +Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { /* * Matrix is generated as an array and accessed latter accordingly! */ //Get Type of elements in Vector of Elements, and define as I. - Type* I = buildTypes->llvmType(melements->getMatrixType(block, allocblock)); + element_dt = melements->getMatrixType(func); + Type* I = buildTypes->llvmType(element_dt); // The matrix size unsigned int lines = melements->getLineCount(); @@ -20,19 +39,19 @@ Value *Matrix::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc bool allConst = true; vector elementValues; elementValues.reserve(lines * cols); - for(MatrixElement& i: melements->elements) { - unsigned elCount = i.count; + for(MatrixElement *i: getElements()) { + unsigned elCount = i->count; for (int j=0; jelements) { - Node* elValue = k.value; + for(ArrayElement *k: i->array->getElements()) { + Node* elValue = k->value; Value *val = elValue->generate(func, block, allocblock); if (!val) return NULL; val = Coercion::Convert(val, I, block, elValue); if (!dyn_cast(val)) allConst = false; - for (int l=0; lcount; l++) elementValues.push_back(val); } } @@ -46,7 +65,6 @@ Value *Matrix::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc //Allocate matrix as a vector. //Allocate array. - Value* var; if (allocblock == global_alloc) { // when alloc is global vector constantValues; constantValues.reserve(elementValues.size()); @@ -55,25 +73,25 @@ Value *Matrix::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc ArrayRef constantRefs(constantValues); GlobalVariable *gv = new GlobalVariable(*mainmodule, arrayType, false, GlobalValue::ExternalLinkage, ConstantArray::get(arrayType, constantRefs), name); - var = gv; + //gv->setDSOLocal(true); + alloc = gv; } else { - var = new AllocaInst(arrayType, 0, name, allocblock); + alloc = new AllocaInst(arrayType, 0, name, allocblock); Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); StoreInst *store = NULL; for(unsigned index = 0; index < elementValues.size(); index++) { Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), index); Value* indexList[2] = {zero, idx}; - GetElementPtrInst* gep = GetElementPtrInst::Create(arrayType, var, + GetElementPtrInst* gep = GetElementPtrInst::Create(arrayType, alloc, ArrayRef(indexList), "", block); store = new StoreInst(elementValues[index], gep, false, block); } } - //Add array to table of symbols. - tabelasym[allocblock][name] = new RobSymbol(var); - tabelasym[allocblock][name]->matrixLines = lines; - tabelasym[allocblock][name]->matrixCols = cols; + return alloc; +} - return var; +void Matrix::accept(Visitor& v) { + v.visit(*this); } diff --git a/src/Matrix.h b/src/Matrix.h index e350482..e7d98cf 100644 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -1,13 +1,22 @@ -#ifndef __Matrix_H__ -#define __Matrix_H__ -class Matrix: public Node { +#pragma once + +#include "MatrixElements.h" +#include "Array.h" + +class Matrix: public LinearDataStructure { private: - string name; MatrixElements *melements; public: - Matrix(const char *n, MatrixElements *me) : name(n), melements(me) { } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); -}; + Matrix(const char *n, MatrixElements *me); + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; -#endif + virtual Node *getElementIndex(Node *p1, Node *p2) override; + + std::vector const& getElements() { + return melements->getElements(); + } + + void accept(Visitor& v) override; +}; diff --git a/src/MatrixElements.cpp b/src/MatrixElements.cpp index ee5fdeb..1af9bb0 100644 --- a/src/MatrixElements.cpp +++ b/src/MatrixElements.cpp @@ -1,24 +1,25 @@ -#include "Header.h" + +#include "MatrixElements.h" MatrixElements::MatrixElements() {}; -void MatrixElements::append(MatrixElement& m) { +void MatrixElements::append(MatrixElement *m) { elements.push_back(m); }; -unsigned MatrixElements::getLineCount() const { +unsigned MatrixElements::getLineCount() { unsigned r = 0; for(auto& e : elements) - r += e.count; + r += e->count; return r; }; -unsigned MatrixElements::getColumnCount() const { +unsigned MatrixElements::getColumnCount() { unsigned r = 0; unsigned biggest_r = 0; for(auto& e : elements) { - for (auto& i : e.array->elements) - r += i.count; + for (auto& i : e->array->getElements()) + r += i->count; if (biggest_r < r) biggest_r = r; r = 0; @@ -26,12 +27,12 @@ unsigned MatrixElements::getColumnCount() const { return biggest_r; } -BasicDataType MatrixElements::getMatrixType(BasicBlock *block, BasicBlock *allocblock) const { +DataType MatrixElements::getMatrixType(FunctionImpl *func) { unsigned intsize = 0; unsigned floatsize = 0; for(auto& j : elements) { - for (auto& i : j.array->elements) { - BasicDataType dt = i.value->getResultType(block, allocblock); + for (auto& i : j->array->getElements()) { + DataType dt = i->value->getDataType(); if (buildTypes->isIntegerDataType(dt) && intsize < buildTypes->bitWidth(dt)) intsize = buildTypes->bitWidth(dt); @@ -64,6 +65,6 @@ BasicDataType MatrixElements::getMatrixType(BasicBlock *block, BasicBlock *alloc } } -unsigned MatrixElements::getElementCount(int position) const { - return elements[position].count; +unsigned MatrixElements::getElementCount(int position) { + return elements[position]->count; } diff --git a/src/MatrixElements.h b/src/MatrixElements.h index 970911f..828b952 100644 --- a/src/MatrixElements.h +++ b/src/MatrixElements.h @@ -1,20 +1,29 @@ -#ifndef __MATRIX_ELEMENTS_H__ -#define __MATRIX_ELEMENTS_H__ + +#pragma once #include "Node.h" +#include "ArrayElements.h" + +class MatrixElement { +public: + ArrayElements *array; + unsigned count; + MatrixElement(ArrayElements *array, unsigned count): array(array), count(count) {} +}; class MatrixElements { private: + std::vector elements; public: MatrixElements(); - std::vector elements; - void append(MatrixElement& m); + void append(MatrixElement *m); - unsigned getColumnCount() const; - unsigned getLineCount() const; - unsigned getElementCount(int position) const; - BasicDataType getMatrixType(BasicBlock *block, BasicBlock *allocblock) const; + unsigned getColumnCount(); + unsigned getLineCount(); + unsigned getElementCount(int position); + DataType getMatrixType(FunctionImpl *func); + + std::vector const& getElements() { + return elements; + } }; - -#endif - diff --git a/src/Node.cpp b/src/Node.cpp index 5fcac5c..314fbae 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -1,12 +1,23 @@ -#include "Header.h" -bool Node::isFunctionDecl() -{ - return false; -} +#include "Node.h" +#include "Int8.h" +#include "Int16.h" +#include "Int32.h" +#include "Int64.h" +#include "Visitor.h" Node::~Node() {} +Node::Node(vector &&children, bool constructor) : node_children(children) { + // scalars alread has their scope set in the type + if (!constructor) + setChildrenScope(this); +} + +Node::Node(vector &&children) : node_children(children) { + setChildrenScope(this); +} + std::vector const& Node::children() const { return node_children; } @@ -15,3 +26,89 @@ void Node::accept(Visitor& v) { v.visit(*this); } +Node* Node::findMember(const string& name) { + // look for pseudo fields (array, matrix, register) + Node *m = findSymbol(name, false); + + // force getting dataType in case it was not queried yet + DataType this_dt = getDataType(); + + if (!m && this_dt != BuildTypes::undefinedType) { + // look for fields in the base type + const char *ut_name = buildTypes->name(this_dt); + Node *ut = findSymbol(ut_name); + m = ut->findSymbol(name, false); + } + return m; +} + +Node* Node::findSymbol(const string& name, bool recursive) { + Node *current_scope = this; + do { + auto it = current_scope->symbols.find(name); + if (it != current_scope->symbols.end()) { + return it->second; + } else if (recursive) + current_scope = current_scope->scope; + } while (current_scope && recursive); + + return NULL; +} + +void Node::addChild(Node *n) { + node_children.push_back(n); +} + +void Node::addSymbol(NamedNode *nm) { + // if the variable is already defined in a parent scope, + // don't add it to symbols table in inner scopes. + if (!findSymbol(nm->getName(), true)) { + symbols[nm->getName()] = nm; + } +} + +map const& Node::getSymbols() { + return symbols; +} + +void Node::setScope(Node *s) { + if (scope != NULL) + assert(scope == NULL && "node already has a scope"); + scope = s; +/* if (hasName()) + s->symbols[getName()] = dynamic_cast(this); + for(auto& n : node_children) { + if (!n->scope) + n->setScope(s); + }*/ +} + +void Node::setChildrenScope(Node *s) { + for(auto& n : node_children) { + //n->setScope(s); + } +} + +Value* Node::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return NULL; +} + +Value* Node::generateChildren(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + for(Node *n: getChildren()) { + Value *b = n->generate(func, block, allocblock); + if (b && b->getValueID() == Value::BasicBlockVal) + block = (BasicBlock*)b; + } + return block; +} + +extern Node* getNodeForIntConst(int64_t i) { + if (i >= SCHAR_MIN && i <= SCHAR_MAX) + return new Int8(i); + else if (i >= SHRT_MIN && i <= SHRT_MAX) + return new Int16(i); + else if (i >= INT_MIN && i <= INT_MAX) + return new Int32(i); + else + return new Int64(i); +} diff --git a/src/Node.h b/src/Node.h index e04407a..bf6222b 100644 --- a/src/Node.h +++ b/src/Node.h @@ -1,54 +1,43 @@ #pragma once +#include "SourceLocation.h" +#include "BuildTypes.h" + class Visitor; class NamedNode; class UserType; +class FunctionImpl; class Node : public SourceLocation { protected: + map symbols; vector node_children; - map symbols; - Node *parent = nullptr; - bool update_names = false; - - virtual void updateNamedNodes() { - for(Node *n : node_children) { - if (n->hasName()) - symbols[n->getName()] = n; - } - } + DataType dt = BuildTypes::undefinedType; + set qualifiers; + Node *scope = nullptr; + + virtual void setChildrenScope(Node *scope); public: Node() {} - Node(vector &&children) : node_children(children) { - updateNamedNodes(); - update_names = false; - for(auto c : children) - c->setParent(this); - } + Node(vector &&children); + Node(vector &&children, bool constructor); virtual ~Node(); - virtual bool isFunctionDecl(); - - virtual bool isConstExpr(BasicBlock *block, BasicBlock *allocblock) { + virtual bool isConstExpr() { return false; } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) = 0; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); + + virtual Value *generateChildren(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); virtual std::vector const& children() const; virtual void accept(Visitor &); - virtual BasicDataType getResultType(BasicBlock *block, BasicBlock *allocblock) { - /* this method should be overrided in descending classes - * that define vars/consts - */ - return tvoid; - } - virtual bool hasName() { return false; } @@ -57,24 +46,48 @@ class Node : public SourceLocation { return ""; } - Node *getParent() { - return parent; + Node *getScope() { + return scope; + } + + virtual void setScope(Node *s); + + virtual Node* findSymbol(const string& name, bool recursive = true); + + virtual Node* findMember(const string& name); + + void addChild(Node *n); + + vector const& getChildren() { + return node_children; + } + + map const& getSymbols(); + + virtual void addSymbol(NamedNode *nm); + + void setDataType(DataType dt) { + this->dt = dt; + } + + virtual DataType getDataType() { + return dt; + } + + void setQualifier(DataQualifier dq) { + qualifiers.insert(dq); } - virtual void setParent(Node *p) { - parent = p; + bool hasQualifier(DataQualifier dq) const { + return qualifiers.count(dq) == 1; } - virtual Node* findSymbol(const string& name, bool recursive = true) { - auto it = symbols.find(name); - if (it != symbols.end()) { - return it->second; - } else if (recursive && parent) - return parent->findSymbol(name); - else - return nullptr; + virtual Value* getLLVMValue(Node *stem) { + return NULL; } + virtual void setLeftValue(Value *lv, const string& name) {} + friend class UserType; friend class Program; }; @@ -86,13 +99,20 @@ class NamedNode: public Node { public: NamedNode(const string &name) : name(name) {} - NamedNode(const string &name, vector &&children) : + NamedNode(const string &name, vector &&children) : Node(std::move(children)), name(name) {} - + + NamedNode(const string &name, vector &&children, bool constructor) : + Node(std::move(children), constructor), name(name) {} + string const getName() const override { return name; } + void setName(const string& nname) { + name = nname; + } + bool hasName() override { return true; } diff --git a/src/OutPort.cpp b/src/OutPort.cpp index 75e397e..acf45f9 100644 --- a/src/OutPort.cpp +++ b/src/OutPort.cpp @@ -1,26 +1,29 @@ -#include "Header.h" + +#include "OutPort.h" OutPort::OutPort (const char *p, Node *e) : port(Int8(atoi(p))) { expr = e; - node_children.reserve(2); - node_children.push_back(&port); - node_children.push_back(e); + addChild(&port); + addChild(e); } -Value *OutPort::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - vector args; - - args.push_back(port.generate(func, block, allocblock)); +Value *OutPort::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + /*vector args; + + args.push_back(port.generate(func, block, allocblock)); + + Value *value = expr->generate(func, block, allocblock); + Value *nvalue = value; + if (value->getType()->isFloatTy()) + nvalue = new FPToSIInst(value, Type::getInt16Ty(global_context), "trunci", block); - Value *value = expr->generate(func, block, allocblock); - Value *nvalue = value; - if (value->getType()->isFloatTy()) - nvalue = new FPToSIInst(value, Type::getInt16Ty(global_context), "trunci", block); + args.push_back(nvalue); + //Value *int8v = new TruncInst(value, Type::getInt8Ty(global_context), "", block); + //args.push_back(int8v); - args.push_back(nvalue); - //Value *int8v = new TruncInst(value, Type::getInt8Ty(global_context), "", block); - //args.push_back(int8v); + ArrayRef argsRef(args); + return CallInst::Create(analogWrite, argsRef, "", block);*/ - ArrayRef argsRef(args); - return CallInst::Create(analogWrite, argsRef, "", block); - } + //TODO: Implement a new way of reading ports + return NULL; +} diff --git a/src/OutPort.h b/src/OutPort.h index aabea2b..79720c8 100644 --- a/src/OutPort.h +++ b/src/OutPort.h @@ -1,6 +1,8 @@ -#ifndef __OUTPORT_H__ -#define __OUTPORT_H__ + +#pragma once + #include "Node.h" +#include "Int8.h" #include "Int16.h" #include "Float.h" @@ -10,7 +12,5 @@ class OutPort: public Node { Node *expr; public: OutPort (const char *p, Node *e); - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; }; - -#endif diff --git a/src/ParamsCall.cpp b/src/ParamsCall.cpp index 22c4dc6..e21f9a1 100644 --- a/src/ParamsCall.cpp +++ b/src/ParamsCall.cpp @@ -1,4 +1,5 @@ -#include "Header.h" + +#include "ParamsCall.h" ParamsCall::ParamsCall() {}; diff --git a/src/ParamsCall.h b/src/ParamsCall.h index 575df1c..4d0efd1 100644 --- a/src/ParamsCall.h +++ b/src/ParamsCall.h @@ -12,6 +12,10 @@ class ParamsCall { unsigned getNumParams() const; Node *getParamElement (int position) const; + + std::vector const& getParameters() { + return parameters; + } }; #endif diff --git a/src/Pointer.cpp b/src/Pointer.cpp index 2bece89..ebe5241 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -1,15 +1,35 @@ #include "Pointer.h" -Value *Pointer::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) +Pointer::Pointer(const char *name, DataType type, Node *address): + Variable(name), address(address) { + dt = type; + addChild(address); +} + +Pointer::Pointer(const char *name, DataType type, Node *address, Structure *structure): + Pointer(name, type, address) { + if (structure->nextBit > buildTypes->bitWidth(type)) { + const char *emsg = "The sum of field sizes for %s (%d) is larger than its type size (%d)."; + yyerrorcpp(string_format(emsg, name, structure->nextBit, buildTypes->bitWidth(type)), this); + } +} + +Value *Pointer::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - auto sym = search_symbol(name); - if (sym != NULL) { + auto sym = findSymbol(name, true); + if (sym != NULL && sym != this) { yyerrorcpp("Register/pointer " + name + " already defined.", this); yyerrorcpp(name + " was first defined here.", sym); return NULL; } + // valid register types + /*if (!(dt == tint8 || dt == tint16 || dt == tint32 || dt == tint64)) { + yyerrorcpp("Register " + name + " must be of int8, int16, int32 or int64 type.", this); + return NULL; + }*/ + // generate code to produce the address Value *addr = address->generate(func, block, allocblock); if (addr == NULL) { @@ -17,26 +37,35 @@ Value *Pointer::generate(Function *func, BasicBlock *block, BasicBlock *allocblo return NULL; } - Type *targetPointerType = buildTypes->llvmType(currentTarget.pointerType); - Value *addrp = NULL; - if (Constant *addrc = dyn_cast(addr)) - addrp = ConstantExpr::getIntToPtr(addrc, targetPointerType); - else - addrp = new IntToPtrInst(addr, targetPointerType, name, allocblock); - - Type *ty = buildTypes->llvmType(type); - DataQualifier vol = isVolatile ? qvolatile : qnone; - - RobSymbol *rs = new RobSymbol(addrp, vol); - rs->structure = structure; - rs->setLocation(this); - rs->dt = type; - tabelasym[allocblock][name] = rs; - - return addrp; -} + Type *targetPointerType = buildTypes->llvmType(dt)->getPointerTo(); + /*if (Constant *addrc = dyn_cast(addr)) { + alloc = ConstantExpr::getIntToPtr(addrc, targetPointerType); + } else*/ + auto sp = RobDbgInfo.currScope(); + auto funit = RobDbgInfo.currFile(); -void Pointer::accept(Visitor &v) { - v.visit(*this); -} + if (allocblock == global_alloc) { + /*Constant *addr_num = dyn_cast(addr); + assert(addr_num && "FIXME: global pointer defined without constant address."); + Constant *addr = ConstantExpr::getIntToPtr(addr_num, targetPointerType); + GlobalVariable *gv = new GlobalVariable(*mainmodule, buildTypes->llvmType(dt), + false, GlobalValue::CommonLinkage, addr, name); + //gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Local); + //gv->setDSOLocal(true); + alloc = gv; + + if (debug_info) { + auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", + funit, getLineNo(), buildTypes->diType(dt), false); + gv->addDebugInfo(d); + }*/ + Constant *addr_num = dyn_cast(addr); + assert(addr_num && "FIXME: global pointer defined without constant address."); + alloc = ConstantExpr::getIntToPtr(addr_num, targetPointerType); + } + else { + alloc = new IntToPtrInst(addr, targetPointerType, name, allocblock); + } + return alloc; +} diff --git a/src/Pointer.h b/src/Pointer.h index 6b2abc2..6111bb4 100644 --- a/src/Pointer.h +++ b/src/Pointer.h @@ -1,28 +1,18 @@ -#ifndef __REGISTER_H__ -#define __REGISTER_H__ -#include "Header.h" +#pragma once -class Pointer: public Node { +#include "Field.h" + +class Pointer: public Variable { private: - BasicDataType type; Node *address; - string name; - bool isVolatile; Structure *structure; + public: - Pointer(const char *name, BasicDataType type, Node *address, bool isVolatile = false): - name(name), type(type), address(address), isVolatile(isVolatile) {} - Pointer(const char *name, BasicDataType type, Node *address, Structure *structure, - bool isVolatile = false): - name(name), type(type), address(address), structure(structure), isVolatile(isVolatile) { - if (structure->nextBit > buildTypes->bitWidth(type)) { - const char *emsg = "The sum of field sizes for %s (%d) is larger than its type size (%d)."; - yyerrorcpp(string_format(emsg, name, structure->nextBit, buildTypes->bitWidth(type)), this); - } - } - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor &v) override; -}; + Pointer(const char *name, DataType type, Node *address); + + Pointer(const char *name, DataType type, Node *address, Structure *structure); -#endif + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + +}; diff --git a/src/Print.cpp b/src/Print.cpp index a191945..8d74ae2 100644 --- a/src/Print.cpp +++ b/src/Print.cpp @@ -1,34 +1,37 @@ -#include "Header.h" - Value *Print::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - vector args; +#include "Print.h" - Value *lexp = expr->generate(func, block, allocblock); - char cty1 = -1; - if (lexp != NULL) { - Type *ty1 = lexp->getType(); - if (ty1->isIntegerTy()) - cty1 = 0; - else if (ty1->isFloatTy()) - cty1 = 1; - else if (ty1->isArrayTy()) - cty1 = 2; - } - /* TODO */ - if (cty1 == -1) { - yyerrorcpp("Type not supported by print.", this); - return NULL; - } +Value *Print::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + /*vector args; - Int8 prt(cty1); - args.push_back(prt.generate(func, block, allocblock)); - - AllocaInst *ptr_aux = new AllocaInst(lexp->getType(), 0, "prntaux", block); - /*StoreInst *st = */ new StoreInst(lexp, ptr_aux, false, block); - CastInst *cinst = new BitCastInst(ptr_aux, PointerType::get(IntegerType::get(global_context, 8), 0), "bitcast", block); - args.push_back(cinst); - - ArrayRef argsRef(args); - return CallInst::Create(print, argsRef, "", block); + Value *lexp = expr->generate(func, block, allocblock); + char cty1 = -1; + if (lexp != NULL) { + Type *ty1 = lexp->getType(); + if (ty1->isIntegerTy()) + cty1 = 0; + else if (ty1->isFloatTy()) + cty1 = 1; + else if (ty1->isArrayTy()) + cty1 = 2; + } + + if (cty1 == -1) { + yyerrorcpp("Type not supported by print.", this); + return NULL; } + Int8 prt(cty1); + args.push_back(prt.generate(func, block, allocblock)); + + AllocaInst *ptr_aux = new AllocaInst(lexp->getType(), 0, "prntaux", block); + new StoreInst(lexp, ptr_aux, false, block); + CastInst *cinst = new BitCastInst(ptr_aux, PointerType::get(IntegerType::get(global_context, 8), 0), "bitcast", block); + args.push_back(cinst); + + ArrayRef argsRef(args); + return CallInst::Create(print, argsRef, "", block);*/ + + //TODO: Implement a new way of print (serial interface with simavr!) + return NULL; +} diff --git a/src/Print.h b/src/Print.h index e9dece1..d1da129 100644 --- a/src/Print.h +++ b/src/Print.h @@ -7,7 +7,7 @@ class Print: public Node { Node *expr; public: Print(Node *e) : expr(e) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); }; #endif diff --git a/src/PrintAstVisitor.cpp b/src/PrintAstVisitor.cpp index aa17343..ce5bf1d 100644 --- a/src/PrintAstVisitor.cpp +++ b/src/PrintAstVisitor.cpp @@ -1,26 +1,26 @@ +#define SCANNER_OR_VISITOR #include "Header.h" #include #include "Language_gen_y.hpp" +#include "Program.h" +#include "PrintAstVisitor.h" template char* get_typename(T& object) { return abi::__cxa_demangle(typeid(object).name(), 0, 0, 0); } -PrintAstVisitorNode::PrintAstVisitorNode(std::ostream& _os) : os(_os) { -} - -PrintAstVisitorNode::~PrintAstVisitorNode() { -} - -bool PrintAstVisitorNode::before(Node const& n) { +bool PrintAstVisitor::before(Node& n) { this->os << "N" << std::hex << (long int)&n << "[label=\"" << get_typename(n) << "\"];\n"; return false; } -void PrintAstVisitorNode::visit_children(Node const& n) { +void PrintAstVisitor::after(Node& n) { +} + +void PrintAstVisitor::visit_children(Node& n) { for (Node *c : n.children()) { c->accept(*this); @@ -31,22 +31,22 @@ void PrintAstVisitorNode::visit_children(Node const& n) { } } -void PrintAstVisitorNode::visit(Node const& n) { +void PrintAstVisitor::visit(Node& n) { if (before(n)) { return; } visit_children(n); after(n); } -PrintAstVisitor::PrintAstVisitor(std::ostream& _os) : PrintAstVisitorNode(_os) { +PrintAstVisitor::PrintAstVisitor(std::ostream& _os) : os(_os) { } -void PrintAstVisitor::visit(Program const& p) { +void PrintAstVisitor::visit(Program& p) { if (before(p)) { return; } visit_children(p); after(p); } -bool PrintAstVisitor::before(Program const& p) { +bool PrintAstVisitor::before(Program& p) { this->os << "graph {\nN" << std::hex << (long int)&p << "[label=\"" << get_typename(p) @@ -54,29 +54,25 @@ bool PrintAstVisitor::before(Program const& p) { return false; } -void PrintAstVisitor::after(Program const& p) { +void PrintAstVisitor::after(Program& p) { this->os << "}\n"; } -void PrintAstVisitor::visit(Int8 const& n) { +void PrintAstVisitor::visit(Int8& n) { this->os << "N" << std::hex << (long int)&n << "[label=\"" << get_typename(n) << "(" << std::dec << (int)n.getNumber() << ")\"];\n"; } -void PrintAstVisitor::visit(Int16 const& n) { +void PrintAstVisitor::visit(Int16& n) { this->os << "N" << std::hex << (long int)&n << "[label=\"" << get_typename(n) << "(" << std::dec << n.getNumber() << ")\"];\n"; } -void PrintAstVisitor::visit(Int32 const& n) { +void PrintAstVisitor::visit(Int32& n) { this->os << "N" << std::hex << (long int)&n << "[label=\"" << get_typename(n) << "(" << std::dec << n.getNumber() << ")\"];\n"; } -void PrintAstVisitor::visit(While const& n) { - PrintAstVisitorNode::visit(n); -} - const string PrintAstVisitor::getOperatorName(int op) { switch (op) { case EQ_OP: return "="; @@ -96,38 +92,28 @@ const string PrintAstVisitor::getOperatorName(int op) { } } -void PrintAstVisitor::visit(CmpOp const& n) { +void PrintAstVisitor::visit(CmpOp& n) { this->os << "N" << std::hex << (long int)&n << "[label=\"" << get_typename(n) << "(" << std::dec << getOperatorName(n.getOperator()) << ")\"];\n"; visit_children(n); } -void PrintAstVisitor::visit(BinaryOp const& n) { +void PrintAstVisitor::visit(BinaryOp& n) { this->os << "N" << std::hex << (long int)&n << "[label=\"" << get_typename(n) << "(" << std::dec << getOperatorName(n.getOperator()) << ")\"];\n"; visit_children(n); } -void PrintAstVisitor::visit(Load const& n) { +void PrintAstVisitor::visit(Load& n) { this->os << "N" << std::hex << (long int)&n - << "[label=\"" << get_typename(n) << "(" << n.getIdent() << ")\"];\n"; + << "[label=\"" << get_typename(n) << "(" << n.getName() << ")\"];\n"; visit_children(n); } -void PrintAstVisitor::visit(Scalar const& n) { +void PrintAstVisitor::visit(Scalar& n) { this->os << "N" << std::hex << (long int)&n - << "[label=\"" << get_typename(n) << "(" << n.getIdent() << ")\"];\n"; + << "[label=\"" << get_typename(n) << "(" << n.getName() << ")\"];\n"; visit_children(n); } - -void PrintAstVisitor::visit(Delay const& n) { - PrintAstVisitorNode::visit(n); -} - -void PrintAstVisitor::visit(If const& n) { - PrintAstVisitorNode::visit(n); -} - - diff --git a/src/PrintAstVisitor.h b/src/PrintAstVisitor.h index 393a4dc..4eb4e81 100644 --- a/src/PrintAstVisitor.h +++ b/src/PrintAstVisitor.h @@ -1,42 +1,32 @@ -#ifndef __PRINT_AST_VISITOR_H__ -#define __PRINT_AST_VISITOR_H__ + +#pragma once #include "Node.h" +#include "RecursiveVisitor.h" -class PrintAstVisitorNode: public RecursiveVisitor { +class PrintAstVisitor: public RecursiveVisitor { protected: std::ostream& os; -public: - PrintAstVisitorNode(std::ostream& _os); - virtual ~PrintAstVisitorNode(); - - virtual void visit_children(Node const& n); - virtual void visit(Node const& n) override; - virtual bool before(Node const& n) override; -}; - -class PrintAstVisitor: public PrintAstVisitorNode { public: PrintAstVisitor(std::ostream& _os); - virtual void visit(Program const& p) override; - virtual void visit(Int8 const& n) override; - virtual void visit(Int16 const& n) override; - virtual void visit(Int32 const& n) override; - virtual void visit(While const& n) override; + virtual void visit(Node& p) override; + void visit_children(Node& n); + bool before(Node& n) override; + void after(Node& n) override; + + virtual void visit(Program& p) override; + virtual void visit(Int8& n) override; + virtual void visit(Int16& n) override; + virtual void visit(Int32& n) override; const string getOperatorName(int op); - virtual void visit(CmpOp const& n) override; - virtual void visit(BinaryOp const& n) override; + virtual void visit(CmpOp& n) override; + virtual void visit(BinaryOp& n) override; - virtual void visit(Load const& n) override; - virtual void visit(Scalar const& n) override; - virtual void visit(Delay const& n) override; - virtual void visit(If const& n) override; + virtual void visit(Load& n) override; + virtual void visit(Scalar& n) override; - virtual bool before(Program const& p) override; - virtual void after(Program const& p) override; + virtual bool before(Program& p) override; + virtual void after(Program& p) override; }; - -#endif - diff --git a/src/Program.cpp b/src/Program.cpp index 9755a0f..a2c7d4e 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -1,4 +1,26 @@ -#include "Header.h" +#include "Program.h" +#include "SymbolizeTree.h" +#include "BackLLVM.h" + +Program::Program() { + mainmodule = new Module(this->file, global_context); + Builder = make_unique>(global_context); + + if (debug_info) { + mainmodule->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); + mainmodule->addModuleFlag(Module::Warning, "Dwarf Version", 2); + DBuilder = make_unique(*mainmodule); + RobDbgInfo.cunit = DBuilder->createCompileUnit(dwarf::DW_LANG_C, + DBuilder->createFile(this->file, std::filesystem::current_path().string()), + "Robcmp", false, "", 0); + + // global scope + RobDbgInfo.push_scope(RobDbgInfo.cunit->getFile(), RobDbgInfo.cunit); + } + + buildTypes = make_unique(currentTarget.pointerType); + global_alloc = BasicBlock::Create(global_context, "global"); +} void Program::declara_auxiliary_c_funcs() { std::vector arg_types; @@ -85,31 +107,18 @@ void Program::declara_auxiliary_c_funcs() { i16div->setCallingConv(CallingConv::C);*/ } -Value *Program::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *Program::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return NULL; } void Program::generate() { - mainmodule = new Module(build_filename, global_context); - Builder = make_unique>(global_context); - - if (debug_info) { - mainmodule->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); - mainmodule->addModuleFlag(Module::Warning, "Dwarf Version", 2); - DBuilder = make_unique(*mainmodule); - RobDbgInfo.cunit = DBuilder->createCompileUnit(dwarf::DW_LANG_C, - DBuilder->createFile(build_filename, std::filesystem::current_path().string()), - "Robcmp", false, "", 0); - - // global scope - RobDbgInfo.push_scope(RobDbgInfo.cunit->getFile(), RobDbgInfo.cunit); - } - - global_alloc = BasicBlock::Create(global_context, "global"); + // instrumentation passes + SymbolizeTree st; + st.visit(*this); // generate the program! - for(auto n: node_children) + for(auto n: getChildren()) n->generate(NULL, NULL, global_alloc); if (debug_info) diff --git a/src/Program.h b/src/Program.h index 12589ea..2a056cc 100644 --- a/src/Program.h +++ b/src/Program.h @@ -5,12 +5,12 @@ class Program : public Node { public: - - Program(Stmts &&stmts): Node(std::move(stmts.node_children)) {} + Program(); void declara_auxiliary_c_funcs(); - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); - void generate(); - + Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); + void generate(); }; + +extern Program* program; diff --git a/src/RecursiveVisitor.cpp b/src/RecursiveVisitor.cpp index 398b6d5..a09c9c5 100644 --- a/src/RecursiveVisitor.cpp +++ b/src/RecursiveVisitor.cpp @@ -1,7 +1,7 @@ -#include "Header.h" +#include "RecursiveVisitor.h" -void RecursiveVisitor::visit(Node const& n) { +void RecursiveVisitor::visit(Node& n) { if (before(n)) { return; } for (auto &c : n.children()) { diff --git a/src/RecursiveVisitor.h b/src/RecursiveVisitor.h index 3d28048..82ccbe8 100644 --- a/src/RecursiveVisitor.h +++ b/src/RecursiveVisitor.h @@ -1,13 +1,10 @@ -#ifndef __RECURSIVE_VISITOR_H__ -#define __RECURSIVE_VISITOR_H__ + +#pragma once + #include "Node.h" +#include "Visitor.h" class RecursiveVisitor: public Visitor { public: - void visit(Node const& n) override; + void visit(Node& n) override; }; - -#endif - - - diff --git a/src/Return.cpp b/src/Return.cpp index 8ebe556..9078536 100644 --- a/src/Return.cpp +++ b/src/Return.cpp @@ -1,10 +1,18 @@ -#include "Header.h" - Value *Return::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(block); - Value *ret = node->generate(func, block, allocblock); - Type *retty = func->getReturnType(); - ret = Coercion::Convert(ret, retty, block, this); - return Builder->CreateRet(ret); +#include "Return.h" +#include "Coercion.h" +#include "FunctionImpl.h" + +Value *Return::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + Value *ret = NULL; + if (node) { + ret = node->generate(func, block, allocblock); + if (ret) { + Type *retty = func->getLLVMFunction()->getReturnType(); + ret = Coercion::Convert(ret, retty, block, this); + } } + return Builder->CreateRet(ret); +} diff --git a/src/Return.h b/src/Return.h index 4bfed58..3e704ba 100644 --- a/src/Return.h +++ b/src/Return.h @@ -1,15 +1,20 @@ -#ifndef __RETURN_H__ -#define __RETURN_H__ + +#pragma once + #include "Node.h" class Return: public Node { private: Node *node; public: + Return() { + node = NULL; + } + Return(Node *n) { + addChild(n); this->node = n; } - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; }; - -#endif diff --git a/src/RobSymbol.h b/src/RobSymbol.h deleted file mode 100644 index 99cfe1a..0000000 --- a/src/RobSymbol.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __ROBSYMBOL_H__ -#define __ROBSYMBOL_H__ - -class RobSymbol: public SourceLocation { -public: - Value* value; - DataQualifier qualifier; - unsigned int matrixLines; - unsigned int matrixCols; - Structure *structure; - BasicDataType dt; - BasicDataType pointee_dt; - FunctionParams *params; - bool isDeclaration; - - RobSymbol(Value *v, DataQualifier qualifier = qnone): - value(v), qualifier(qualifier) { - matrixLines = matrixCols = 0; - structure = nullptr; - dt = tvoid; - pointee_dt = tvoid; - params = nullptr; - isDeclaration = false; - } -}; - -#endif diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 51104bb..81f0b2f 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -1,50 +1,69 @@ -#include "Header.h" -Scalar::Scalar(const char *n, Node *e, DataQualifier qualifier) : - name(n), expr(e), qualifier(qualifier), complexIdent(nullptr) { - node_children.reserve(1); - node_children.push_back(e); +#include "Scalar.h" +#include "Coercion.h" +#include "FunctionImpl.h" +#include "BackLLVM.h" + +Scalar::Scalar(Identifier ident, Node *e) : + Variable(ident.getFullName()), expr(e) { + addChild(e); } -Scalar::Scalar(ComplexIdentifier *ci, Node *e, DataQualifier qualifier) : - complexIdent(ci), expr(e), qualifier(qualifier) { - node_children.reserve(1); - node_children.push_back(e); +Scalar::Scalar(const char* ident, Node *e): Variable(ident), expr(e) { + addChild(e); } -Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { RobDbgInfo.emitLocation(this); - string id = complexIdent ? complexIdent->names[0] : name; - auto symbol = search_symbol(id, allocblock, block); - Field field; + Node *symbol = ident.getSymbol(getScope()); + if (!symbol) + return NULL; - // semantic validation of complexIdent - if (complexIdent) { - string idfield = complexIdent->names[1]; - auto fieldit = symbol->structure->fields.find(idfield); + if (ident.isComplex()) { + Identifier istem = ident.getStem(); + Node *stem = istem.getSymbol(getScope()); + alloc = symbol->getLLVMValue(stem); + + if (stem->hasQualifier(qvolatile)) + symbol->setQualifier(qvolatile); - if (symbol == NULL) { - yyerrorcpp("Symbol " + id + " must be defined first.", this); - return NULL; - } else if (fieldit == symbol->structure->fields.end()) { - yyerrorcpp("Field " + idfield + " not declared in " + id, this); - return NULL; - } else { - field = fieldit->second; - } + // TODO: When accessing a.x.func(), need to load a and gep x + //Load loadstem(ident.getStem()); + //loadstem.setParent(this->parent); + //stem = loadstem.generate(func, block, allocblock); + } else { + alloc = symbol->getLLVMValue(func); } - // variable doesn't exists - if (symbol == NULL) { - Value *ret, *leftv; - Value *exprv = expr->generate(func, block, allocblock); - BasicDataType dt = expr->getResultType(block, allocblock); + // tell the allocated left value to an eventual + // constructor initializing a user type field + if (getGEPIndex() != -1) + expr->setLeftValue(alloc, name); + + Value *exprv = expr->generate(func, block, allocblock); + if (!exprv) + return NULL; + DataType exprv_dt = expr->getDataType(); + + // is the result of a constructor()? + Value *allocall = dyn_cast(exprv); + if (!allocall) + allocall = dyn_cast(exprv); + + if (allocall) { + setDataType(exprv_dt); + alloc = allocall; + if (debug_info) + RobDbgInfo.declareVar(this, alloc, allocblock); + } + + // variable not allocated + if (alloc == NULL) { + Value *ret; + setDataType(exprv_dt); - if (!exprv) - return NULL; - auto sp = RobDbgInfo.currScope(); auto funit = RobDbgInfo.currFile(); @@ -53,12 +72,13 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc if (exprvc == NULL) return NULL; //TODO: semantic error, global const value can't be generated - if (qualifier == qconst) - ret = leftv = exprvc; + if (symbol->hasQualifier(qconst)) + ret = alloc = exprvc; else { GlobalVariable *gv = new GlobalVariable(*mainmodule, buildTypes->llvmType(dt), false, GlobalValue::CommonLinkage, exprvc, name); - ret = leftv = gv; + //gv->setDSOLocal(true); + ret = alloc = gv; if (debug_info) { auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", @@ -68,48 +88,34 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc } } else { Builder->SetInsertPoint(allocblock); - AllocaInst *newvar = Builder->CreateAlloca(exprv->getType(), 0, name); - newvar->setAlignment(Align(1)); - leftv = newvar; + AllocaInst *temp = Builder->CreateAlloca(exprv->getType(), globalAddrSpace, 0, name); + temp->setAlignment(Align(1)); + alloc = temp; Builder->SetInsertPoint(block); - ret = Builder->CreateStore(exprv, leftv, qualifier == qvolatile); + ret = Builder->CreateStore(exprv, alloc, symbol->hasQualifier(qvolatile)); - if (debug_info) { - llvm::DIType *dty = buildTypes->diType(dt); - if (qualifier == qvolatile) { - dty = DBuilder->createQualifiedType(dwarf::DW_TAG_volatile_type, dty); - } - DILocalVariable *d = DBuilder->createAutoVariable( - sp, name, funit, getLineNo(), dty, true); - DBuilder->insertDeclare(leftv, d, DBuilder->createExpression(), - DILocation::get(sp->getContext(), getLineNo(), getColNo(), sp), allocblock); - } + if (debug_info) + RobDbgInfo.declareVar(this, alloc, allocblock); } - RobSymbol *rs = new RobSymbol(leftv, qualifier); - rs->dt = dt; - tabelasym[allocblock][name] = rs; return ret; - } else { - // variable already exists - if (symbol->qualifier == qconst) { - yyerrorcpp("Constant '" + name + "' can not be changed.", this); + } else { // variable already allocated + + if (symbol->hasQualifier(qconst)) { + yyerrorcpp("Constant '" + symbol->getName() + "' can not be changed.", this); return NULL; } - Type *leftvty = buildTypes->llvmType(symbol->dt); - qualifier = symbol->qualifier; - Value *exprv = expr->generate(func, block, allocblock); - Value *nvalue; - + Type *currty = buildTypes->llvmType(symbol->getDataType()); Builder->SetInsertPoint(block); + /* if (complexIdent) { - /* this code does: - * symbol->value &= ~(0x11... << field.startBit) - * symbol->value |= (exprv << field.startBit) - */ + // this code does: + // symbol->value &= ~(0x11... << field.startBit) + // symbol->value |= (exprv << field.startBit) + // // Coerce the left side to the field size exprv = Coercion::Convert(exprv, buildTypes->llvmType(field.fieldDataType), block, expr); @@ -136,14 +142,43 @@ Value *Scalar::generate(Function *func, BasicBlock *block, BasicBlock *allocbloc Builder->SetInsertPoint(block); //caution, after generate! Value *vaftermask = Builder->CreateAnd(leftv, mask, "mask"); nvalue = Builder->CreateOr(vaftermask, exprv, "setbits"); - } else { - nvalue = Coercion::Convert(exprv, leftvty, block, expr); + } else {*/ + + // TODO: remove this check after converting Coercion to use DataType + // instead of llvm::Type + Value *nvalue; + if (allocall) + return allocall; + else { + nvalue = Coercion::Convert(exprv, currty, block, expr); + return Builder->CreateStore(nvalue, alloc, symbol->hasQualifier(qvolatile)); } + } +} - return Builder->CreateStore(nvalue, symbol->value, qualifier == qvolatile); +Value *Scalar::getLLVMValue(Node *stem) { + int gepidx = getGEPIndex(); + if (gepidx != -1) { + Value *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); + Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), gepidx); + Value* indexList[2] = {zero, idx}; + + if (FunctionImpl *func = dynamic_cast(stem)) { + // generating a function of a type: get the gep on the #this parameter + Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); + alloc = Builder->CreateStructGEP(thisTy, func->getThisArg(), gepidx, "gepthis"); + } else { + // accessing a var of a user type: get the gep in the scope (user type) of the scalar + Type *udt = buildTypes->llvmType(stem->getDataType()); + alloc = Builder->CreateStructGEP(udt, stem->getLLVMValue(NULL), gepidx, "gepu"); // FIXME + } } + return alloc; } -void Scalar::accept(Visitor& v) { - v.visit(*this); +DataType Scalar::getDataType() { + if (dt == BuildTypes::undefinedType) + return dt = expr->getDataType(); + else + return dt; } diff --git a/src/Scalar.h b/src/Scalar.h index 674e9ec..83cf069 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -1,23 +1,35 @@ -#ifndef __SCALAR_H__ -#define __SCALAR_H__ -#include "Node.h" -#include "Float.h" -class Scalar: public Node { +#pragma once + +#include "Field.h" +#include "Variable.h" + +class Scalar: public Variable { private: - string name; Node *expr; - DataQualifier qualifier; - ComplexIdentifier *complexIdent; + int gepIndex = -1; + public: - Scalar(const char *n, Node *e, DataQualifier qualifier = qnone); - Scalar(ComplexIdentifier *ci, Node *e, DataQualifier qualifier = qnone); + Scalar(const char* ident, Node *e); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; + Scalar(Identifier ident, Node *e); - string getIdent() const { return name; }; + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; -}; + virtual Value* getLLVMValue(Node *stem) override; + + virtual void setGEPIndex(int idx) { + gepIndex = idx; + } -#endif + int getGEPIndex() const { + return gepIndex; + } + + virtual bool isConstExpr() override { + return hasQualifier(qconst) && expr->isConstExpr(); + } + + virtual DataType getDataType() override; + +}; diff --git a/src/Scanner.cpp b/src/Scanner.cpp index 4c87931..05f1ab6 100644 --- a/src/Scanner.cpp +++ b/src/Scanner.cpp @@ -1,10 +1,19 @@ -#include "Header.h" +#include "SourceLocation.h" +#include "Scanner.h" +#include "Program.h" +#include "FlexDependencies.h" #include "Language_gen_y.hpp" +Program *program; + int errorsfound = 0; -char *build_filename; + char *build_outputfilename; +vector includeDirs; +vector buildStack; +vector buildStackScanner; +int buildStackTop; int USElex(YYSTYPE *yylval_param, location_t *yylloc_param, yyscan_t yyscanner) { return MAINlex(yylval_param, yylloc_param, yyscanner); @@ -13,16 +22,16 @@ int USElex(YYSTYPE *yylval_param, location_t *yylloc_param, yyscan_t yyscanner) int MAINlex_init(yyscan_t* scanner); void MAINset_in(FILE *_in_str, yyscan_t yyscanner); int MAINlex_destroy(yyscan_t yyscanner); +int USEparse(yyscan_t scanner); -void yyerror(location_t *loc, yyscan_t scanner, const char *s) -{ +void yyerror(location_t *loc, yyscan_t scanner, const char *s) { fprintf(stderr, "%s:%d:%d: %s\n", - build_filename, loc->first_line, loc->first_column, s); + build_filename(), loc->first_line, loc->first_column, s); errorsfound++; } void USEerror(location_t *loc, yyscan_t scanner, const char *s) { - yyerror(loc, scanner, s); + yyerror(loc, scanner, s); } void MAINerror(location_t *loc, yyscan_t scanner, const char *s) { @@ -32,36 +41,119 @@ void MAINerror(location_t *loc, yyscan_t scanner, const char *s) { void yyerrorcpp(const string& s, SourceLocation *n) { string e = COLOR_RED "semantic error: " COLOR_RESET + s; fprintf(stderr, "%s:%d:%d: %s\n", - build_filename, n->getLineNo(), n->getColNo(), s.c_str()); + n->getFile(), n->getLineNo(), n->getColNo(), s.c_str()); errorsfound++; } void yywarncpp(const string& s, SourceLocation *n) { string e = COLOR_BLUE "semantic warning: " COLOR_RESET + s; fprintf(stderr, "%s:%d:%d %s\n", - build_filename, n->getLineNo(), n->getColNo(), e.c_str()); + n->getFile(), n->getLineNo(), n->getColNo(), e.c_str()); } -bool parseFile(const char *source) { +bool parseFile(const string& source) { + + filesystem::path file_path(source); + buildStack.push_back(file_path); + buildStackTop = 0; + + // search for use files in the path of build_filename; + // next in the working dir; next in the -I dirs (right from left) + includeDirs.push_back(file_path.parent_path()); + includeDirs.push_back("./"); - FILE *f = fopen(source, "r"); + FILE *f = fopen(file_path.c_str(), "r"); if (f == NULL) { - fprintf(stderr, "Could not open file %s.\n", source); + fprintf(stderr, file_not_found.c_str(), file_path.c_str()); return false; } yyscan_t scanner; MAINlex_init(&scanner); + buildStackScanner.push_back(scanner); MAINset_in(f, scanner); + + program = new Program(); + MAINparse(scanner); - MAINlex_destroy(scanner); - if (f) - fclose(f); + MAINlex_destroy(scanner); + fclose(f); return true; } -bool parseUseFile(const char *use) { - return false; +FILE *findFile(string file_name, filesystem::path& file_path) { + FILE *f = NULL; + for(auto dirit = rbegin(includeDirs); dirit != rend(includeDirs); ++dirit) { + filesystem::path test_path(*dirit); + test_path /= file_name; + FILE *f = fopen(test_path.c_str(), "r"); + if (f) { + file_path = test_path; + return f; + } + } + return f; +} + +bool parseUseFile(const string& use, location_t loc) { + + // search for and open {use}.rob file + string file_name = use + ".rob"; + filesystem::path file_path; + FILE *f = findFile(file_name, file_path); + + if (f == NULL) { + fprintf(stderr, file_not_found.c_str(), file_name.c_str()); + return false; + } + + auto it = find(buildStack.begin(), buildStack.end(), file_path); + if (it != buildStack.end()) { + // circular dependency + SourceLocation sl(loc); + yywarncpp(string_format("circular dependency for %s", file_path.c_str()), &sl); + while (it != buildStack.end()) { + fprintf(stderr, "\t%s ->\n", it->c_str()); + it++; + } + fprintf(stderr, "\t%s\n", file_path.c_str()); + fclose(f); + return true; + } + + buildStack.push_back(file_path); + buildStackTop++; + + yyscan_t scanner; + MAINlex_init(&scanner); + buildStackScanner.push_back(scanner); + + MAINset_in(f, scanner); + extern int USEdebug; + //USEdebug = 1; + USEparse(scanner); + MAINlex_destroy(scanner); + fclose(f); + + buildStackTop--; + buildStackScanner.pop_back(); + + return true; +} + +int MAINget_lineno(yyscan_t yyscanner); +int MAINget_column(yyscan_t yyscanner); + +int build_filelineno() { + return MAINget_lineno(buildStackScanner[buildStackTop]); +} + +int build_filecolno() { + return MAINget_column(buildStackScanner[buildStackTop]); } + +const char* build_filename() { + return buildStack[buildStackTop].c_str(); +} \ No newline at end of file diff --git a/src/Scanner.h b/src/Scanner.h index 28c8ba8..dc149ca 100644 --- a/src/Scanner.h +++ b/src/Scanner.h @@ -2,21 +2,21 @@ #pragma once #include +#include +#include + #include "SourceLocation.h" using namespace std; -#define COLOR_RED "\x1b[31m" -#define COLOR_GREEN "\x1b[32m" -#define COLOR_YELLOW "\x1b[33m" -#define COLOR_BLUE "\x1b[34m" -#define COLOR_MAGENTA "\x1b[35m" -#define COLOR_CYAN "\x1b[36m" -#define COLOR_RESET "\x1b[0m" +const string file_not_found = "No such file or directory '%s'\n"; typedef void* yyscan_t; extern int errorsfound; -extern char *build_filename; +extern vector includeDirs; +extern vector buildStack; +extern int buildStackTop; +extern vector buildStackScanner; void yyerror(location_t *loc, yyscan_t scanner, const char *s); void USEerror(location_t *loc, yyscan_t scanner, const char *s); @@ -24,5 +24,9 @@ void MAINerror(location_t *loc, yyscan_t scanner, const char *s); void yyerrorcpp(const string& s, SourceLocation *n); void yywarncpp(const string& s, SourceLocation *n); -bool parseFile(const char *source); -bool parseUseFile(const char *use); +bool parseFile(const string &source); +bool parseUseFile(const string& use, location_t loc); + +const char* build_filename(); +int build_filecolno(); +int build_filelineno(); diff --git a/src/Semantic.cpp b/src/Semantic.cpp index f5254cc..8ff20dd 100644 --- a/src/Semantic.cpp +++ b/src/Semantic.cpp @@ -1,4 +1,4 @@ -#include "Header.h" +#include "Semantic.h" Value *Semantic::Verification() { return NULL; diff --git a/src/Semantic.h b/src/Semantic.h index 6b51deb..38f6ee0 100644 --- a/src/Semantic.h +++ b/src/Semantic.h @@ -1,9 +1,10 @@ -#ifndef __SEMANTIC_H__ -#define __SEMANTIC_H__ + +#pragma once + +#include "HeaderExternals.h" class Semantic { public: static Value *Verification(); }; -#endif diff --git a/src/SourceLocation.h b/src/SourceLocation.h index 29818e5..8fef4fa 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -8,23 +8,30 @@ typedef struct { int last_column; } location_t; +extern const char *build_filename(); +extern int build_filecolno(); +extern int build_filelineno(); + class SourceLocation { protected: location_t sloc; + const char* file; public: SourceLocation() { - //TODO: sloc = yylloc; + file = build_filename(); + sloc.first_column = build_filecolno(); + sloc.first_line = build_filelineno(); } - SourceLocation(location_t l) { + SourceLocation(location_t l): SourceLocation() { sloc = l; } - virtual int getLineNo() { + virtual int getLineNo() const { return sloc.first_line; } - virtual int getColNo() { + virtual int getColNo() const { return sloc.first_column; } @@ -39,4 +46,8 @@ class SourceLocation { virtual location_t *getLoct() { return &sloc; } + + virtual const char* getFile() const { + return file; + } }; diff --git a/src/Stmts.cpp b/src/Stmts.cpp deleted file mode 100644 index 4d61a33..0000000 --- a/src/Stmts.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "Header.h" - -void Stmts::append(Node *s) { - node_children.push_back(s); - if (s->hasName()) - update_names = true; -} - -void Stmts::prepend(Node *s) { - // put after function declarations - auto last_func = node_children.begin(); - auto iterator = node_children.begin(); - while (iterator != node_children.end()) { - if ((*iterator)->isFunctionDecl()) - last_func = iterator; - iterator = next(iterator); - } - last_func = next(last_func); - node_children.insert(last_func, s); -} - -Value *Stmts::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - for(Node *n: node_children) { - Value *b = n->generate(func, block, allocblock); - if (b && b->getValueID() == Value::BasicBlockVal) - block = (BasicBlock*)b; - } - return block; -} diff --git a/src/Stmts.h b/src/Stmts.h deleted file mode 100644 index 4643fcf..0000000 --- a/src/Stmts.h +++ /dev/null @@ -1,19 +0,0 @@ - -#pragma once - -#include "Node.h" - -class Stmts: public Node { -public: - Stmts() {}; - - Stmts(Node *s) { - node_children.push_back(s); - } - - void append(Node *s); - - void prepend(Node *s); - - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; -}; diff --git a/src/String.cpp b/src/String.cpp deleted file mode 100644 index 8f5250c..0000000 --- a/src/String.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "Header.h" - - Value *String::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantDataArray::getString(global_context, str, true);; - } diff --git a/src/String.h b/src/String.h deleted file mode 100644 index 8513e41..0000000 --- a/src/String.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __STRING_H__ -#define __STRING_H__ -#include "Node.h" - -class String: public Node { -private: - string str; -public: - String(const char *s): str(s) {} - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); -}; - -#endif diff --git a/src/StringConst.cpp b/src/StringConst.cpp new file mode 100644 index 0000000..499f0ea --- /dev/null +++ b/src/StringConst.cpp @@ -0,0 +1,6 @@ + +#include "StringConst.h" + +Value *StringConst::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantDataArray::getString(global_context, str, true);; +} diff --git a/src/StringConst.h b/src/StringConst.h new file mode 100644 index 0000000..4f8a73e --- /dev/null +++ b/src/StringConst.h @@ -0,0 +1,12 @@ + +#pragma once + +#include "Node.h" + +class StringConst: public Node { +private: + string str; +public: + StringConst(const char *s): str(s) {} + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); +}; diff --git a/src/SymbolizeTree.h b/src/SymbolizeTree.h new file mode 100644 index 0000000..7b0ac54 --- /dev/null +++ b/src/SymbolizeTree.h @@ -0,0 +1,60 @@ + +#pragma once + +#include "Node.h" +#include "Visitor.h" +#include "UserType.h" +#include "Matrix.h" +#include "Array.h" +#include "FunctionImpl.h" +#include "Loop.h" +#include "While.h" +#include "FunctionCall.h" + +class SymbolizeTree: public Visitor { +public: + SymbolizeTree() {} + + virtual void visit(Node& n) override { + for(auto& c : n.children()) { + c->setScope(&n); + if (c->hasName()) { + //fprintf(stderr, "%s\n", c->getName().c_str()); + n.addSymbol(dynamic_cast(c)); + } + } + for(auto& c : n.children()) { + c->accept(*this); + } + } + + virtual void visit(Array& n) override { + for(auto& c : n.children()) { + if (c->hasName()) { + n.addSymbol(dynamic_cast(c)); + } + } + for(ArrayElement *e : n.getElements()) + e->value->setScope(&n); + } + + virtual void visit(Matrix& n) override { + for(auto& c : n.children()) { + if (c->hasName()) { + n.addSymbol(dynamic_cast(c)); + } + } + for(MatrixElement *i: n.getElements()) { + for(ArrayElement *e: i->array->getElements()) { + e->value->setScope(&n); + } + } + } + + virtual void visit(FunctionCall& n) override { + for(Node *p: n.getParameters()) { + p->setScope(&n); + p->accept(*this); + } + } +}; diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index 6b2eedf..4c2ae3f 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -1,13 +1,21 @@ -#include "Header.h" -Value *UpdateArray::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - auto rsym = search_symbol(ident, allocblock, block); - /* TODO */ +#include "UpdateArray.h" +#include "Coercion.h" +#include "Array.h" +#include "FunctionImpl.h" + +UpdateArray::UpdateArray(const char *i, Node *pos, Node *expr): ident(i), position(pos), expr(expr) { + addChild(pos); + addChild(expr); +} + +Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + Node *rsym = ident.getSymbol(getScope()); if (rsym == NULL) { - yyerrorcpp("Variable " + ident + " not defined.", this); return NULL; } - auto sym = rsym->value; + LinearDataStructure *arr = dynamic_cast(rsym); + Value *sym = rsym->getLLVMValue(func); // sym type can be GlobalVariable or AllocInst Type *ty = NULL; @@ -21,14 +29,14 @@ Value *UpdateArray::generate(Function *func, BasicBlock *block, BasicBlock *allo arrayTy = (ArrayType*)ty; } else { - yyerrorcpp("Symbol " + ident + " is not an array.", this); + yyerrorcpp("Symbol " + ident.getFullName() + " is not an array.", this); return NULL; } - Node *indn = getUpdateIndex(rsym, block, allocblock); + Node *indn = getElementIndex(arr); Value *indice = indn->generate(func, block, allocblock); - if (!indice->getType()->isIntegerTy()){ - yyerrorcpp("Index to update " + ident + " elements should be of type integer.", this); + if (!indice || !indice->getType()->isIntegerTy()){ + yyerrorcpp("Index to update " + ident.getFullName() + " elements must be of type integer.", this); return NULL; } diff --git a/src/UpdateArray.h b/src/UpdateArray.h index fd6a34f..f864eba 100644 --- a/src/UpdateArray.h +++ b/src/UpdateArray.h @@ -2,18 +2,20 @@ #pragma once #include "Node.h" +#include "Array.h" +#include "Field.h" class UpdateArray: public Node { protected: - string ident; + Identifier ident; Node *position; Node *expr; public: - UpdateArray(const char *i, Node *pos, Node *expr): ident(i), position(pos), expr(expr) {} + UpdateArray(const char *i, Node *pos, Node *expr); - virtual Node *getUpdateIndex(RobSymbol *rsym, BasicBlock *block, BasicBlock *allocblock) { - return position; - } + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock); + virtual Node *getElementIndex(LinearDataStructure *arr) { + return arr->getElementIndex(position, NULL); + } }; diff --git a/src/UpdateMatrix.h b/src/UpdateMatrix.h index afea498..3ece2a0 100644 --- a/src/UpdateMatrix.h +++ b/src/UpdateMatrix.h @@ -7,13 +7,11 @@ class UpdateMatrix: public UpdateArray { private: Node *position2; public: - UpdateMatrix(const char *i, Node *pos1, Node *pos2, Node *expr) : UpdateArray(i, pos1, expr) { - this->position2 = pos2; - } + UpdateMatrix(const char *i, Node *p1, Node *p2, Node *expr) : UpdateArray(i, p1, expr) { + this->position2 = p2; + } - virtual Node *getUpdateIndex(RobSymbol *rsym, BasicBlock *block, BasicBlock *allocblock) override { - //Generate index of element - Node *mcols = getNodeForIntConst(rsym->matrixCols); - return new BinaryOp(new BinaryOp(position, '*', mcols), '+', position2); + virtual Node *getElementIndex(LinearDataStructure *arr) override { + return arr->getElementIndex(position, position2); } }; diff --git a/src/UserType.cpp b/src/UserType.cpp index 805f7cc..34eb2d8 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -1,7 +1,41 @@ -#include "Header.h" +#include "UserType.h" +#include "Interface.h" +#include "FunctionImpl.h" +#include "FunctionParams.h" +#include "Program.h" +#include "Visitor.h" -Value *UserType::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { +void UserType::createDataType() { + std::vector elements; + + int idx = 0; + for(auto nn : this->getSymbols()) { + Scalar *s = dynamic_cast(nn.second); + if (s) { + DataType sdt = s->getDataType(); + elements.push_back(buildTypes->llvmType(sdt)); + s->setGEPIndex(idx++); + } + } + + StructType *uttype = StructType::create(global_context, ArrayRef(elements), name); + dt = buildTypes->addDataType(this, uttype); + if (dt == BuildTypes::undefinedType) { + yyerrorcpp("Type " + name + " alread defined.", this); + yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); + return; + } + + /*printf("Type %s defined with:\n", name.c_str()); + for(const auto n : symbols) { + printf("\t%s\n", n.first.c_str()); + }*/ +} + +Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + createDataType(); // semantic analysis for(auto n : implements) { @@ -15,8 +49,35 @@ Value *UserType::generate(Function *func, BasicBlock *block, BasicBlock *allocbl return NULL; } - for(const auto n : symbols) { - printf("Will generate %s_%s function!\n", name.c_str(), n.first.c_str()); + // get vars + vector fields; + for(auto & [key, stmt] : getSymbols()) { + if (Scalar *c = dynamic_cast(stmt)) { + fields.push_back(c); + } } - return NULL; + + // generate functions + for(auto & [key, stmt] : getSymbols()) { + if (FunctionImpl *f = dynamic_cast(stmt)) { + f->setUserTypeName(name); + f->addThisArgument(dt); + for(auto &field : fields) + f->addSymbol(dynamic_cast(field)); + f->generate(func, block, allocblock); + } + } + + FunctionParams *fp = new FunctionParams(); + FunctionImpl *finit = new FunctionImpl((DataType)tvoid, "init", fp, + std::move(fields), *this->getLoct(), true); + finit->addThisArgument(dt); + finit->setUserTypeName(name); + addChild(finit); + addSymbol(finit); + return finit->generate(func, block, allocblock); +} + +void UserType::accept(Visitor& v) { + v.visit(*this); } diff --git a/src/UserType.h b/src/UserType.h index 8c6b8b9..a2caad1 100644 --- a/src/UserType.h +++ b/src/UserType.h @@ -1,19 +1,26 @@ #pragma once +#include "HeaderExternals.h" #include "Node.h" +#include "Scalar.h" + +class Visitor; class UserType: public NamedNode { private: vector implements; + void createDataType(); public: - UserType(const string name, Stmts &&stmts): NamedNode(name, std::move(stmts.node_children)) {} + UserType(const string name, vector &&stmts): NamedNode(name, std::move(stmts)) { } + + UserType(const string name, vector &&stmts, vector &&implements): + NamedNode(name, std::move(stmts)), implements(std::move(implements)) { } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - UserType(const string name, Stmts &&stmts, vector &&implements): - NamedNode(name, std::move(stmts.node_children)), - implements(std::move(implements)) {} + void accept(Visitor& v) override; - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/Variable.h b/src/Variable.h new file mode 100644 index 0000000..ed5c10e --- /dev/null +++ b/src/Variable.h @@ -0,0 +1,40 @@ + +#pragma once + +#include "Node.h" + +class Identifier: public SourceLocation { +private: + string ident; + bool complex; + +public: + Identifier(const string& ident): ident(ident) { + complex = ident.find('.') != string::npos; + } + + Node* getSymbol(Node *scope, bool validate = true); + + string const getFullName() const { + return ident; + } + + bool isComplex() { + return complex; + } + + Identifier getStem(); +}; + +class Variable: public NamedNode { +protected: + Value *alloc; + Identifier ident; + +public: + Variable(const string &name): NamedNode(name), ident(name) {} + + virtual Value* getLLVMValue(Node *stem) override { + return alloc; + } +}; diff --git a/src/Visitor.cpp b/src/Visitor.cpp deleted file mode 100644 index 43be0ee..0000000 --- a/src/Visitor.cpp +++ /dev/null @@ -1,3 +0,0 @@ - -#include "Header.h" - diff --git a/src/Visitor.h b/src/Visitor.h index eaeaa88..f8bd8f1 100644 --- a/src/Visitor.h +++ b/src/Visitor.h @@ -1,42 +1,92 @@ -#ifndef __VISITOR_H__ -#define __VISITOR_H__ +#pragma once #include "Node.h" +class BinaryOp; +class Capsule; +class CmpOp; +class Delay; +class Float; +class FunctionCall; +class FunctionDecl; +class FunctionImpl; +class FunctionBase; +class Matrix; +class If; +class InPort; +class Int16; +class Int32; +class Int64; +class Int8; +class Load; +class LoadArray; +class OutPort; +class Print; +class Program; +class Return; +class Scalar; +class StringConst; +class Array; +class While; +class Loop; +class UserType; +class Variable; +class NamedConst; +class LinearDataStructure; + +#define VISITOR_DECLAREP(T, P) \ + virtual void visit(T& n) { visit((P&)n); } \ + virtual void after(T&) {} \ + virtual bool before(T&) { return false; } + #define VISITOR_DECLARE(T) \ - virtual void visit(T const&) {}; \ - virtual void after(T const&) {}; \ - virtual bool before(T const&) { return false; } + virtual void visit(T& n) { visit((Node&)n); } \ + virtual void after(T&) {} \ + virtual bool before(T&) { return false; } + +#define VISITOR_VISIT(T) \ + void T::accept(Visitor& v) {\ + v.visit(*this);\ + } class Visitor { public: - VISITOR_DECLARE(Node); - VISITOR_DECLARE(BinaryOp); - VISITOR_DECLARE(Capsule); - VISITOR_DECLARE(CmpOp); - VISITOR_DECLARE(Delay); - VISITOR_DECLARE(Float); - VISITOR_DECLARE(FunctionCall); - VISITOR_DECLARE(FunctionDecl); - VISITOR_DECLARE(Matrix); - VISITOR_DECLARE(If); - VISITOR_DECLARE(InPort); - VISITOR_DECLARE(Int16); - VISITOR_DECLARE(Int32); - VISITOR_DECLARE(Int8); - VISITOR_DECLARE(Load); - VISITOR_DECLARE(LoadArray); - VISITOR_DECLARE(OutPort); - VISITOR_DECLARE(Print); - VISITOR_DECLARE(Program); - VISITOR_DECLARE(Return); - VISITOR_DECLARE(Scalar); - VISITOR_DECLARE(Stmts); - VISITOR_DECLARE(String); - VISITOR_DECLARE(Array); - VISITOR_DECLARE(While); -}; + virtual void visit(Node&) { } + virtual void after(Node&) {} + virtual bool before(Node&) { return false; } + + VISITOR_DECLARE(NamedNode) + VISITOR_DECLARE(BinaryOp) + VISITOR_DECLARE(Capsule) + VISITOR_DECLARE(CmpOp) + VISITOR_DECLARE(Delay) + VISITOR_DECLARE(Float) + VISITOR_DECLARE(FunctionCall) + VISITOR_DECLARE(If) + VISITOR_DECLARE(InPort) + VISITOR_DECLARE(Int16) + VISITOR_DECLARE(Int32) + VISITOR_DECLARE(Int8) + VISITOR_DECLARE(Load) + VISITOR_DECLARE(LoadArray) + VISITOR_DECLARE(OutPort) + VISITOR_DECLARE(Print) + VISITOR_DECLARE(Program) + VISITOR_DECLARE(Return) + VISITOR_DECLARE(StringConst) + VISITOR_DECLARE(While) + VISITOR_DECLARE(Loop) + VISITOR_DECLAREP(Scalar, Variable) + VISITOR_DECLAREP(Variable, NamedNode) + VISITOR_DECLAREP(NamedConst, NamedNode) + VISITOR_DECLAREP(FunctionBase, NamedNode) + VISITOR_DECLAREP(FunctionDecl, FunctionBase) + VISITOR_DECLAREP(UserType, NamedNode) + VISITOR_DECLAREP(FunctionImpl, FunctionBase) + VISITOR_DECLAREP(LinearDataStructure, Variable) + VISITOR_DECLAREP(Array, LinearDataStructure) + VISITOR_DECLAREP(Matrix, LinearDataStructure) -#endif +}; diff --git a/src/While.cpp b/src/While.cpp index 0bf2019..971cf04 100644 --- a/src/While.cpp +++ b/src/While.cpp @@ -1,15 +1,21 @@ -#include "Header.h" -While::While(Node *e, Node *stms) : expr(e), stmts(stms) { - node_children.reserve(2); - node_children.push_back(e); - node_children.push_back(stms); +#include "While.h" +#include "FunctionImpl.h" + +While::While(Node *e) : expr(e) { + addChild(e); +} + +While::While(Node *e, vector &&ss) : While(e) { + stmts = new Node(std::move(ss)); + addChild(stmts); } -Value *While::generate(Function *func, BasicBlock *block, BasicBlock *allocblock) { - BasicBlock *condwhile = BasicBlock::Create(global_context, "while_cond", func, 0); - BasicBlock *bodywhile = BasicBlock::Create(global_context, "while_body", func, 0); - BasicBlock *endwhile = BasicBlock::Create(global_context, "while_end", func, 0); +Value *While::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + Function *llvmf = func->getLLVMFunction(); + BasicBlock *condwhile = BasicBlock::Create(global_context, "while_cond", llvmf, 0); + BasicBlock *bodywhile = BasicBlock::Create(global_context, "while_body", llvmf, 0); + BasicBlock *endwhile = BasicBlock::Create(global_context, "while_end", llvmf, 0); // go to condition RobDbgInfo.emitLocation(expr); @@ -24,11 +30,13 @@ Value *While::generate(Function *func, BasicBlock *block, BasicBlock *allocblock Builder->CreateCondBr(exprv, bodywhile, endwhile); // alloc instructions inside bodywhile should go to allocblock to prevent repeatedly allocation - Value *newb = stmts->generate(func, bodywhile, allocblock); + Value *newb = NULL; + if (stmts) + newb = stmts->generateChildren(func, bodywhile, allocblock); // identify last while body block BasicBlock *endbody = bodywhile; - if (newb->getValueID() == Value::BasicBlockVal) + if (newb && newb->getValueID() == Value::BasicBlockVal) endbody = (BasicBlock*)newb; // if end block already has a terminator, don't generate branch @@ -39,8 +47,3 @@ Value *While::generate(Function *func, BasicBlock *block, BasicBlock *allocblock return endwhile; } - -void While::accept(Visitor& v) { - v.visit(*this); -} - diff --git a/src/While.h b/src/While.h index f3b5f24..6098ab5 100644 --- a/src/While.h +++ b/src/While.h @@ -1,5 +1,5 @@ -#ifndef __WHILE_H__ -#define __WHILE_H__ + +#pragma once #include "Node.h" @@ -7,10 +7,10 @@ class While: public Node { private: Node *expr; Node *stmts; + public: - While(Node *e, Node *stms); - virtual Value *generate(Function *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; -}; + While(Node *e); + While(Node *e, vector &&stmts); + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; -#endif +}; diff --git a/src/main.cpp b/src/main.cpp index d66e7bf..5d9d64a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,11 +2,13 @@ #include #include -#include "Header.h" +#include "BackLLVM.h" +#include "Scanner.h" +#include "Program.h" void print_llvm_ir(char opt_level); -Function *AttachInterrupt::fattach = NULL; bool debug_info; +extern char *build_outputfilename; int main(int argc, char *argv[]) { @@ -21,11 +23,12 @@ int main(int argc, char *argv[]) { if (t > 1) fprintf(stderr, ","); fprintf(stderr, "%s", supportedTargets[t].name); } - fprintf(stderr, "} -g -O{1,2,3,s,z} -o output_file input_file\n"); + fprintf(stderr, "} -I {include_dir} -g -O{1,2,3,s,z} -o output_file input_file\n"); return 1; } // Compila o arquivo passado como parâmetro + const char* buildFileName = NULL; FILE *source = NULL; int i = 1; while (i < argc) { @@ -33,17 +36,22 @@ int main(int argc, char *argv[]) { if (strlen(argv[i]) > 2) optimization = argv[i][2]; } - else if (strncmp(argv[i], "-a", 2) == 0) { + else if (strncmp(argv[i], "-a", 2) == 0) { // target arch targetarch = argv[++i]; } - else if (strncmp(argv[i], "-g", 2) == 0) { + else if (strncmp(argv[i], "-g", 2) == 0) { // debug debug_info = true; } - else if (strncmp(argv[i], "-o", 2) == 0) { - build_outputfilename = argv[++i]; + else if (strncmp(argv[i], "-o", 2) == 0) { // output + if (i+1 < argc) + build_outputfilename = argv[++i]; + } + else if (strncmp(argv[i], "-I", 2) == 0) { // include dirs + if (i+1 < argc) + includeDirs.push_back(argv[++i]); } else { - build_filename = argv[i]; + buildFileName = argv[i]; } i++; } @@ -51,7 +59,7 @@ int main(int argc, char *argv[]) { // set current target and basic build types initTarget(targetarch); - if (!parseFile(build_filename)) + if (!parseFile(buildFileName)) exit(1); if (errorsfound > 0) { diff --git a/testnew/avr328p/Makefile b/testnew/avr328p/Makefile new file mode 100644 index 0000000..a24ea27 --- /dev/null +++ b/testnew/avr328p/Makefile @@ -0,0 +1,46 @@ +ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) +ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,out/%.tt,$(wildcard *.rob)) +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/avr328p.o + +ROBCMP=../../robcmp +OPT=-g -O0 +#OPT=-Oz + +#LD_FLAGS=-nostdlib -entry=main -L../../lib -Bstatic -Tavr328p.ld -Tdata=0x800100 ../../lib/avr5.o +LD_FLAGS=-nostdlib -entry=main -L../../lib -Tavr5.xn -Tdata=0x800100 ../../lib/avr5.o +#LD_FLAGS+=-Bstatic +LD_FLAGS+=--gc-sections + +all: out ${ALL} + +out: + mkdir -p out + +clean: + rm -f ${ALL} ${ALL_LL} ${ALL_OO} + +out/avr328p.o : ../../lib/avr328p.rob + ${ROBCMP} -a avr328p ${OPT} -o $@ $< + +out/avr328p.ll : ../../lib/avr328p.rob + ${ROBCMP} -a avr328p ${OPT} $< > $@ + +.SECONDARY: +out/%.o : %.rob out/avr328p.o ${ROBCMP} Makefile + ${ROBCMP} -a avr328p ${OPT} -o $@ $< + +out/%.ll : %.rob ${ROBCMP} Makefile + ${ROBCMP} -a avr328p ${OPT} $< > $@ + +out/%.tt : %.rob + @-./runtest.sh $< $(patsubst %.rob,out/%,$<) + +out/% : out/%.o out/avr328p.o + @#ld.lld ${LD_FLAGS} $^ -o $@ + avr-ld ${LD_FLAGS} $^ -o $@ + + +test: ${ALL_TT} + + diff --git a/testnew/avr328p/aux/serial.rob b/testnew/avr328p/aux/serial.rob new file mode 100644 index 0000000..5755c9f --- /dev/null +++ b/testnew/avr328p/aux/serial.rob @@ -0,0 +1,79 @@ + +/* USART0 control status register A */ +register int8 UCSR0A at 0xc0 { + bool MPCM0; + bool U2X0; + bool UPE0; + bool DOR0; + bool FE0; + bool UDRE0; + bool TXC0; + bool RXC0; +} + +/* USART0 control status register B */ +register int8 UCSR0B at 0xc1 { + bool TXB80; + bool RXB80; + bool UCSZ02; + bool TXEN0; + bool RXEN0; + bool UDRIE0; + bool TXCIE0; + bool RXCIE0; +} + +/* USART0 control status register C */ +register int8 UCSR0C at 0xc2 { + bool UCPOL0; + int8 UCSZ0: 2; + bool USBS0; + int8 UPM0: 2; + int8 UMSEL0: 2; +} + +/* USART0 baud rate register, 12 bits*/ +register int16 UBRR0 at 0xc4; + +/* USART0 byte to send/received */ +register int8 UDR0 at 0xc6; + +type avr5_serial { + + void start(mcu m, int32 baud_rate) { + // set baudrate + UBRR0 = int16(((m.clock() / (8 * baud_rate)) -1)); + + // use 2x + UCSR0A.U2X0 = true; + + // 8 bit + UCSR0B.UCSZ02 = false; + UCSR0C.UCSZ0 = 0x3; + + // no parity + UCSR0C.UPM0 = 0x0; + + // 1 stop bit + UCSR0C.USBS0 = false; + + UCSR0B.RXEN0 = true; + UCSR0B.TXEN0 = true; + } + + void write(int8 c) { + while UCSR0A.UDRE0 == false; + UDR0 = c; + } + + int8 read() { + while UCSR0A.RXC0 == false; + return UDR0; + } + + bool has_data() { + return UCSR0A.RXC0; + } + +} + diff --git a/testnew/avr328p/itoa.rob b/testnew/avr328p/itoa.rob new file mode 100644 index 0000000..9c8692a --- /dev/null +++ b/testnew/avr328p/itoa.rob @@ -0,0 +1,128 @@ + +chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + +result = {0:18}; + +void itoa(int16 value, int8 base) { + if base < 2 or base > 16 { + result[0] = 0; + return; + } + + negative = false; + if value < 0 { + negative = true; + value = - value; + } + + i = 0; + if value == 0 { + result[i] = '0'; + i++; + } else { + while value != 0 { + temp = value; + value /= base; + result[i] = chars[temp - value * base]; + //result[i] = chars[value % base]; + //value /= base; + i++; + } + } + + if negative == true { + result[i] = '-'; + i++; + } + result[i] = 0; + + // reverse result + j = 0; + i--; + while j < i { + temp = result[j]; + result[j] = result[i]; + result[i] = temp; + j++; + i--; + } +} + +numbers = {-32123, -15678, -4364, -501, -25, 0, 25, 512, 4364, 15678, 32767}; + +base10 = { + {'-', '3', '2', '1', '2', '3', 0}, + {'-', '1', '5', '6', '7', '8', 0}, + {'-', '4', '3', '6', '4', 0 , 0}, + {'-', '5', '0', '1', 0 , 0 , 0}, + {'-', '2', '5', 0 , 0 , 0 , 0}, + {'0', 0 , 0 , 0 , 0 , 0 , 0}, + {'2', '5', 0 , 0 , 0 , 0 , 0}, + {'5', '1', '2', 0 , 0 , 0 , 0}, + {'4', '3', '6', '4', 0 , 0 , 0}, + {'1', '5', '6', '7', '8', 0 , 0}, + {'3', '2', '7', '6', '7', 0 , 0} +}; + +base16 = { + {'-', '7', 'd', '7', 'b', 0}, + {'-', '3', 'd', '3', 'e', 0}, + {'-', '1', '1', '0', 'c', 0}, + {'-', '1', 'f', '5', 0 , 0}, + {'-', '1', '9', 0 , 0 , 0}, + {'0', 0 , 0 , 0 , 0 , 0}, + {'1', '9', 0 , 0 , 0 , 0}, + {'2', '0', '0', 0 , 0 , 0}, + {'1', '1', '0', 'c', 0 , 0}, + {'3', 'd', '3', 'e', 0 , 0}, + {'7', 'f', 'f', 'f', 0 , 0} +}; + +bool check10(int8 id) { + ret = true; + i = 0; + while result[i] != 0 and ret == true { + if result[i] != base10[id][i] { + ret = false; + } + i++; + } + return ret; +} + +bool check16(int8 id) { + ret = true; + i = 0; + while result[i] != 0 and ret == true { + if result[i] != base16[id][i] { + ret = false; + } + i++; + } + return ret; +} + +void sleep_cpu(); + +int16 main() { + ret = true; + i = 0; + while i < numbers.size and ret == true { + itoa(numbers[i], 10); + ret = check10(i); + if ret == true { + itoa(numbers[i], 16); + ret = check16(i); + } + i++; + } + + sleep_cpu(); + + if ret == true { + return 0; + } else { + return 1; + } +} + diff --git a/testnew/avr328p/out/itoa b/testnew/avr328p/out/itoa new file mode 100755 index 0000000000000000000000000000000000000000..12d82656533337fcf4ffc0d6723eed56e81fe1ee GIT binary patch literal 6116 zcmb_g3vg3a8b0^lv<*#28y@ng+9D_@G)W&kT;(ZMkV>E}iYQ)^Hf;lK(@oMM?(UGZ zwq>6U853)F{=8TX88H z6j^yfS+6{F=@h-o;KvejXX%{1>3{7Anb~|9G|6zIB-OT6*i)BiFJ{TYAe_);H4WmBVImRz(*@ z9nmS#g-)kahBl49`a%{T{pAVAvT`rIoOjGbqpgd+dX+}{m2e89?EgB;b`z{-o!)$H z6l`vX&5Y9vhP$HSD2=LmV2oPh1D_p<3$a_eUz~p=>%vuQ{JHp%c>LmUT#RLOjqV<} z_ej>+tBjrR{=7TUozs)wGt_gw=hU%}j?LVk^NTNgKRTIn;?&9d9lLfM+~IbZhpS?) zBJ-uyvHZ4O+YWB)oBH5zIKHo)=m8|Z%`dF(?<$-EYDP{#v`$-8xFn~_zI6I7 zd*AeqnbDd1g&BEwn+jGfbeDdh9dcqoJgYU^RDw<#^~PgEB525exbi;J@C+!;(vkd|yYt%ihC4Cd z-te>G0~5@bem%5%gxx)nPRRal|I(hwNtiBHe(MZ{$(DZXPH=X^>)q{VhqUNV)kQxN zKiIyzeNx+wxD@LP_eA^J`$o+9P^8Oo;nKlym*f3Q@B$I*3l|jLnKNL2i_h=5^(UOO zBKjyDigZsHHGFnxa@(JVI>S@1i;^+=pS;-qeZ5%weZ9C%7mG=4;dp1e6x)S(?P}i@ z-t917DvWi8Lyl3ycY=Gs-j~y7+L_arACeC{zY#*=NO)u1(yOptVZ0?mxVf`E;M0SaUbARHvZM?| z&z(_Y6e%uM97V+?rL*VEop-m(U0vg;-PWck!xv58{w=}SB&0*Lb;10^)|5IcEGb40 zR#-%RSYc_&9AxRj*^VNp6c*1WMTe@b0yev-n6RqI)NZV#c~_`2 zUjGl73n zf+`52Br!pn2ikBy9vOnTA|*3Ok|Kx|z%r^Jlt@ypAk~02tivNi%;*rzlF+b$q?y9g z7*5C(BgPJnNe?KilOq}-ON?ahBV_J{Dp1A&LSvFL=^&wr)DJSTpU{k?OyIJagjj}I z>c*%WNxoVjQ#7hr$FZjWJfVu@IP3tSO0{>lG|?b5Y$ne7>w2#r(ff%Jy=ArcL_-X{ zX_E?@1aeh?uL2*fVT67o*Ee`bg&F*4upC>cVLlab`XxM%q4Kpsiz3DhXAELj!60a% zL};N#JYzUVJUUtkcO`j@&0*kuKs-~Dcg_$ey)(pHsq!S%2PRmB+bv@=Buj2)p5^T& zW~(p;u@g&~WLZ9Tq4@`_8$uLG><}ho z8-JTAJ@rneWUjSmN`baa$zrpgwVxPlH@1jN$7f2_V2v|=Vw?hvI^&f3E1A+-Tc&hZ zZNG5}{Yg{XvW<@xIySkD5ouPNv_`x`SZQ3C<`uL_F3ww=ZCtQi8ug&GrS=Qs>mM3l zKUtnBZQoiePKJ{^;gHB?;rSi6Z8kgp8@zDa)#@)Pp4ZIhfEm#oVg{*L$R1a;Q8GXH z&@H%Qn7)O3cW7mMqVD2Dfo-W__U{#!xDR8@o!Z>6L! z+WB6>?Ll882D7>%u?!u;it^h)nkA(&w#t*3F)aiou~FCIY|SIiH?Yfz(IYf2CnfoXSAc7D*a-T^I(#$eCw15k`cw2#i@;_B zFVM;FNzv;3|KIUl3j4J4Zbi+-O05D8VSg%+73JhavAu!1OQ4d)}xi= zs53YgSUYHKCzHMXz_h!m5Izh%klcpU{|(?XkRwHN`^SMhPAGz4ESAnZw`=;dh61~1De=a8`1IK_#PUB4hejI)1yGZ^zNS}r20c>FN zfxC6_DC2U~N9yk+jPa>I#cvI;_I~C9Zvdt}T7XLSy}+dyPm5m*@HzNHE|R^izxM4_4vXNw@jdBxY)K=q@s~bEnzw8bK(k zp2g{}I{a>IX{h%Gye0fQix0DQ9g*dwi>nsP2;Oq%O1Zpj7$gCdbyPJYahX+s3Ov;)>umR0-*yUDAb78or|>R`zrYFnAf9tx4Ror?)>eIo&1``!jX{?iZP2f_^%}*u zhmHGYLnN@xJ?@q|xw*yNqJ`ql)A~ppy>8a@}#6lU!lcbO=^u3@m9o2|RdXz_(z%b=v zt*Dudspox-iI((U)Zt_bW%q)o(IoyW^d@OWbh2eSn)DKIg1#AA(QG^nhDMX@r#KSc zr(TUrn5M<-dn7HFyLvEsKC9YeDR_6WTh;~Cq{d#Ddh?_Uf3cm)6e literal 0 HcmV?d00001 diff --git a/testnew/avr328p/out/register b/testnew/avr328p/out/register new file mode 100755 index 0000000000000000000000000000000000000000..9e1e67b8dcc0baabda01972ab86f17e1f61f41c2 GIT binary patch literal 5708 zcmb_geQ;FO6~FgA_QPGWBqWL$AR(YwYj>A`O8r0}EF|R9d{~+)&)sB67L)9{y9r|J zBw?8r?FWg;lTjH%vD%U8SQV7Ew8CpE+7D`Gbf(j>qlGuVp?~AndKO z1KP9TQYGFj)Gp&bBVojiKBL#@G43_C88M^V=rXn%QKQr7Fd|0SxW~|pEymr(UB)+z zcH`@YTR$-IJU=vXoIf>@C>UN?v~+agi#f@y`^HPz(-R{Fhf#ktF;p-LhFgD|?-`pI z^NnA}j*b3w^nlPm1;&f0WdGrNSNRW?9xeTh7aTuWcC_rDWm9Db<{fgq@A|}5e)d4= zA@BR%PrO^pwwLWLd#voL@!0u$^n^a7kLXYEpYUJtH@F+}5OiUEuyIf0M59}G`1gLg z=wmkS8}DLY`^+`z8xJwp1$DCF1*_$zF5D#v9VDDn?}FmluL~M%)BG6!n4nm z9`Vv>?fSFlX{2BBlNe?1r!M~$@ame}{@G>l`EB@gOs@WTL?6~^R5Jp%UXP^0ql`-caD4Z2G-jXGXHV@i_Y(=X*!SUS&gLzh#Awyo&l7%VdYfeq*5%Y*?V7 zu@kJ~(Y*h6N8cFDkGy!=$U~zi*ii7)zaAQm_ulYO8UPWhzvkzs4KGfgyjsJ}e zzwa9_=R3tSBc2Z<>TR2+Ryo5x;eX zxrCmv61035pH!4xd>>av%GZ;kjekOoN~B?-P^q7?j~^yZt58`S@?df@f^(RkAdY6| zT$|%u5S$Zyjlz4j5#@T*%`9b?*bcZ+*iL#vLGoA7?u8^)7O9||R6bC!CaPfKD|kOt9GcUl+eEtSEFEJvGU!@K z=e2aFm9xa#Lb?W1rv-cM7ve`Ao zx6fuwbuh(gs%naHQUO{Ff{vBbpmQlxeXG4*FY;H+RiD>OuJ8g2psy(=u*yTzxF~`) zCq=+68A0AD8>6&{&4Tk!eK=IjQC@OxP>RXI^)I)9DSKn1%-(6elt^f{Xx~RP^;8b58 z-04*R!2C}2r9nJSvQ4#JRFt_0VmAg;*!6f`6qer~z+X=cA%zE$D=JqdM0|*t;+s^| zO71CHzD=FIslHa-;`fx)Dhj;7c3QzG+*2Ho3Uu&r&*g#7ErQq_k971Vre`D2mWn1* zfpm8yp6rUI0*PdN8}_+W0I32wkdCI(ebMa!D?)uJ zV}0r6H?k$^?pTVgZ)^^-NIc%dHiUw#zNxA{$eK4-1z9US+A25WvA!9mwkCSe)(`u- zRf1ImRrBUh1F=bkKBQ_DDsbC_mDHPb)N>u4O^tN|vFHeLhyv*AUs)BLE=e3t+}44H1=gqwg*!2SR*#TO)hXsOWqsUd9hcPC-n z`|A~a8r0o_9I`j~ z7Oi%K7M?;e+rrAEbbfFE8G5fM&L z9AA6UzD{8I-8a3HY0GoXX`(lM{K=k}zR5#${W83|#;V#&gePtc=3NM0Y#Brd_}EOw zdo5q`CSgTN1BgRhrUGM`c`#o-%{PDP(6pACjSXvC+nPg{h(Ub0TCc(kLcR;iL+)jY zyP8JJAr+(d-_{ap{-1u$q{tMRqgV-)E0}3fN+zQv3zzw&4G;=7H8<8@B3|3d(XeYjhTedCKfN~rnFVf;Jt!C=_6bg z$-4szDU)pn{ztOJrjX*@7B5I7lzq7BbxR{KiB!9-7L6#gJdE8c0b1FGGA(5?uK|xf zt7Vb43=~o(+t0zHvq~0eqt=!N_DAr74%|JUr`*!}pnh~CMapvJ!W_o-*c8%V(G1>q N@wrU@Hjzd0{tFpKiW2|; literal 0 HcmV?d00001 diff --git a/testnew/avr328p/out/simple b/testnew/avr328p/out/simple new file mode 100755 index 0000000000000000000000000000000000000000..78ef774b0ab4d14a4655c86e4b564a4395e0b4d3 GIT binary patch literal 2940 zcmb_eO-x)>6h800(!vZ(fT6S%6l$SVV`glt6>V&X(gBgb%AYRK%M3hW2=n864+B^dTHzsbn>B2Qz7mczuX8g{5@6J4aG%P%M=bis^&%O8D``#z% zkpaUnNP|g}#8NNtC7@SFRHOJ#=+99D)hqiHbQbHn(nV-`%d=YU=9v@rysc+5Yz7 zorkge?G(FDRJ-NBH@9lHPGAfZNOTo=2AI#}3M^AU&{XP=z`Y6-BAZzdIp+h)Kyp`X zyCmjItJJM*xkApPQN^y=^Ip+$!4q8u`XiWXX-qn%^hC{|MlYqvRIj_8*H~d1uQ0I& z@vbpx1H@FL>u?@|t5M;g05e51WZvzZ2X9<7R+*SHG|Rdo3(p5SqD!pfq((H*&0@i! z`;2vCzRp@^0Z)_B9gEjkvBslqu?N@cn~Y{?%>*%%ideDNqL-sR^+WNi^+Z+|S+Oh8 zXq0331x_D5RN%`9Ht95{F#d`);H?^pYaut6FRj=Kr z3f}okRHGrP;vFr@IQ4I`Lr{{SpGJa%y~~MYSO-wuS0+1xkN} zcFGOAJa)>bAgfJR`knGwP@cOFJLM#pD_TT6-&?PT|PoQD@uWShRuMzwAnB`!b z*#CEkDPSv*^ZyA-^r?EY|KE!9bF%#yFLo#&-yO41aZ0wgvptl*7jn3sfj#jPkasiz~d7~QW*eT#*do=i{tXS`p#o{67L&C}+2 zVrkOp8x!NB2aK%NK?e?CpaXoS((g>|Q&Ym-$a|SAsOR`}NposH5^Ctgf}LGm6s6T{ zA(OXV3glej{i5bG*{ox)X^D4M^T?-JB=9y$)dWtafbWQE)kD47;Kl8#Z&m*1ngePG z+S>o}LTRx9XXSx*2&ig#@I7n}+1M`|lC@3!%Y^i;Fz~&jLHqSXp?S7FhTv$YknODy z&*tkme!nmifX?wQWaeKC^mUlfoq%V;HpZoZf++YBeq6H#oo^iq&9m(h{2H}W$i_bY vjo=%%;nxY|pCZ0Dd7U{9zry|+gDSvJ;giq+nr(s+;T3p-%kOqYs@C)m9(d7Z literal 0 HcmV?d00001 diff --git a/testnew/avr328p/register.c b/testnew/avr328p/register.c new file mode 100644 index 0000000..7ff51ab --- /dev/null +++ b/testnew/avr328p/register.c @@ -0,0 +1,29 @@ +#include + +struct UCSRA { + uint8_t MPCM0:1; + uint8_t U2X0 :1; + uint8_t UPE0 :1; + uint8_t DOR0 :1; + uint8_t FE0 :1; + uint8_t UDRE0 :1; + uint8_t TXC0 :1; + uint8_t RXC0 :1; +}; + +/* USART0 control status register A */ +volatile struct UCSRA *UCSR0A = (struct UCSRA*)0xc0; +volatile uint8_t *SREG = (uint8_t*)0x3f; +volatile uint16_t *STACK = (uint16_t*)0x3d; + +void init() { +// *SREG = 0; + *STACK = 0x0AFF; +} + +int main() { + //init(); + UCSR0A->U2X0 = 1; + //int a = UCSR0A->RXC0; + return 10; +} diff --git a/testnew/avr328p/register.rob b/testnew/avr328p/register.rob new file mode 100644 index 0000000..2957c0b --- /dev/null +++ b/testnew/avr328p/register.rob @@ -0,0 +1,84 @@ + +type UCSRA { + MPCM0 = false; + U2X0 = false; + UPE0 = false; + DOR0 = false; + FE0 = false; + UDRE0 = false; + TXC0 = false; + RXC0 = false; +} + +type UCSRB { + TXB80 = false; + RXB80 = false; + UCSZ02 = false; + TXEN0 = false; + RXEN0 = false; + UDRIE0 = false; + TXCIE0 = false; + RXCIE0 = false; +} + +type UCSRC { + UCPOL0 = false; + UCSZ0 = int2(0); + USBS0 = false; + UPM0 = int2(0); + UMSEL0 = int2(0); +} + +/* USART0 control status register A */ +register UCSRA UCSR0A at 0xc0; + +/* USART0 control status register B */ +register UCSRB UCSR0B at 0xc1; + +/* USART0 control status register C */ +register UCSRC UCSR0C at 0xc2; + +register int16 UBRR0 at 0xc4; +register int8 UDR0 at 0xc6; + +void start(int16 baud) { + // set baudrate + UBRR0 = int16(((16000000 / (16 * baud)) -1)); + //(((F_CPU) + 8 * (BAUD)) / (16 * (BAUD)) -1) + //UBRR0 = int16(((16000000 + 8*baud)/16*baud)-1); + + // use 2x + UCSR0A.U2X0 = false; + + // 8 bit + UCSR0B.UCSZ02 = false; + UCSR0C.UCSZ0 = 0x3; + + // no parity + UCSR0C.UPM0 = 0x0; + + // 1 stop bit + UCSR0C.USBS0 = false; + + UCSR0B.RXEN0 = true; + UCSR0B.TXEN0 = true; +} + +void write(int8 c) { + while UCSR0A.UDRE0 == false; + UDR0 = c; +} + +int16 main() { + a = 0; + if UCSR0A.UDRE0 == true { + a = 1; + } + start(9600); + write(65); + write(66); + write(67); + write(10); + asm "sleep"; + return 0; +} diff --git a/testnew/avr328p/run_avr b/testnew/avr328p/run_avr new file mode 120000 index 0000000..1dc1d13 --- /dev/null +++ b/testnew/avr328p/run_avr @@ -0,0 +1 @@ +../../platformio/toolchain-robcmp/bin/run_avr \ No newline at end of file diff --git a/testnew/avr328p/runtest.sh b/testnew/avr328p/runtest.sh new file mode 100755 index 0000000..63b8505 --- /dev/null +++ b/testnew/avr328p/runtest.sh @@ -0,0 +1,3 @@ +#!/bin/bash +#./run_avr -f 16000000 -m atmega328p -v -v -v -g 1234 $1 +./run_avr -f 16000000 -m atmega328p -v -v -v $1 diff --git a/testnew/avr328p/simple.rob b/testnew/avr328p/simple.rob new file mode 100644 index 0000000..e271ea6 --- /dev/null +++ b/testnew/avr328p/simple.rob @@ -0,0 +1,5 @@ + +int16 main() { + asm "sleep"; +} + diff --git a/testnew/general/Makefile b/testnew/general/Makefile new file mode 100644 index 0000000..a98afa3 --- /dev/null +++ b/testnew/general/Makefile @@ -0,0 +1,30 @@ +ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) +ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,out/%.tt,$(wildcard *.rob)) +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) + +ROBCMP=../../robcmp +#OPT=-g -O0 +OPT=-Oz + +all: out ${ALL} + +out: + mkdir -p out + +clean: + rm -f ${ALL} ${ALL_LL} ${ALL_OO} + +.SECONDARY: +out/%.o : %.rob ${ROBCMP} Makefile + ${ROBCMP} ${OPT} -o $@ $< + +out/%.ll : %.rob ${ROBCMP} Makefile + ${ROBCMP} ${OPT} $< > $@ + +out/%.tt : %.rob + @-./runtest.sh $< $(patsubst %.rob,out/%,$<) + +test: ${ALL_TT} + + diff --git a/testnew/general/bellmanford.rob b/testnew/general/bellmanford.rob new file mode 100644 index 0000000..a8a2982 --- /dev/null +++ b/testnew/general/bellmanford.rob @@ -0,0 +1,78 @@ +/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */ + +const INT_MAX = 9999; + +// edges (u,v,w) +graph = + {{0, 1, -1}, {0, 2, 4}, {1, 2, 3}, + {1, 3, 2}, {1, 4, 2}, {3, 2, 5}, + {3, 1, 1}, {4, 3, -3}}; + +// expected distances +dise = {0, -1, 2, -2, 1}; + +// Initialize distance of all vertices. +dis = {INT_MAX : 5}; + +bool bellmanford(int16 V, int16 src) { + + // Number of edges + E = graph.rows; + + // initialize distance of source as 0 + dis[src] = 0; + + /* Relax all edges |V| - 1 times. A simple + * shortest path from src to any other + * vertex can have at-most |V| - 1 edges + */ + i = 0; + while(i < (V-1)) { + j = 0; + while(j < E) { + d = dis[graph[j][0]] + graph[j][2]; + if (d < dis[graph[j][1]]) { + dis[graph[j][1]] = dis[graph[j][0]] + graph[j][2]; + } + j++; + } + i++; + } + + /* check for negative-weight cycles. + * The above step guarantees shortest + * distances if graph doesn't contain + * negative weight cycle. If we get a + * shorter path, then there is a cycle. + */ + i = 0; + while(i < E) { + x = graph[i][0]; + y = graph[i][1]; + weight = graph[i][2]; + if (dis[x] != INT_MAX and dis[x] + weight < dis[y]) { + //print "Graph contains negative weight cycle\n"; + return false; + } + i++; + } + + return true; +} + +int16 main() { + r = bellmanford(5, 0); + if r == false { + return 1; + } + + i = 0; + while i < dis.size { + if dis[i] != dise[i] { + return 1; + } + i++; + } + return 0; +} + diff --git a/testnew/general/bitstruct.rob b/testnew/general/bitstruct.rob new file mode 100644 index 0000000..b994424 --- /dev/null +++ b/testnew/general/bitstruct.rob @@ -0,0 +1,35 @@ + +type bitstruct { + a = false; + b = false; + c = false; + d = false; + e = false; + f = false; + g = false; + h = false; + i = false; + j = false; + k = true; +} + +void set_struct_kfield(bitstruct s) { + s.k = false; +} + +int16 main() { + x = bitstruct(); + x.a = true; + x.c = true; + x.e = true; + x.j = true; + + set_struct_kfield(x); + + if x.c == true and x.k == false and x.j == true { + return 0; + } else { + return 1; + } +} + diff --git a/testnew/general/fibonacci.rob b/testnew/general/fibonacci.rob new file mode 100644 index 0000000..9f32474 --- /dev/null +++ b/testnew/general/fibonacci.rob @@ -0,0 +1,32 @@ +/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */ + +int32 fibonacci (int32 n) { + if (n == 1 or n == 2) { + return 1; + } else { + return fibonacci(n - 1) + fibonacci(n - 2); + } +} + +int8 main() { + check = {1, 1, 2, 3, 5, 6765}; + + result = { + fibonacci(1), + fibonacci(2), + fibonacci(3), + fibonacci(4), + fibonacci(5), + fibonacci(20) + }; + + i = 0; + while (i < check.size) { + if (result[i] != check[i]) { + return 1; + } + i++; + } + + return 0; +} diff --git a/testnew/general/itoa.rob b/testnew/general/itoa.rob new file mode 100644 index 0000000..98c5e0d --- /dev/null +++ b/testnew/general/itoa.rob @@ -0,0 +1,123 @@ + +chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + +result = {0:18}; + +void itoa(int16 value, int8 base) { + if base < 2 or base > 16 { + result[0] = 0; + return; + } + + negative = false; + if value < 0 { + negative = true; + value = - value; + } + + i = 0; + if value == 0 { + result[i] = '0'; + i++; + } else { + while value != 0 { + temp = value; + value /= base; + result[i] = chars[temp - value * base]; + //result[i] = chars[value % base]; + //value /= base; + i++; + } + } + + if negative == true { + result[i] = '-'; + i++; + } + result[i] = 0; + + // reverse result + j = 0; + i--; + while j < i { + temp = result[j]; + result[j] = result[i]; + result[i] = temp; + j++; + i--; + } +} + +numbers = {-32123, -15678, -4364, -501, -25, 0, 25, 512, 4364, 15678, 32767}; + +base10 = { + {'-', '3', '2', '1', '2', '3', 0}, + {'-', '1', '5', '6', '7', '8', 0}, + {'-', '4', '3', '6', '4', 0 , 0}, + {'-', '5', '0', '1', 0 , 0 , 0}, + {'-', '2', '5', 0 , 0 , 0 , 0}, + {'0', 0 , 0 , 0 , 0 , 0 , 0}, + {'2', '5', 0 , 0 , 0 , 0 , 0}, + {'5', '1', '2', 0 , 0 , 0 , 0}, + {'4', '3', '6', '4', 0 , 0 , 0}, + {'1', '5', '6', '7', '8', 0 , 0}, + {'3', '2', '7', '6', '7', 0 , 0} +}; + +base16 = { + {'-', '7', 'd', '7', 'b', 0}, + {'-', '3', 'd', '3', 'e', 0}, + {'-', '1', '1', '0', 'c', 0}, + {'-', '1', 'f', '5', 0 , 0}, + {'-', '1', '9', 0 , 0 , 0}, + {'0', 0 , 0 , 0 , 0 , 0}, + {'1', '9', 0 , 0 , 0 , 0}, + {'2', '0', '0', 0 , 0 , 0}, + {'1', '1', '0', 'c', 0 , 0}, + {'3', 'd', '3', 'e', 0 , 0}, + {'7', 'f', 'f', 'f', 0 , 0} +}; + +bool check10(int8 id) { + ret = true; + i = 0; + while result[i] != 0 and ret == true { + if result[i] != base10[id][i] { + ret = false; + } + i++; + } + return ret; +} + +bool check16(int8 id) { + ret = true; + i = 0; + while result[i] != 0 and ret == true { + if result[i] != base16[id][i] { + ret = false; + } + i++; + } + return ret; +} + +int16 main() { + ret = true; + i = 0; + while i < numbers.size and ret == true { + itoa(numbers[i], 10); + ret = check10(i); + if ret == true { + itoa(numbers[i], 16); + ret = check16(i); + } + i++; + } + if ret == true { + return 0; + } else { + return 1; + } +} + diff --git a/testnew/general/out/bellmanford b/testnew/general/out/bellmanford new file mode 100755 index 0000000000000000000000000000000000000000..a42e6da98d3c29f75b485be06c4055c992d37905 GIT binary patch literal 33088 zcmeI*UuauZ90%~<$xUX()H{Vqr=mf{x;?b(wAi9-i6->~TNk>5+g^^Txz}c-S#57| zLpn0!9`X=Dec6-v=9>r#`VOFS2McX1Rr`kS2hujwEBm&bSWbt#S{$N2i%>UgERI9|F? zDRD0C0S>8S=gp}D_sl*0&U-Vzf4r~q(RW9AEX5J5X_(Q6{bR8wb=o@2oxeWGxv_6e z=2_w2y}!x#%KGJ;tl27!^1rFtt%d73d11|SmdBnORq4s_Uz^v z-JE=chq897<7TJ7zBrk0+?c!E_72V2t%V~aIlDD`-8EP_X|ba9pxR?&Ea?D zi*9n=Z}EYy-%5D*+O21g>fTrG^t5i~W8P0&v5EHStHIvo2mRTI`g_@jEc@MgkG3D5 zhI^JJm;KF2-k-cb-1*FD&{U6NaTT+a6;tt;6-!u3#jQW77wamrN29;!a`X^@00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009X6Hv%c1HhN}&d_(YVbUFHmcgib6cgh0? zC}EbDjC0<3b=`B!l2a@>tCU!DDwXA8)jhXbqGP4<8a@BoYH?+W=9i1*DxI>Zy+LvM zpr({VvvGbKy5h9PpBDXcQD$v#eBzfOUtz1@jqEaTpPvWMIgtEO$@$?152b^;`F-tv qJ`(0*VNPK_DLLOL?{k;?Q)F&azv-{vNd5BRkO@{{{8jMXM1KMJ0Og(l literal 0 HcmV?d00001 diff --git a/testnew/general/out/bitstruct b/testnew/general/out/bitstruct new file mode 100755 index 0000000000000000000000000000000000000000..a86b67886e7fa4906744757e2077b4d230bd77eb GIT binary patch literal 16664 zcmeI3!D|yy5XNUsi&a~blT;K96s(FQ+Iq-EjABTNRZH!mdU-U>rd@2JBpcg;kV5M{ zM=wGz-g^+wLcpun-o1F~Kj1<9=IsmFZ3X=Uz9F-3zIkt7W`68-zW+M9`^98VoE}A5U29V_ zCiJ($D2{aUzTSN_gN-S7MD@tKgPlSSKAkU0i4{yeqPk(Wod=z%uJ}0eTr)YnX(8fY$yFvEnD^ z;0y4$>3)JieDfdidF*H5K{#3)Rqd&dp0DR-7|673Tp7xxoP2+R$hP9xc=iBYj zZ{!~4P*+gJA=ovz-rp;VjA6auwDO{n011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011%5{}8C}u8m1$cUr!c&wBlO4~z8cx%AaN`*!cn*S?*jzU(fGuR0&C^X`}( zx3075YN~badK_FaR!9A**7@!<0-YCEeaq>6r?Z&kKUtSKR+q7LnUi(NA5CJ0?f?J) literal 0 HcmV?d00001 diff --git a/testnew/general/out/fibonacci b/testnew/general/out/fibonacci new file mode 100755 index 0000000000000000000000000000000000000000..7ec8aa5ed39224eec288f3bce42dd0cbd244526c GIT binary patch literal 16600 zcmeI3OK1~e5XZmWG+1eC0v4%SFv3zFNSpeA>Or%z!4!*D+iLB@k2VjQ(4>;4*rJs{ ztgr{6Ui9GEdk-SLh=o*pEC@ouOOFd}(Su$DjWfF&lBjs_;^jZ&pPBid^Zk%KGFsS3nD;~5c^3Hl9avrrSMSr`c)pSHKjKFW5(xLBq{sDgZ;Hj?ERtI zG2!N38fI~AY*OapvpFYr^4jw@&(mXQ;)A<{^Sa7%PV&{Mlrx#T$xKWpGl?mh__e;} z3(k4WfQ|EVEzU^ocZF9^_m#_Gqr3dpkaJG?U1h)FZs(e-Ii40G@8`LY5MAU>xp^1m z^s#GbA)lv&f4e2}N69ykdP&vB^Q?cdJ+vu6Y9w{cOlLbLlj9w+xycyiYzIkP$NQ&4 z*_Zmc!cyDo=vU*}wUaa!AUSVpq5_)i*seplc%c1AV=v_0Esx_ri{vZLoGqrIJ!KKW%+370r!E zVYPmEw3ul39eQY&mslLoZ|XPn{=P_II~ZA3sMA=b-sy;GXxf^go$!kEfs`Vx7j%wU zOsUd(&e7YHM_NxP(#?0NI%z$!!?l!GTKDX5HPtMwJG^v6YcwY{zhUOIX2ZO%wHRhh zYo+r8sV{?(g_Yc1-I=Aq}85# zq`Bvv`p0d(a{H+{=ici^+Ud7*_0=u9py zC*otVcvg55$?>VoSTvdx!Sq-%BhGll<~$X!_<*;NZO-$JPEWT_aXP{I-hCt=1?4{e X!*0%f;XEIp4*lQnla>3VeV_OVJCewl literal 0 HcmV?d00001 diff --git a/testnew/general/out/itoa b/testnew/general/out/itoa new file mode 100755 index 0000000000000000000000000000000000000000..75cb5a02de39c2d71e0ad60f0b234f23fdd1bb4a GIT binary patch literal 33248 zcmeI5U1%It6vxjb8=Iu9la^X6ipi5!VUztxHi;zdY{}Lw37XniZA*LI?9PyFvI!&` z(m+2}lRy$#=|f)xA4Eias1QWzTe@x}Eq#gfsVZvT3ezb7p4AZs?1?DgOg! z?)=X^_sqS&nb&(~?ayBeJBYMuBC29`Dzp-WsS(vBw*gF>-Ychs9-XVoIgW3u))x(UtWY4)J2R<3o2+qCH#bA~NMt zsmal)5KKy0y-p@Ibh%&v5FL*0sGA{-t*yqm)X- z(lNPnOsU7$%a;<2ZR;$>-BzjiSSmF(S_*Hkmp7dG?JXs6>msxx<@XZU`Y!s8z1kb; zIaYe7nQiN2Ew=6!kfyv=D^W(iIe9A`+yq_S!TKZC!uo0U^$bxxx0!c{-sW~Edp~=* zNx%5Nu_t*@6Z!vOZ|HpqFQcWbhYq;fdB}A00@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p z2!H?x{PziDkN(#6`$X+(%_p)8b;X)1rjIZDVLiHM>Csz;e&eD4ZZx}lo;&-pH8*+J zt2LMF)0gk04_F^qj|x%!=G`NU`>Mk8`|84luX`5mZ2rVGruTU%0)wZZ+$Tvo>eF zv4?1QZO4)(b836QlZj@#&v5gZmTu%p5L!#XXD=pzZpJxqJK&2%Xa6up8tpQ^=HpFgwOFDx}r0G)lY@O`d5b+ z?r(ftC>9rf-smkBi`@5=M0*w$(m18rvsy1^EztwN#X4bXn%r~`X z!so*3>m{H)4c78_CfLn6G4-U`h9V}T3p8K@8o``lzmG9pC~(p>~w0k zEXyu}3kZM!2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x{0|5;@fu2J z2gq{doPm;gN;lhEO;Md3JU}~CYDk$E%=l#5R6}MgVUAPHU~Izl)A9HanaT86jApe| zEICRG+UR6z&>Wwj_qB0zVsa!+*EA0;W%!X*KI#q8DG&eRT_e8Qu^6W+Gd}F6scOny zva`lRbfuaym-%dis~7o_yUgiVIo(5f9_rZDi%XheIR8@DHTgrjv#$Nz>U=1I&v5i} zuFkkx{--YeIE}G->6{L2^)x>8kh?b)kq+iZo5FK%~{NG)4uV}8Ma&A3&xL$w7-*46Ttcb_3O|dqbbG>Z0 z7yJ;{^9`2J3=Y^2jqzx3!*kU3tD$rK?u)#ey1e`J84iB0??aJ~3}}qYTEb5KIplR` z_3rKD=4#n%E7Vo?Rjz~LI%}?STrk_8=2^>Z5zBlLFCxB*m^I8m&k@sqhc(7J4y{2| z<2m&&b{dyrXaZ{Xcea~b`DQcS+e#7BW+B#bn7lujUs?L`X8iTHx1SHbT*qDvg`Oty zK_54~_I9{tnTw7S!`#Z>N`a=9cGBSH6jt zU>6|fZ@0`&V!d3%B0az2{#)0iFi;;cH2G3Tx)aC6$<=I+p9xST1cXklhM_~jgZh$_#> z*(pC%KH@rUm+fXx`n}AxvyC*{wz1Ae-nH`$8@w#8ln$>D=8Ch-5v J=X^dK+b>MnU*iA( literal 0 HcmV?d00001 diff --git a/testnew/general/out/simplescope b/testnew/general/out/simplescope new file mode 100755 index 0000000000000000000000000000000000000000..f8b3a6d8394ea697a741e0dd5dc6820b51229250 GIT binary patch literal 16560 zcmeI3KTi}<6vgkb5K%#>h(?Ps#=ixtVnN4hoG8I4Q3}`Q1)MQEgk25n2B@H+x3{&h z+`_`r#1CNWCondC0Sn_f@6BXq)XG?%o1A&~zBljgy}#M^e*W?O=P|RWVP<2{4DjuOP(c@@xJjd;@8ag-V?dHAI<-Hd#aqxS6?~8n7Kx16i5_am(5w8c! z4_A`A%Vn>vP*>Skxekl#thvhZmf7Jf&st`SSQd(S5%G1ztl>2D3NiiHSYxawp;f4A zJg5G}PT^7vO+n4U&USMv-)N@$TPb4NS%`JK`LKCnGgUb*o0CiY?|^fZkR zGVOi;U7~j58qR!wSZP<#AM@~gRgJ&P{&~h88tG;H9imY!sOQQ4PCx6;-SZe{2cYUB3X6id^G2$F+1+XS#=s?&RtL8=B&TX-I2v`Ia5y2!pwH?%Q^ZGRi2Tv z<9?`o%ym01+smF0`kCuw>uI)a6W#T^XBQhbJSeV|4zJ8aVe*^5Gw0(_H{%!+_DT5NH)cH72&C4XqD+ktoFErr07SP)r#DEX2k~ zM3N>hUAcAPh81Di$fm56m99+Ok)T^460GOUBb^dVbm8v5$>GkqcjorYH*D|Bho9en z?IY4^iKvFd%khwt=j7)jq9Yt}4yA5HdSipJTi0c@x@pzvo|&w(&Y@I)>~4ScDaQ5T z>M^qNIv$pg+N3F^r)PBY*vzZf3tZxx;fWX4DU!P?r%RG|rbb z%hq~gAWd?+7IUQfuiWQr4yB@z{)l5PY}RGp*X~~YC2UKjQb|2ox&BY<`R!A}m22%G zXJ2`aR}+0#V$p>C4D!3`;@oIfA=243$#@r0Uj9c!F~r?jD-UrlMq+cAW1e$)ZlAe7 z$$cZo4Gw3spRIH3Z;ub~iGB_@N9WXJu5&Ci)R~$cOK~pk7>Cqx`QC%zk5c!ich}U- zCwIQQIm2Uq4)dOx7`@3j7JJeLYEN@#+@Iv!xc0oPljrB|Z1THu|1u}{T$^g++tDhu za6PwYC-wArM^6XWl^NobxSimT_49e62JTN;xp<*L00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY>&CQ#@tdzMPU;Q(D+%jI&g7%wzsWu3yIY3ZJB zdG+S-LRUlhLYFsQ2y6Pc;bo0BYJ$aq6=ToxajSG^FME+?&pYqaHbVBROOssoIJ@~u zuW_}E618sElRFjiweM`Y5BlmGH@A1FzP{1TiLbRiWN)W7PsU#eKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##{+ocGSGM05AV1>#-n&Z%_G+4<{qnK_s#D`5Dm|0F zKc%PDNIIEH=cq18!SQ4!OWirTI60BismH~iJlFUY1o_A0qF2V@;vCW9ocUFFS<0iC zUtX8r_em}x6 zfcx;z2%bp_k;rlQHMlX8nX%m6+^q@Cwp*fI?yK~jA8=!)bGN74kJ$U^_MAA~g|xcX zre;hOEJtx1>-P8VUqLh2m~ux{cQ%i!sI^LCDy1i3sbIoV@ewxm*7w%Erwr6oH)@G9 z?Vn9vH^y&X&s`mF^qP+AYV_4u=Nvp;TxcJ>BvR|sC@nII<)YK0(2LMo!!h^JBbD;f$b6U|DXh#Fpw&*mwT?Hhzpi~*yZmzVdu`~` z=lOacStmAK|NC| z<>J(-TMQwlk9Fu6zl%hL`Tu{{jD)C@nO4IPd{JnXgN@S zpX?UFmBth2-)-AD>VAi_b=CQ3op;CVxOJUXS5vKX*FCt|XK!n^X(@!~oNG3o+14n& z7e{+O6Gr+y`L>F&?AaiauCNqFa@3Pw$aH1~r8_$)IkPZlg5}^rB?`=3FjEMYWOiXD zEXhMpYE`_hSJU?Dy>bwlVi;huJnzYR6&2U3@yNGqRPjZ9YBu4cz{Z^aL6oI>5xr{N zN1U!Xt#jkLzwUI(>AKTrt&S(r^?t_fZ|t5onL(`*i>=dSW0~ER&BDz-{Tkb^`~?8z Bn416q literal 0 HcmV?d00001 diff --git a/testnew/general/runtest.sh b/testnew/general/runtest.sh new file mode 100755 index 0000000..17fc685 --- /dev/null +++ b/testnew/general/runtest.sh @@ -0,0 +1,19 @@ +#!/bin/bash +GREEN="\033[0;32m" +RED="\033[0;31m" +NC="\033[0m" + +echo -n " $1" +make -s $2 &> /dev/null +if [ "$?" -eq 0 ]; then + timeout 10s ./$2 &> /dev/null + #./$2 &> /dev/null + if [ "$?" -eq 0 ]; then + echo -e \\r${GREEN}[PASS]\\t\\t${NC} + else + echo -e \\r${RED}[FAILED]\\t${NC} + fi +else + echo -e \\r${RED}[BUILD FAILED]\\t${NC} +fi + diff --git a/testnew/general/simple.rob b/testnew/general/simple.rob new file mode 100644 index 0000000..7d8e82f --- /dev/null +++ b/testnew/general/simple.rob @@ -0,0 +1,6 @@ +/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */ + +int16 main() { + return 0; +} + diff --git a/testnew/general/simplescope.rob b/testnew/general/simplescope.rob new file mode 100644 index 0000000..d2fc3d2 --- /dev/null +++ b/testnew/general/simplescope.rob @@ -0,0 +1,10 @@ +/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */ + +int16 main() { + i = 0; + while (i < 6) { + i++; + } + return i != 6; +} + diff --git a/testnew/general/sort.rob b/testnew/general/sort.rob new file mode 100644 index 0000000..d26d18d --- /dev/null +++ b/testnew/general/sort.rob @@ -0,0 +1,37 @@ +/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab + * sorts the vector a and check the result + */ + +a = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; +r = { -9, -5, -3, 0, 6, 6, 11, 12, 12, 17, 22, 22, 34, 44, 56, 100 }; + +void sort(int8 n) { + t = 0; + s = 0; + temp = 0; + while t < n - 1 { + s = t + 1; + while s < n { + if a[t] > a[s] { + temp = a[t]; + a[t] = a[s]; + a[s] = temp; + } + s++; + } + t++; + } +} + +int16 main() { + sort(a.size); + i = 0; + while i < a.size { + if a[i] != r[i] { + return 1; + } + i++; + } + return 0; +} + diff --git a/testnew/general/type.rob b/testnew/general/type.rob new file mode 100644 index 0000000..8a12994 --- /dev/null +++ b/testnew/general/type.rob @@ -0,0 +1,38 @@ + +type A { + field0 = int8(10); + + int8 get() { + return field0; + } +} + +type B { + field0 = int16(10); + field1 = int8(0); + field2 = A(); + + int16 get() { + return field0 + field1 + field2.get(); + } + + void set_field(int8 x) { + field1 = x; + } +} + +int16 main() { + a = A(); + + b = B(); + b.set_field(10); + + x = a.get(); + y = b.get(); + + if x == 10 and y == 30 { + return 0; + } else { + return 1; + } +} From b3693c62a58c30d94ae49a547b7e5c082485edc8 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 9 Aug 2023 00:02:28 -0300 Subject: [PATCH 027/117] Implements test cases, fixes debugging of avr and other general fixes. --- lib/avr328p.ld | 8 +- lib/avr328p.rob | 110 +++++++++--------- lib/avr5.S | 40 ++++--- lib/avr5.ld | 22 ++-- rob.vim | 2 +- src/Array.cpp | 7 +- src/BackLLVM.cpp | 13 ++- src/BackLLVM.h | 4 +- src/BuildTypes.cpp | 15 ++- src/BuildTypes.h | 11 +- src/DebugInfo.cpp | 14 ++- src/Field.h | 20 ---- src/FunctionCall.cpp | 5 +- src/FunctionCall.h | 2 +- src/FunctionDecl.cpp | 4 +- src/FunctionDecl.h | 17 ++- src/FunctionImpl.cpp | 18 +-- src/Header.h | 1 - src/HeaderExternals.h | 1 + src/HeaderGlobals.h | 1 + src/{Field.cpp => Identifier.cpp} | 2 +- src/Identifier.h | 27 +++++ src/Language.l | 2 +- src/Language.y | 48 ++------ src/LanguageHeader.y | 2 - src/LanguageUse.y | 185 ++++++++++++++++-------------- src/Load.cpp | 26 ++++- src/Load.h | 2 +- src/LoadArray.h | 2 +- src/Matrix.cpp | 6 +- src/Node.cpp | 15 +-- src/Node.h | 10 -- src/Pointer.cpp | 53 +++------ src/Pointer.h | 6 +- src/Program.cpp | 4 +- src/Scalar.cpp | 103 +++++++++-------- src/Scalar.h | 1 - src/Scanner.cpp | 7 +- src/Scanner.h | 2 +- src/UpdateArray.h | 2 +- src/UserType.cpp | 26 ++++- src/UserType.h | 7 ++ src/Variable.h | 24 +--- testnew/avr328p/Makefile | 46 ++++---- testnew/avr328p/aux/avr5mcu.rob | 11 ++ testnew/avr328p/aux/serial.rob | 92 +++++++++------ testnew/avr328p/globals.rob | 17 +++ testnew/avr328p/itoa.rob | 20 +++- testnew/avr328p/out/itoa | Bin 6116 -> 0 bytes testnew/avr328p/out/register | Bin 5708 -> 0 bytes testnew/avr328p/out/simple | Bin 2940 -> 0 bytes testnew/avr328p/register.c | 29 ----- testnew/avr328p/register.rob | 84 -------------- testnew/avr328p/runtest.sh | 22 +++- testnew/avr328p/runtrace.sh | 2 + testnew/avr328p/simple.rob | 5 - testnew/avr328p/uart.rob | 17 +++ testnew/general/Makefile | 3 + testnew/general/out/bellmanford | Bin 33088 -> 0 bytes testnew/general/out/bitstruct | Bin 16664 -> 0 bytes testnew/general/out/fibonacci | Bin 16600 -> 0 bytes testnew/general/out/itoa | Bin 33248 -> 0 bytes testnew/general/out/simple | Bin 16560 -> 0 bytes testnew/general/out/simplescope | Bin 16560 -> 0 bytes testnew/general/out/sort | Bin 33024 -> 0 bytes testnew/general/out/type | Bin 16744 -> 0 bytes 66 files changed, 622 insertions(+), 603 deletions(-) delete mode 100644 src/Field.h rename src/{Field.cpp => Identifier.cpp} (96%) create mode 100644 src/Identifier.h create mode 100644 testnew/avr328p/aux/avr5mcu.rob create mode 100644 testnew/avr328p/globals.rob delete mode 100755 testnew/avr328p/out/itoa delete mode 100755 testnew/avr328p/out/register delete mode 100755 testnew/avr328p/out/simple delete mode 100644 testnew/avr328p/register.c delete mode 100644 testnew/avr328p/register.rob create mode 100755 testnew/avr328p/runtrace.sh delete mode 100644 testnew/avr328p/simple.rob create mode 100644 testnew/avr328p/uart.rob delete mode 100755 testnew/general/out/bellmanford delete mode 100755 testnew/general/out/bitstruct delete mode 100755 testnew/general/out/fibonacci delete mode 100755 testnew/general/out/itoa delete mode 100755 testnew/general/out/simple delete mode 100755 testnew/general/out/simplescope delete mode 100755 testnew/general/out/sort delete mode 100755 testnew/general/out/type diff --git a/lib/avr328p.ld b/lib/avr328p.ld index 71cd8ae..150eced 100644 --- a/lib/avr328p.ld +++ b/lib/avr328p.ld @@ -4,16 +4,14 @@ MEMORY { - text (rx) : ORIGIN = 0, LENGTH = 128K - data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0 - eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K + text (rx) : ORIGIN = 0, LENGTH = 32K + data (rw!x) : ORIGIN = 0x800100, LENGTH = 2K + eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 1K fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = 1K } -__vectors_size = 106; /* should be 104, but llvm ir requires a return at the end of __vectors*/ - INCLUDE avr5.ld diff --git a/lib/avr328p.rob b/lib/avr328p.rob index 21f3221..385d5bc 100644 --- a/lib/avr328p.rob +++ b/lib/avr328p.rob @@ -3,78 +3,72 @@ */ void main(); -void __init(); -void __bad_irq(); +void __vectors(); + +// implemented in avr5.S void __do_copy_data(); void __do_clear_bss(); void __vectors() { + /* FIXME: provide proper interrupt functions instead of __vectors + * after implementing "weak" attribute for functions + */ + /* atmega328p has 26 interruptions */ - /* FIXME: provide proper interrupt functions instead of __bad_irq after implementing "weak" attribute for functions */ asm "rjmp __init"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; - asm "rjmp __bad_irq"; -} - -void __bad_irq() { - // reset - __vectors(); -} - -const offset = 0; -register int8 SREG at (0x3f + offset); -register int16 STACK at (0x3d + offset); + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; + asm "rjmp __vectors"; -void __init() { + asm "__init:"; // clear r1 (zero reg) - asm "eor r1, r1"; - - // clear SREG - SREG = 0; - //asm "out 0x3f, r1"; - - // set STACK at RAM top and call main - STACK = 0x0AFF; - /*asm "ldi r28, 0xFF"; - asm "ldi r29, 0x0A"; + asm "clr r1"; + // clear sreg + asm "out 0x3f, r1"; + // set stack at 0x08FF (0x100+2K-1) + asm "ldi r28, 0xFF"; + asm "ldi r29, 0x08"; asm "out 0x3e, r29"; - asm "out 0x3d, r28";*/ + asm "out 0x3d, r28"; + /* same code in .rob, but it produces a larger assembly code + /*register int8 SREG at 0x3f; + register int16 STACK at 0x3d; + SREG = 0; + STACK = 0x08FF;*/ + // copy global vars init data - //__do_copy_data(); + __do_copy_data(); - // clear vars initialized as zero - //__do_clear_bss(); + // clear zeroed global vars + __do_clear_bss(); main(); - // if main returns, reset. - __vectors(); -} - -void sleep_cpu() { + // if main returns, disable interruptions and sleep. + // this is used to quit simavr in our tests + asm "cli"; asm "sleep"; } diff --git a/lib/avr5.S b/lib/avr5.S index 7afe9d3..0372a50 100644 --- a/lib/avr5.S +++ b/lib/avr5.S @@ -325,22 +325,10 @@ __divmodhi4_exit: ret ENDF __divmodhi4 + /* - * Clear the bss data + * Copy data and clear bss */ -DEFUN __do_clear_bss - ldi r17, hi8(__bss_end) - ldi r26, lo8(__bss_start) - ldi r27, hi8(__bss_start) - rjmp .do_clear_bss_start -.do_clear_bss_loop: - st X+, __zero_reg__ -.do_clear_bss_start: - cpi r26, lo8(__bss_end) - cpc r27, r17 - brne .do_clear_bss_loop -ENDF __do_clear_bss - DEFUN __do_copy_data ldi r17, hi8(__data_end) @@ -348,12 +336,28 @@ DEFUN __do_copy_data ldi r27, hi8(__data_start) ldi r30, lo8(__data_load_start) ldi r31, hi8(__data_load_start) - rjmp .do_copy_data_start -.do_copy_data_loop: + rjmp __do_copy_data_start +__do_copy_data_loop: lpm r0, Z+ st X+, r0 -.do_copy_data_start: +__do_copy_data_start: cpi r26, lo8(__data_end) cpc r27, r17 - brne .do_copy_data_loop + brne __do_copy_data_loop + ret ENDF __do_copy_data + +DEFUN __do_clear_bss + ldi r17, hi8(__bss_end) + ldi r26, lo8(__bss_start) + ldi r27, hi8(__bss_start) + rjmp __do_clear_bss_start +__do_clear_bss_loop: + st X+, __zero_reg__ +__do_clear_bss_start: + cpi r26, lo8(__bss_end) + cpc r27, r17 + brne __do_clear_bss_loop + ret +ENDF __do_clear_bss + diff --git a/lib/avr5.ld b/lib/avr5.ld index 3b16305..1abad0e 100644 --- a/lib/avr5.ld +++ b/lib/avr5.ld @@ -7,33 +7,32 @@ OUTPUT_ARCH(avr:5) SECTIONS { - .text : { + .text : AT (0x0) { _start__vectors = .; KEEP(*(.vectors)) - . = __vectors_size; - _end_vectors = .; . = ALIGN(2); + _end_vectors = .; _stext = .; *(.progmem*) . = ALIGN(2); *(.text) . = ALIGN(2); *(.text.*) + . = ALIGN(2); _etext = . ; - } > text + } - .data : { + .data : AT (ADDR(.text) + SIZEOF(.text)) { PROVIDE (__data_start = .) ; *(.data) *(.data*) *(.rodata) /* We need to include .rodata here if gcc is used */ *(.rodata*) /* with -fdata-sections. */ . = ALIGN(2); - _edata = . ; PROVIDE (__data_end = .) ; - } > data AT> text + } > data - .bss ADDR(.data) + SIZEOF (.data) : AT (ADDR (.bss)) { + .bss : AT (ADDR (.bss)) { PROVIDE (__bss_start = .) ; *(.bss) *(.bss*) @@ -70,8 +69,9 @@ SECTIONS } > user_signatures /* DWARF 3 */ - .debug_pubtypes 0 : { *(.debug_pubtypes) } - .debug_ranges 0 : { *(.debug_ranges) } + .debug_pubtypes 1 : { *(.debug_pubtypes) } + .debug_ranges 1 : { *(.debug_ranges) } /* DWARF Extension. */ - .debug_macro 0 : { *(.debug_macro) } + .debug_macro 1 : { *(.debug_macro) } } + diff --git a/rob.vim b/rob.vim index 534b8c4..477c230 100644 --- a/rob.vim +++ b/rob.vim @@ -7,7 +7,7 @@ if exists("b:current_syntax") finish endif -syn keyword keywords while loop if else delay print return register at volatile const asm type +syn keyword keywords while loop if else delay print return register at volatile const asm type use syn keyword typeKeywords void char int8 int16 int32 int64 long unsigned float double bool syn keyword operatorKeywords and or quando esta servo syn keyword booleanKeyword true false diff --git a/src/Array.cpp b/src/Array.cpp index 2c6dfd1..b601497 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -59,8 +59,9 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb constantValues.push_back(dyn_cast(a)); ArrayRef constantRefs(constantValues); GlobalVariable *gv = new GlobalVariable(*mainmodule, arrayType, - false, GlobalValue::ExternalLinkage, ConstantArray::get(arrayType, constantRefs), name); - //gv->setDSOLocal(true); + false, GlobalValue::InternalLinkage, + ConstantArray::get(arrayType, constantRefs), name); + gv->setDSOLocal(true); gv->setAlignment(Align(2)); alloc = gv; @@ -74,7 +75,7 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb } else { Builder->SetInsertPoint(allocblock); - alloc = Builder->CreateAlloca(arrayType, globalAddrSpace, 0, name); + alloc = Builder->CreateAlloca(arrayType, dataAddrSpace, 0, name); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index c628aa9..0504cdb 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,9 @@ std::unique_ptr DBuilder; struct DebugInfo RobDbgInfo; std::unique_ptr buildTypes; -unsigned int globalAddrSpace = 0; +unsigned int codeAddrSpace = 1; +unsigned int dataAddrSpace = 0; + enum SupportedTargets currentTargetId; extern char *build_outputfilename; @@ -47,6 +50,13 @@ void print_llvm_ir(char opt_level) { std::string defaultt = sys::getDefaultTargetTriple(); supportedTargets[0].triple = defaultt.c_str(); + SubtargetFeatures Features; + StringMap HostFeatures; + if (sys::getHostCPUFeatures(HostFeatures)) + for (auto &F : HostFeatures) + Features.AddFeature(F.first(), F.second); + supportedTargets[0].features = Features.getString().c_str(); + TargetInfo ai = currentTarget; std::string Error; @@ -63,6 +73,7 @@ void print_llvm_ir(char opt_level) { mainmodule->setDataLayout(targetMachine->createDataLayout()); mainmodule->setTargetTriple(ai.triple); + mainmodule->setFramePointer(FramePointerKind::All); PassBuilder passBuilder(targetMachine); auto loopAnalysisManager = LoopAnalysisManager{}; diff --git a/src/BackLLVM.h b/src/BackLLVM.h index 0d7ffda..3c90d10 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -13,7 +13,9 @@ typedef struct { const DataType pointerType; } TargetInfo; -extern unsigned int globalAddrSpace; +extern unsigned int codeAddrSpace; +extern unsigned int dataAddrSpace; + enum SupportedTargets {native, avr328p, stm32f1, esp32, __last_target}; extern enum SupportedTargets currentTargetId; #define currentTarget (supportedTargets[currentTargetId]) diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 9b15614..f6cee26 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -2,6 +2,7 @@ #include "BuildTypes.h" #include "Node.h" #include "Variable.h" +#include "BackLLVM.h" BuildTypes::BuildTypes(DataType targetPointerType) { tinfo[tvoid] = {"void", 0, Type::getVoidTy(global_context), dwarf::DW_ATE_address}; @@ -33,6 +34,7 @@ BuildTypes::BuildTypes(DataType targetPointerType) { if (t > 0) // no void bitWidth = dl.getTypeAllocSizeInBits(info.llvmType); info.diType = DBuilder->createBasicType(info.name, bitWidth, info.dwarfEnc); + info.diPointerType = DBuilder->createPointerType(info.diType, 8); } } } @@ -42,20 +44,24 @@ DataType BuildTypes::getType(const string& name, bool createUndefined) { if (ut == namedTypes.end()) { if (createUndefined) return addDataType(DataTypeInfo(name)); - } else if (tinfo[ut->second].isDefined) { + } else if (tinfo[ut->second].isDefined || createUndefined) { return ut->second; } return undefinedType; } -DataType BuildTypes::addDataType(Node* userType, Type* llvmType) { +DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBitWidth) { const string& name = userType->getName(); auto udt = namedTypes.find(name); DataType id; const DataLayout &dl = mainmodule->getDataLayout(); - uint64_t bitWidth = dl.getTypeAllocSizeInBits(llvmType); uint32_t align = dl.getABITypeAlign(llvmType).value(); + + uint64_t bitWidth = typeBitWidth; + if (typeBitWidth == 0) + typeBitWidth = dl.getTypeAllocSizeInBits(llvmType); + if (udt == namedTypes.end()) { DataTypeInfo info(name.c_str(), bitWidth, llvmType, 0); @@ -69,6 +75,7 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType) { info.isDefined = true; info.isComplex = true; info.dwarfEnc = 0; + info.bitWidth = bitWidth; if (debug_info) { unsigned offset = 0; @@ -100,6 +107,8 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType) { info.diType = DBuilder->createClassType(RobDbgInfo.currScope(), name, RobDbgInfo.currFile(), userType->getLineNo(), bitWidth, align, 0, DINode::DIFlags::FlagZero, nullptr, dielems); + unsigned ptbw = tinfo[currentTarget.pointerType].bitWidth; + info.diPointerType = DBuilder->createPointerType(info.diType, 8); } return id; } diff --git a/src/BuildTypes.h b/src/BuildTypes.h index bc2cbf2..f393819 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -20,6 +20,7 @@ struct DataTypeInfo { Type *llvmType; unsigned dwarfEnc; DIType *diType; + DIDerivedType *diPointerType; SourceLocation *sl; bool isDefined; bool isComplex; @@ -32,13 +33,14 @@ struct DataTypeInfo { this->llvmType = NULL; this->dwarfEnc = 0; this->diType = NULL; + this->diPointerType = NULL; this->isDefined = false; this->isComplex = false; } DataTypeInfo(const char* name, unsigned bitWidth, Type *llvmType, unsigned dwarfEnc): name(name), bitWidth(bitWidth), llvmType(llvmType), dwarfEnc(dwarfEnc), diType(NULL), - sl(NULL), isDefined(true), isComplex(false) {}; + diPointerType(NULL), sl(NULL), isDefined(true), isComplex(false) {}; }; class BuildTypes { @@ -59,7 +61,7 @@ class BuildTypes { BuildTypes(DataType targetPointerType); - DataType addDataType(Node* userType, Type* llvmType); + DataType addDataType(Node* userType, Type* llvmType, unsigned typeBitWidth = 0); DataType getType(const string& name, bool createUndefined = false); @@ -83,6 +85,11 @@ class BuildTypes { return tinfo[tid].diType; } + DIDerivedType *diPointerType(unsigned tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].diPointerType; + } + SourceLocation *location(unsigned tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].sl; diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index c697c8d..7755621 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -42,6 +42,15 @@ DIScope* DebugInfo::currScope() { return scopes.back(); } +DIExpression *DebugInfo::getFixedOffsetExpression() { + // TODO: For some unknown reason (to me), we need to offset + // the var declaration by one to see its actual value + SmallVector Ops; + DIExpression *ex = DBuilder->createExpression(); + ex->appendOffset(Ops, 1); + return DIExpression::prependOpcodes(ex, Ops, false); +} + void DebugInfo::declareVar(Node *n, Value *alloc, BasicBlock *allocblock) { DataType dt = n->getDataType(); llvm::DIType *dty = buildTypes->diType(dt); @@ -51,7 +60,8 @@ void DebugInfo::declareVar(Node *n, Value *alloc, BasicBlock *allocblock) { auto sp = RobDbgInfo.currScope(); auto funit = RobDbgInfo.currFile(); DILocalVariable *d = DBuilder->createAutoVariable( - sp, n->getName(), funit, n->getLineNo(), dty, true); - DBuilder->insertDeclare(alloc, d, DBuilder->createExpression(), + sp, n->getName(), funit, n->getLineNo(), dty); + + DBuilder->insertDeclare(alloc, d, getFixedOffsetExpression(), DILocation::get(sp->getContext(), n->getLineNo(), n->getColNo(), sp), allocblock); } diff --git a/src/Field.h b/src/Field.h deleted file mode 100644 index 4f4514a..0000000 --- a/src/Field.h +++ /dev/null @@ -1,20 +0,0 @@ - -#pragma once - -#include "HeaderGlobals.h" -#include "Variable.h" - -class Field : public Variable { -public: - unsigned startBit; - unsigned bitWidth; - Field(const string& Name, DataType dt) : Variable(name) { - setDataType(dt); - } -}; - -class Structure { -public: - int nextBit; - map fields; -}; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 80c7863..8f1d494 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -52,7 +52,7 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock Value *var = leftValue; if (leftValue == NULL) { Builder->SetInsertPoint(allocblock); - var = Builder->CreateAlloca(buildTypes->llvmType(dt), globalAddrSpace, 0, leftName); + var = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, 0, leftName); } vector args; args.push_back(var); @@ -109,6 +109,9 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock vector args; for (int i = 0; i < parameters->getNumParams(); i++){ Value *valor = parameters->getParamElement(i)->generate(func, block, allocblock); + if (!valor) + return NULL; + DataType pdt = fsymbol->getParameters().getParamType(i); if (!buildTypes->isComplex(pdt)) { //TODO: we don't support cohercion between user types yet diff --git a/src/FunctionCall.h b/src/FunctionCall.h index 3529103..6b09b05 100644 --- a/src/FunctionCall.h +++ b/src/FunctionCall.h @@ -3,7 +3,7 @@ #include "Node.h" #include "ParamsCall.h" -#include "Field.h" +#include "Identifier.h" class FunctionCall: public Node { private: diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 9232f99..e438dfe 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -41,8 +41,8 @@ Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocbloc Type *xtype = buildTypes->llvmType(dt); FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, globalAddrSpace, name, mainmodule); - //nfunc->setDSOLocal(true); + Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, codeAddrSpace, name, mainmodule); + nfunc->setDSOLocal(true); nfunc->setCallingConv(CallingConv::C); func = nfunc; diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 0eaed04..feb52eb 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -9,6 +9,8 @@ class FunctionBase: public NamedNode { FunctionParams *parameters; Function *func = NULL; bool declaration = true; + bool constructor = false; + bool external = false; bool validateAndGetArgsTypes(std::vector &args); @@ -20,9 +22,10 @@ class FunctionBase: public NamedNode { FunctionBase(DataType dt, string name, FunctionParams *fp, vector &&stmts, bool constructor = false) : - NamedNode(name, std::move(stmts), constructor) { + NamedNode(name, std::move(stmts)) { this->dt = dt; this->parameters = fp; + this->constructor = constructor; } FunctionParams& getParameters() { @@ -44,6 +47,18 @@ class FunctionBase: public NamedNode { bool isDeclaration() { return declaration; } + + bool isConstructor() { + return constructor; + } + + void setExternal(bool e) { + external = e; + } + + bool isExternal() { + return external; + } }; class FunctionDecl: public FunctionBase { diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 50297b2..8240b06 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -36,14 +36,18 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo return NULL; FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - func = Function::Create(ftype, Function::ExternalLinkage, globalAddrSpace, getFinalName(), mainmodule); + func = Function::Create(ftype, Function::ExternalLinkage, codeAddrSpace, getFinalName(), mainmodule); } - //func->setDSOLocal(true); + if (isExternal()) + return NULL; + + func->setDSOLocal(true); llvm::AttrBuilder attrs(global_context); //attrs.addAttribute(Attribute::MinSize); attrs.addAttribute("target-cpu", currentTarget.cpu); - //attrs.addAttribute("frame-pointer", "all"); + attrs.addAttribute("frame-pointer", "all"); + attrs.addAttribute("stack-protector-buffer-size", "8"); if (name == "init") // inline constructors attrs.addAttribute(Attribute::InlineHint); @@ -51,7 +55,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo if (name == "__vectors") { // FIXME: remove after adding functions attributes to language func->setSection(".vectors"); } - + func->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); func->setCallingConv(CallingConv::C); @@ -61,7 +65,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo funit = DBuilder->createFile(RobDbgInfo.cunit->getFilename(), RobDbgInfo.cunit->getDirectory()); DIScope *fcontext = funit; sp = DBuilder->createFunction(fcontext, getFinalName(), StringRef(), funit, this->getLineNo(), - getFunctionDIType(), this->getLineNo(), DINode::FlagPrototyped, DISubprogram::SPFlagDefinition); + getFunctionDIType(), this->getLineNo(), DINode::FlagZero, DISubprogram::SPFlagDefinition); func->setSubprogram(sp); RobDbgInfo.push_scope(funit, sp); } @@ -82,7 +86,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo Value *variable = &Arg; if (!buildTypes->isComplex(ptype)) - variable = Builder->CreateAlloca(buildTypes->llvmType(ptype), globalAddrSpace, 0, argname); + variable = Builder->CreateAlloca(buildTypes->llvmType(ptype), dataAddrSpace, 0, argname); if (argname == "#this") { thisArg = variable; @@ -96,7 +100,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo if (debug_info) { DILocalVariable *d = DBuilder->createParameterVariable(sp, argname, Idx+1, funit, this->getLineNo(), buildTypes->diType(ptype), true); - DBuilder->insertDeclare(variable, d, DBuilder->createExpression(), + DBuilder->insertDeclare(variable, d, RobDbgInfo.getFixedOffsetExpression(), DILocation::get(sp->getContext(), this->getLineNo(), 0, sp), falloc); } diff --git a/src/Header.h b/src/Header.h index a37b6d3..f41adac 100644 --- a/src/Header.h +++ b/src/Header.h @@ -11,7 +11,6 @@ #include "HeaderGlobals.h" #include "SourceLocation.h" #include "Scanner.h" -#include "Field.h" #include "Node.h" #include "ArrayElements.h" #include "AttachInterrupt.h" diff --git a/src/HeaderExternals.h b/src/HeaderExternals.h index cb8cf79..b3d471a 100644 --- a/src/HeaderExternals.h +++ b/src/HeaderExternals.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/src/HeaderGlobals.h b/src/HeaderGlobals.h index fcb1e34..d9b257c 100644 --- a/src/HeaderGlobals.h +++ b/src/HeaderGlobals.h @@ -28,6 +28,7 @@ struct DebugInfo { DIFile *currFile(); DIScope *currScope(); void declareVar(Node *n, Value *alloc, BasicBlock *allocblock); + DIExpression *getFixedOffsetExpression(); }; extern struct DebugInfo RobDbgInfo; diff --git a/src/Field.cpp b/src/Identifier.cpp similarity index 96% rename from src/Field.cpp rename to src/Identifier.cpp index de83eaf..f4b74b9 100644 --- a/src/Field.cpp +++ b/src/Identifier.cpp @@ -1,5 +1,5 @@ -#include "Field.h" +#include "Identifier.h" Node* Identifier::getSymbol(Node *scope, bool validate) { diff --git a/src/Identifier.h b/src/Identifier.h new file mode 100644 index 0000000..acad8be --- /dev/null +++ b/src/Identifier.h @@ -0,0 +1,27 @@ + +#pragma once + +#include "Node.h" + +class Identifier: public SourceLocation { +private: + string ident; + bool complex; + +public: + Identifier(const string& ident): ident(ident) { + complex = ident.find('.') != string::npos; + } + + Node* getSymbol(Node *scope, bool validate = true); + + string const getFullName() const { + return ident; + } + + bool isComplex() { + return complex; + } + + Identifier getStem(); +}; diff --git a/src/Language.l b/src/Language.l index fdf72bb..5237d11 100644 --- a/src/Language.l +++ b/src/Language.l @@ -158,7 +158,7 @@ ID {A}({A}|{D})* void update_loc(location_t *loc, int lineno, int leng, char *text) { loc->first_line = loc->last_line; - loc->last_line = loc->last_column; + loc->first_column = loc->last_column; if (loc->last_line == lineno) loc->last_column += leng; else { diff --git a/src/Language.y b/src/Language.y index b7e193c..9b0aff6 100644 --- a/src/Language.y +++ b/src/Language.y @@ -30,8 +30,6 @@ %type TOK_IDENTIFIER TOK_XIDENTIFIER ident_or_xident %type TOK_STRING asminline %type TOK_STEPPER -%type struct_field -%type struct_fields %type error %type intf_decls @@ -52,15 +50,15 @@ programa : gstmts { }; gstmts : gstmts gstmt { - $1->push_back($gstmt); - //$gstmt->setScope(program); + if ($gstmt) { // TOK_USE returns NULL + $1->push_back($gstmt); + } } gstmts : gstmt { $$ = new vector(); if ($gstmt) { $$->push_back($gstmt); - //$gstmt->setScope(program); $gstmt->setLocation(@gstmt); } } @@ -304,42 +302,10 @@ printstmt : TOK_PRINT TOK_STRING { $$ = new Print(new StringConst($2)); } | TOK_PRINT expr { $$ = new Print($2); } registerstmt : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT expr ';' { - $$ = new Pointer($name, buildTypes->getType($type, true), $5); - $$->setQualifier(qvolatile); - $$->setLocation(@name); - } - | TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT expr '{' struct_fields '}' { - $$ = new Pointer($name, buildTypes->getType($type, true), $5, $7); - $$->setLocation(@name); - } - ; - -struct_fields : struct_fields struct_field { - $2->startBit = $1->nextBit; - $1->fields[$2->getName()] = $2; - $1->nextBit += $2->bitWidth; - $$ = $1; - } - | struct_field { - Structure *s = new Structure(); - $1->startBit = 0; - s->fields[$1->getName()] = $1; - s->nextBit = $1->bitWidth; - $$ = s; - } - ; - -struct_field : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] ';' { - Field *s = new Field($id, buildTypes->getType($type, true)); - s->bitWidth = buildTypes->bitWidth(s->getDataType()); - $$ = s; - } - | TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] ':' TOK_INTEGER[bit] ';' { - Field *s = new Field($id, buildTypes->getType($type, true)); - s->bitWidth = (unsigned)$bit; - $$ = s; - } - ; + $$ = new Pointer($name, buildTypes->getType($type, true), $5); + $$->setQualifier(qvolatile); + $$->setLocation(@name); +} asminline : TOK_ASM TOK_STRING { $$ = $2; } ; diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index a66de44..a8bb066 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -47,13 +47,11 @@ MatrixElements *mes; FunctionParams *fps; ParamsCall *pc; - Structure *structure; vector *nodes; vector *strings; ArrayElement *ae; MatrixElement *me; FunctionParam *fp; - Field *field; } %start programa diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 2f54a1b..c170ed0 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -2,58 +2,60 @@ %name-prefix="USE" //%define api.prefix {USE} // not working in Bison 3.8.2 %define parse.error verbose + +// enable this to trace the parser. Also, set USEDebug=1 at Scanner.cpp. //%define parse.trace %code provides { #define YY_DECL int USElex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) YY_DECL; void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); - //#define YYDEBUG 1 } -%type gstmts -%type gstmt register interface type ignores ignore_once ignore use -%type function function_decl function_impl var_decl +%type globals type_stmts +%type global register interface type ignore_stmt ignore use type_stmt +%type function function_decl function_impl var_decl cast ignore_param %type function_params %type function_param %type intf_decls %type const_expr %type TOK_IDENTIFIER %type TOK_INTEGER -%type struct_fields -%type struct_field %type type_impls -%type error; +%type qualifier + +%printer { fprintf(yyo, "'%s'", $$); } +%printer { fprintf(yyo, "'%s'", $$ ? $$->getName().c_str() : ""); } %% -programa : gstmts { - for(auto stmt : *($gstmts)) { +programa : globals { + for(auto stmt : *($globals)) { program->addChild(stmt); } } -gstmts : gstmts gstmt { - $1->push_back($gstmt); - //$gstmt->setScope(program); +globals : globals global { + if ($global) { + $1->push_back($global); + } } -gstmts : gstmt { +globals : global { $$ = new vector(); - if ($gstmt) { - $$->push_back($gstmt); - //$gstmt->setScope(program); - $gstmt->setLocation(@gstmt); + if ($global) { + $global->setLocation(@global); + $$->push_back($global); } } -gstmt : register - | interface - | type - | function - | var_decl - | ignore_once - | use +global : use + | interface + | type + | register + | function + | var_decl { $$ = NULL; } // don't export global vars + | qualifier var_decl { $$ = NULL; } use : TOK_USE TOK_IDENTIFIER ';' { parseUseFile($2, @TOK_USE); @@ -67,22 +69,24 @@ function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER '(' function_params ')' ';' $$->setLocation(@type); } -function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' '{' ignores '}'[ef] { +function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' '{' ignore_stmts '}'[ef] { vector auxvec; - $$ = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, - std::move(auxvec), @ef); - $$->setLocation(@type); + FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, + std::move(auxvec), @ef); + func->setExternal(true); + func->setLocation(@type); + $$ = func; } function_params: function_params ',' function_param { $1 -> append($3); - $$ = $1; + $$ = $1; } function_params: function_param { FunctionParams *fps = new FunctionParams(); fps->append($1); - $$ = fps; + $$ = fps; } function_params: %empty { @@ -100,37 +104,6 @@ register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT const_e $$->setLocation(@name); } -register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT const_expr '{' struct_fields '}' { - $$ = new Pointer($name, buildTypes->getType($type, true), $5, $7); - $$->setLocation(@name); -} - -struct_fields : struct_fields struct_field { - $2->startBit = $1->nextBit; - $1->fields[$2->getName()] = $2; - $1->nextBit += $2->bitWidth; - $$ = $1; - } - | struct_field { - Structure *s = new Structure(); - $1->startBit = 0; - s->fields[$1->getName()] = $1; - s->nextBit = $1->bitWidth; - $$ = s; - } - ; - -struct_field : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] ';' { - Field *s = new Field($id, buildTypes->getType($type, true)); - s->bitWidth = buildTypes->bitWidth(s->getDataType()); - $$ = s; - } - | TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] ':' TOK_INTEGER[bit] ';' { - Field *s = new Field($id, buildTypes->getType($type, true)); - s->bitWidth = (unsigned)$bit; - $$ = s; - } - interface : TOK_INTF TOK_IDENTIFIER '{' intf_decls '}' { $$ = new Interface($TOK_IDENTIFIER, std::move(*$intf_decls)); $$->setLocation(@TOK_INTF); @@ -151,14 +124,18 @@ intf_decls : function_decl { $$->push_back($function_decl); } -type : TOK_TYPE TOK_IDENTIFIER TOK_IMPL type_impls '{' gstmts '}' { - $$ = new UserType($TOK_IDENTIFIER, std::move(*$gstmts), std::move(*$type_impls)); - $$->setLocation(@TOK_TYPE); +type : TOK_TYPE TOK_IDENTIFIER TOK_IMPL type_impls '{' type_stmts '}' { + UserType *ut = new UserType($TOK_IDENTIFIER, std::move(*$type_stmts), std::move(*$type_impls)); + ut->setLocation(@TOK_TYPE); + ut->setDeclaration(true); + $$ = ut; } -type : TOK_TYPE TOK_IDENTIFIER '{' gstmts '}' { - $$ = new UserType($TOK_IDENTIFIER, std::move(*$gstmts)); - $$->setLocation(@TOK_TYPE); +type : TOK_TYPE TOK_IDENTIFIER '{' type_stmts '}' { + UserType *ut = new UserType($TOK_IDENTIFIER, std::move(*$type_stmts)); + ut->setLocation(@TOK_TYPE); + ut->setDeclaration(true); + $$ = ut; } type_impls : type_impls ',' TOK_IDENTIFIER { @@ -171,30 +148,68 @@ type_impls : TOK_IDENTIFIER { $$->push_back($1); } -var_decl : TOK_IDENTIFIER '=' const_expr ';' { $$ = new Scalar($1, $3); }; +type_stmts : type_stmts type_stmt { + $$->push_back($type_stmt); +} + +type_stmts : type_stmt { + $$ = new vector(); + $$->push_back($type_stmt); +} + +type_stmt : var_decl + | qualifier[q] var_decl { $var_decl->setQualifier((DataQualifier)$q); $$ = $2; } + | function_impl + +qualifier : TOK_CONST { $$ = qconst; } + | TOK_VOLATILE { $$ = qvolatile; } + +var_decl : TOK_IDENTIFIER '=' const_expr ';' { $$ = new Scalar($1, $3); } +var_decl : TOK_IDENTIFIER '=' cast ';' { $$ = new Scalar($1, $3); } const_expr : TOK_INTEGER { $$ = getNodeForIntConst($1); } + | TOK_TRUE { $$ = new Int1(1); } + | TOK_FALSE { $$ = new Int1(0); } + //TODO: Add other constant nodes here! + +cast : TOK_IDENTIFIER[id] '(' ignore_param ')' { + ParamsCall *pc = new ParamsCall(); + pc->append(new Node()); + $$ = new FunctionCall($id, pc); + $$->setLocation(@id); +} + +ignore_param : ignore_p { $$ = NULL; } + | error { $$ = NULL; } + +/* put here any symbol that can start a expr. + * to be precise, the FIRST(expr) + */ +ignore_p : TOK_INTEGER { YYERROR; } + | TOK_IDENTIFIER { YYERROR; } -ignores : ignores ignore_once - | ignore_once +ignore_stmts : ignore_stmts ignore_stmt + | ignore_stmt -ignore_once : ignore ';' { $$ = NULL; } - | error ';' { $$ = NULL; } - | error '}' { $$ = NULL; } +ignore_stmt : ignore { $$ = NULL; } + | error '{' ignore_stmts '}' { $$ = NULL; } + | error ';' { $$ = NULL; } -/* put here any symbol that can start a stmt (except globals) - * to be precise, the FIRST(stmt) +/* put here any symbol that can start a stmt (except globals). + * to be precise, the FIRST(stmt) of Language.y */ -ignore : TOK_IDENTIFIER { YYERROR; } - | TOK_WHILE { YYERROR; } - | TOK_RETURN { YYERROR; } - | TOK_CONST { YYERROR; } - | TOK_VOLATILE { YYERROR; } - | TOK_IF { YYERROR; } - | TOK_LOOP { YYERROR; } - | TOK_ASM { YYERROR; } - | TOK_PRINT { YYERROR; } - | TOK_DELAY { YYERROR; } +ignore : TOK_IDENTIFIER { YYERROR; } + | TOK_XIDENTIFIER { YYERROR; } + | TOK_WHILE { YYERROR; } + | TOK_RETURN { YYERROR; } + | TOK_CONST { YYERROR; } + | TOK_VOLATILE { YYERROR; } + | TOK_IF { YYERROR; } + | TOK_ELSE { YYERROR; } + | TOK_LOOP { YYERROR; } + | TOK_ASM { YYERROR; } + | TOK_PRINT { YYERROR; } + | TOK_DELAY { YYERROR; } %% diff --git a/src/Load.cpp b/src/Load.cpp index 47aae6c..b1b3f2d 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -4,6 +4,7 @@ #include "Scalar.h" #include "FunctionImpl.h" #include "Variable.h" +#include "Pointer.h" DataType Load::getDataType() { if (dt == BuildTypes::undefinedType) { @@ -18,7 +19,7 @@ DataType Load::getDataType() { Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { Node *isymbol = ident.getSymbol(getScope()); - if (isymbol->isConstExpr()) + if (isymbol && isymbol->isConstExpr()) return isymbol->getLLVMValue(func); Variable *symbol = dynamic_cast(isymbol); @@ -41,7 +42,28 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl if (ident.isComplex()) { Identifier istem = ident.getStem(); Node *stem = istem.getSymbol(getScope()); - alloc = symbol->getLLVMValue(stem); + + // Pointers need a custom procedure: load the stem and get the + // requested bit value through bit shifting + Pointer *reg = dynamic_cast(stem); + if (reg && buildTypes->isComplex(reg->getDataType())) { + alloc = reg->getLLVMValue(NULL); + Type *req_eq_ty = Type::getIntNTy(global_context, buildTypes->bitWidth(reg->getDataType())); + Value *v = Builder->CreateLoad(req_eq_ty, alloc, reg->hasQualifier(qvolatile), "ptrvalue"); + /* this code does: + * v = symbol->value << pointerbits - field_start - field_width + * v = v >> pointer_bits - field_width + */ + int bs = buildTypes->bitWidth(reg->getDataType()) - buildTypes->bitWidth(symbol->getDataType()); + unsigned fieldStartBit = reg->getFieldStartBit(symbol); + if (bs - fieldStartBit > 0) + v = Builder->CreateShl(v, ConstantInt::get(req_eq_ty, bs - fieldStartBit)); + if (bs > 0) + v = Builder->CreateLShr(v, ConstantInt::get(req_eq_ty, bs)); + return Builder->CreateTrunc(v, buildTypes->llvmType(symbol->getDataType())); + } else { + alloc = symbol->getLLVMValue(stem); + } if (stem->hasQualifier(qvolatile)) symbol->setQualifier(qvolatile); diff --git a/src/Load.h b/src/Load.h index e99e715..259c2fc 100644 --- a/src/Load.h +++ b/src/Load.h @@ -1,7 +1,7 @@ #pragma once #include "Node.h" -#include "Field.h" +#include "Identifier.h" class Load: public Node { private: diff --git a/src/LoadArray.h b/src/LoadArray.h index 7be9323..63ef826 100644 --- a/src/LoadArray.h +++ b/src/LoadArray.h @@ -3,7 +3,7 @@ #include "Node.h" #include "Array.h" -#include "Field.h" +#include "Identifier.h" class LoadArray: public Node { protected: diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 93c1c50..63d0041 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -72,8 +72,10 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc constantValues.push_back(dyn_cast(a)); ArrayRef constantRefs(constantValues); GlobalVariable *gv = new GlobalVariable(*mainmodule, arrayType, - false, GlobalValue::ExternalLinkage, ConstantArray::get(arrayType, constantRefs), name); - //gv->setDSOLocal(true); + false, GlobalValue::InternalLinkage, + ConstantArray::get(arrayType, constantRefs), name); + gv->setDSOLocal(true); + gv->setAlignment(Align(2)); alloc = gv; } else { alloc = new AllocaInst(arrayType, 0, name, allocblock); diff --git a/src/Node.cpp b/src/Node.cpp index 314fbae..ea8e347 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -8,14 +8,7 @@ Node::~Node() {} -Node::Node(vector &&children, bool constructor) : node_children(children) { - // scalars alread has their scope set in the type - if (!constructor) - setChildrenScope(this); -} - Node::Node(vector &&children) : node_children(children) { - setChildrenScope(this); } std::vector const& Node::children() const { @@ -83,18 +76,12 @@ void Node::setScope(Node *s) { }*/ } -void Node::setChildrenScope(Node *s) { - for(auto& n : node_children) { - //n->setScope(s); - } -} - Value* Node::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return NULL; } Value* Node::generateChildren(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - for(Node *n: getChildren()) { + for(Node *n: children()) { Value *b = n->generate(func, block, allocblock); if (b && b->getValueID() == Value::BasicBlockVal) block = (BasicBlock*)b; diff --git a/src/Node.h b/src/Node.h index bf6222b..48474b9 100644 --- a/src/Node.h +++ b/src/Node.h @@ -17,12 +17,9 @@ class Node : public SourceLocation { set qualifiers; Node *scope = nullptr; - virtual void setChildrenScope(Node *scope); - public: Node() {} Node(vector &&children); - Node(vector &&children, bool constructor); virtual ~Node(); @@ -58,10 +55,6 @@ class Node : public SourceLocation { void addChild(Node *n); - vector const& getChildren() { - return node_children; - } - map const& getSymbols(); virtual void addSymbol(NamedNode *nm); @@ -102,9 +95,6 @@ class NamedNode: public Node { NamedNode(const string &name, vector &&children) : Node(std::move(children)), name(name) {} - NamedNode(const string &name, vector &&children, bool constructor) : - Node(std::move(children), constructor), name(name) {} - string const getName() const override { return name; } diff --git a/src/Pointer.cpp b/src/Pointer.cpp index ebe5241..b526b86 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -1,5 +1,7 @@ #include "Pointer.h" +#include "BackLLVM.h" +#include "UserType.h" Pointer::Pointer(const char *name, DataType type, Node *address): Variable(name), address(address) { @@ -7,14 +9,6 @@ Pointer::Pointer(const char *name, DataType type, Node *address): addChild(address); } -Pointer::Pointer(const char *name, DataType type, Node *address, Structure *structure): - Pointer(name, type, address) { - if (structure->nextBit > buildTypes->bitWidth(type)) { - const char *emsg = "The sum of field sizes for %s (%d) is larger than its type size (%d)."; - yyerrorcpp(string_format(emsg, name, structure->nextBit, buildTypes->bitWidth(type)), this); - } -} - Value *Pointer::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { auto sym = findSymbol(name, true); @@ -24,12 +18,6 @@ Value *Pointer::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo return NULL; } - // valid register types - /*if (!(dt == tint8 || dt == tint16 || dt == tint32 || dt == tint64)) { - yyerrorcpp("Register " + name + " must be of int8, int16, int32 or int64 type.", this); - return NULL; - }*/ - // generate code to produce the address Value *addr = address->generate(func, block, allocblock); if (addr == NULL) { @@ -38,34 +26,23 @@ Value *Pointer::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo } Type *targetPointerType = buildTypes->llvmType(dt)->getPointerTo(); - /*if (Constant *addrc = dyn_cast(addr)) { - alloc = ConstantExpr::getIntToPtr(addrc, targetPointerType); - } else*/ - auto sp = RobDbgInfo.currScope(); - auto funit = RobDbgInfo.currFile(); - + if (allocblock == global_alloc) { - /*Constant *addr_num = dyn_cast(addr); - assert(addr_num && "FIXME: global pointer defined without constant address."); - Constant *addr = ConstantExpr::getIntToPtr(addr_num, targetPointerType); - GlobalVariable *gv = new GlobalVariable(*mainmodule, buildTypes->llvmType(dt), - false, GlobalValue::CommonLinkage, addr, name); - //gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Local); - //gv->setDSOLocal(true); - alloc = gv; - - if (debug_info) { - auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", - funit, getLineNo(), buildTypes->diType(dt), false); - gv->addDebugInfo(d); - }*/ Constant *addr_num = dyn_cast(addr); assert(addr_num && "FIXME: global pointer defined without constant address."); alloc = ConstantExpr::getIntToPtr(addr_num, targetPointerType); + return alloc; + } else { + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + alloc = Builder->CreateIntToPtr(addr, targetPointerType, name); + return alloc; } - else { - alloc = new IntToPtrInst(addr, targetPointerType, name, allocblock); - } +} - return alloc; +unsigned Pointer::getFieldStartBit(Node *field) { + Node *dtsymbol = findSymbol(buildTypes->name(getDataType())); + UserType *ut = dynamic_cast(dtsymbol); + assert(ut && "Can't get field start bit from a non-complex type."); + return ut->getFieldStartBit(field); } diff --git a/src/Pointer.h b/src/Pointer.h index 6111bb4..f06b2ea 100644 --- a/src/Pointer.h +++ b/src/Pointer.h @@ -1,18 +1,16 @@ #pragma once -#include "Field.h" +#include "Variable.h" class Pointer: public Variable { private: Node *address; - Structure *structure; public: Pointer(const char *name, DataType type, Node *address); - Pointer(const char *name, DataType type, Node *address, Structure *structure); - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + unsigned getFieldStartBit(Node *symbol); }; diff --git a/src/Program.cpp b/src/Program.cpp index a2c7d4e..5ae1ae0 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -8,7 +8,7 @@ Program::Program() { if (debug_info) { mainmodule->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); - mainmodule->addModuleFlag(Module::Warning, "Dwarf Version", 2); + mainmodule->addModuleFlag(Module::Warning, "Dwarf Version", 4); DBuilder = make_unique(*mainmodule); RobDbgInfo.cunit = DBuilder->createCompileUnit(dwarf::DW_LANG_C, DBuilder->createFile(this->file, std::filesystem::current_path().string()), @@ -118,7 +118,7 @@ void Program::generate() { st.visit(*this); // generate the program! - for(auto n: getChildren()) + for(auto n: children()) n->generate(NULL, NULL, global_alloc); if (debug_info) diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 81f0b2f..ace8196 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -3,6 +3,7 @@ #include "Coercion.h" #include "FunctionImpl.h" #include "BackLLVM.h" +#include "Pointer.h" Scalar::Scalar(Identifier ident, Node *e) : Variable(ident.getFullName()), expr(e) { @@ -21,10 +22,19 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc if (!symbol) return NULL; + Pointer *reg = NULL; + Node *stem = NULL; if (ident.isComplex()) { Identifier istem = ident.getStem(); - Node *stem = istem.getSymbol(getScope()); - alloc = symbol->getLLVMValue(stem); + stem = istem.getSymbol(getScope()); + + // Pointers need to load the stem, get its alloc + reg = dynamic_cast(stem); + if (reg && buildTypes->isComplex(reg->getDataType())) { + alloc = reg->getLLVMValue(NULL); + } else { + alloc = symbol->getLLVMValue(stem); + } if (stem->hasQualifier(qvolatile)) symbol->setQualifier(qvolatile); @@ -76,8 +86,8 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc ret = alloc = exprvc; else { GlobalVariable *gv = new GlobalVariable(*mainmodule, buildTypes->llvmType(dt), - false, GlobalValue::CommonLinkage, exprvc, name); - //gv->setDSOLocal(true); + false, GlobalValue::InternalLinkage, exprvc, name); + gv->setDSOLocal(true); ret = alloc = gv; if (debug_info) { @@ -88,7 +98,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc } } else { Builder->SetInsertPoint(allocblock); - AllocaInst *temp = Builder->CreateAlloca(exprv->getType(), globalAddrSpace, 0, name); + AllocaInst *temp = Builder->CreateAlloca(exprv->getType(), dataAddrSpace, 0, name); temp->setAlignment(Align(1)); alloc = temp; Builder->SetInsertPoint(block); @@ -102,7 +112,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc } else { // variable already allocated - if (symbol->hasQualifier(qconst)) { + if (symbol->hasQualifier(qconst) && !func->isConstructor()) { yyerrorcpp("Constant '" + symbol->getName() + "' can not be changed.", this); return NULL; } @@ -110,47 +120,48 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Type *currty = buildTypes->llvmType(symbol->getDataType()); Builder->SetInsertPoint(block); - /* - if (complexIdent) { - // this code does: - // symbol->value &= ~(0x11... << field.startBit) - // symbol->value |= (exprv << field.startBit) - // - - // Coerce the left side to the field size - exprv = Coercion::Convert(exprv, buildTypes->llvmType(field.fieldDataType), block, expr); - // Expand to the left side size - exprv = Coercion::Convert(exprv, leftvty, block, expr); - - // Prepare the mask - Constant *allone = Constant::getAllOnesValue(Type::getIntNTy(global_context, field.bitWidth)); - Constant *ones = ConstantExpr::getZExt(allone, leftvty); - - if (field.startBit > 0) { - Constant *shiftl = ConstantInt::get(leftvty, field.startBit); - ones = ConstantExpr::getShl(ones, shiftl); - exprv = Builder->CreateShl(exprv, shiftl, "shift"); - } - Constant *mask = ConstantExpr::getNot(ones); - - // Load pointer value - Load ld(id); - ld.setLocation(expr); - Value *leftv = ld.generate(func, block, allocblock); - - // Apply mask, than or - Builder->SetInsertPoint(block); //caution, after generate! - Value *vaftermask = Builder->CreateAnd(leftv, mask, "mask"); - nvalue = Builder->CreateOr(vaftermask, exprv, "setbits"); - } else {*/ - - // TODO: remove this check after converting Coercion to use DataType - // instead of llvm::Type - Value *nvalue; - if (allocall) + if (allocall) { + // constructor result return allocall; - else { - nvalue = Coercion::Convert(exprv, currty, block, expr); + + } else { + Value *nvalue; + + // Pointers need a custom procedure: load the stem, set the + // requested bit value through bit shifting, and store the new value + if (reg && buildTypes->isComplex(reg->getDataType())) { + /* this code does: + * symbol->value &= ~(0x11... << fieldStartBit) + * symbol->value |= (exprv << fieldStartBit) + */ + Type *req_eq_ty = Type::getIntNTy(global_context, buildTypes->bitWidth(reg->getDataType())); + Value *v = Builder->CreateLoad(req_eq_ty, alloc, reg->hasQualifier(qvolatile), "ptrvalue"); + + // Prepare the mask + unsigned bitWidth = buildTypes->bitWidth(symbol->getDataType()); + Constant *allone = Constant::getAllOnesValue(Type::getIntNTy(global_context, bitWidth)); + Constant *ones = ConstantExpr::getZExt(allone, req_eq_ty); + + // Coerce the rvalue to the req size + exprv = Coercion::Convert(exprv, req_eq_ty, block, expr); + exprv = Builder->CreateAnd(exprv, ones, "truncrval"); + + unsigned fieldStartBit = reg->getFieldStartBit(symbol); + if (fieldStartBit > 0) { + Constant *shiftl = ConstantInt::get(req_eq_ty, fieldStartBit); + ones = ConstantExpr::getShl(ones, shiftl); + exprv = Builder->CreateShl(exprv, shiftl, "shift"); + } + Constant *mask = ConstantExpr::getNot(ones); + + // Apply mask, than or + Value *vaftermask = Builder->CreateAnd(v, mask, "mask"); + nvalue = Builder->CreateOr(vaftermask, exprv, "setbits"); + + } else { + nvalue = Coercion::Convert(exprv, currty, block, expr); + } + return Builder->CreateStore(nvalue, alloc, symbol->hasQualifier(qvolatile)); } } diff --git a/src/Scalar.h b/src/Scalar.h index 83cf069..051bbe2 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -1,7 +1,6 @@ #pragma once -#include "Field.h" #include "Variable.h" class Scalar: public Variable { diff --git a/src/Scanner.cpp b/src/Scanner.cpp index 05f1ab6..55ba833 100644 --- a/src/Scanner.cpp +++ b/src/Scanner.cpp @@ -64,7 +64,7 @@ bool parseFile(const string& source) { FILE *f = fopen(file_path.c_str(), "r"); if (f == NULL) { - fprintf(stderr, file_not_found.c_str(), file_path.c_str()); + fprintf(stderr, file_not_found, file_path.c_str()); return false; } @@ -105,7 +105,8 @@ bool parseUseFile(const string& use, location_t loc) { FILE *f = findFile(file_name, file_path); if (f == NULL) { - fprintf(stderr, file_not_found.c_str(), file_name.c_str()); + SourceLocation s(loc); + yyerrorcpp(string_format(file_not_found, file_name.c_str()), &s); return false; } @@ -131,7 +132,7 @@ bool parseUseFile(const string& use, location_t loc) { buildStackScanner.push_back(scanner); MAINset_in(f, scanner); - extern int USEdebug; + //extern int USEdebug; //USEdebug = 1; USEparse(scanner); MAINlex_destroy(scanner); diff --git a/src/Scanner.h b/src/Scanner.h index dc149ca..29f8dfa 100644 --- a/src/Scanner.h +++ b/src/Scanner.h @@ -9,7 +9,7 @@ using namespace std; -const string file_not_found = "No such file or directory '%s'\n"; +static const char *file_not_found = "No such file or directory '%s'."; typedef void* yyscan_t; extern int errorsfound; diff --git a/src/UpdateArray.h b/src/UpdateArray.h index f864eba..f2ea285 100644 --- a/src/UpdateArray.h +++ b/src/UpdateArray.h @@ -3,7 +3,7 @@ #include "Node.h" #include "Array.h" -#include "Field.h" +#include "Identifier.h" class UpdateArray: public Node { protected: diff --git a/src/UserType.cpp b/src/UserType.cpp index 34eb2d8..40ffb42 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -10,17 +10,23 @@ void UserType::createDataType() { std::vector elements; int idx = 0; - for(auto nn : this->getSymbols()) { - Scalar *s = dynamic_cast(nn.second); + unsigned startBit = 0; + for(auto child : this->children()) { + Scalar *s = dynamic_cast(child); if (s) { DataType sdt = s->getDataType(); elements.push_back(buildTypes->llvmType(sdt)); s->setGEPIndex(idx++); + + //FIXME: Fix for data alignment on non-packed structure/type + startBits[s->getName()] = startBit; + startBit += buildTypes->bitWidth(s->getDataType()); } } + unsigned bitWidth = startBit; - StructType *uttype = StructType::create(global_context, ArrayRef(elements), name); - dt = buildTypes->addDataType(this, uttype); + StructType *uttype = StructType::create(global_context, ArrayRef(elements), name, true); + dt = buildTypes->addDataType(this, uttype, bitWidth); if (dt == BuildTypes::undefinedType) { yyerrorcpp("Type " + name + " alread defined.", this); yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); @@ -56,7 +62,7 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all fields.push_back(c); } } - + // generate functions for(auto & [key, stmt] : getSymbols()) { if (FunctionImpl *f = dynamic_cast(stmt)) { @@ -64,6 +70,7 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all f->addThisArgument(dt); for(auto &field : fields) f->addSymbol(dynamic_cast(field)); + f->setExternal(declaration); f->generate(func, block, allocblock); } } @@ -73,11 +80,18 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all std::move(fields), *this->getLoct(), true); finit->addThisArgument(dt); finit->setUserTypeName(name); + finit->setExternal(declaration); addChild(finit); addSymbol(finit); - return finit->generate(func, block, allocblock); + finit->generate(func, block, allocblock); + + return NULL; } void UserType::accept(Visitor& v) { v.visit(*this); } + +unsigned UserType::getFieldStartBit(Node *field) { + return startBits[field->getName()]; +} \ No newline at end of file diff --git a/src/UserType.h b/src/UserType.h index a2caad1..6696b63 100644 --- a/src/UserType.h +++ b/src/UserType.h @@ -11,6 +11,8 @@ class UserType: public NamedNode { private: vector implements; void createDataType(); + map startBits; + bool declaration = false; public: @@ -23,4 +25,9 @@ class UserType: public NamedNode { void accept(Visitor& v) override; + unsigned getFieldStartBit(Node *field); + + void setDeclaration(bool d) { + declaration = d; + } }; diff --git a/src/Variable.h b/src/Variable.h index ed5c10e..c6882f6 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -2,29 +2,7 @@ #pragma once #include "Node.h" - -class Identifier: public SourceLocation { -private: - string ident; - bool complex; - -public: - Identifier(const string& ident): ident(ident) { - complex = ident.find('.') != string::npos; - } - - Node* getSymbol(Node *scope, bool validate = true); - - string const getFullName() const { - return ident; - } - - bool isComplex() { - return complex; - } - - Identifier getStem(); -}; +#include "Identifier.h" class Variable: public NamedNode { protected: diff --git a/testnew/avr328p/Makefile b/testnew/avr328p/Makefile index a24ea27..6b30d8c 100644 --- a/testnew/avr328p/Makefile +++ b/testnew/avr328p/Makefile @@ -4,43 +4,49 @@ ALL_TT=$(patsubst %.rob,out/%.tt,$(wildcard *.rob)) ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/avr328p.o ROBCMP=../../robcmp -OPT=-g -O0 -#OPT=-Oz +INCLUDES=-I aux -#LD_FLAGS=-nostdlib -entry=main -L../../lib -Bstatic -Tavr328p.ld -Tdata=0x800100 ../../lib/avr5.o -LD_FLAGS=-nostdlib -entry=main -L../../lib -Tavr5.xn -Tdata=0x800100 ../../lib/avr5.o -#LD_FLAGS+=-Bstatic +ifndef OPT +#OPT=-g -O0 +OPT=-Oz +endif + +LD_FLAGS=-nostdlib -entry=main -L../../lib -Tavr328p.ld ../../lib/avr5.o +LD_FLAGS+=-Bstatic LD_FLAGS+=--gc-sections +DEPENDS=${ROBCMP} Makefile +LINK_DEPENDS=out/avr328p.o +SERIAL_DEPENDS=out/aux/serial.o out/aux/avr5mcu.o + all: out ${ALL} out: - mkdir -p out - -clean: - rm -f ${ALL} ${ALL_LL} ${ALL_OO} + mkdir -p out/aux -out/avr328p.o : ../../lib/avr328p.rob +out/avr328p.o : ../../lib/avr328p.rob ${DEPENDS} ${ROBCMP} -a avr328p ${OPT} -o $@ $< -out/avr328p.ll : ../../lib/avr328p.rob +out/avr328p.ll : ../../lib/avr328p.rob ${DEPENDS} ${ROBCMP} -a avr328p ${OPT} $< > $@ .SECONDARY: -out/%.o : %.rob out/avr328p.o ${ROBCMP} Makefile - ${ROBCMP} -a avr328p ${OPT} -o $@ $< +out/%.o : %.rob out/avr328p.o ${DEPENDS} + ${ROBCMP} -a avr328p ${OPT} ${INCLUDES} -o $@ $< -out/%.ll : %.rob ${ROBCMP} Makefile - ${ROBCMP} -a avr328p ${OPT} $< > $@ +out/%.ll : %.rob ${DEPENDS} + ${ROBCMP} -a avr328p ${OPT} ${INCLUDES} $< > $@ -out/%.tt : %.rob +out/%.tt : %.rob ${DEPENDS} @-./runtest.sh $< $(patsubst %.rob,out/%,$<) -out/% : out/%.o out/avr328p.o - @#ld.lld ${LD_FLAGS} $^ -o $@ - avr-ld ${LD_FLAGS} $^ -o $@ - +out/itoa : out/itoa.o ${SERIAL_DEPENDS} ${LINK_DEPENDS} +out/uart : out/uart.o ${SERIAL_DEPENDS} ${LINK_DEPENDS} +out/% : out/%.o ${LINK_DEPENDS} + ld.lld ${LD_FLAGS} $^ -o $@ test: ${ALL_TT} +clean: + rm -f ${ALL} ${ALL_LL} ${ALL_OO} ${SERIAL_DEPENDS} diff --git a/testnew/avr328p/aux/avr5mcu.rob b/testnew/avr328p/aux/avr5mcu.rob new file mode 100644 index 0000000..8692f62 --- /dev/null +++ b/testnew/avr328p/aux/avr5mcu.rob @@ -0,0 +1,11 @@ + +type avr5mcu { + + int32 clock() { + return 16000000; + } + + void sleep() { + asm "sleep"; + } +} diff --git a/testnew/avr328p/aux/serial.rob b/testnew/avr328p/aux/serial.rob index 5755c9f..ba2afe9 100644 --- a/testnew/avr328p/aux/serial.rob +++ b/testnew/avr328p/aux/serial.rob @@ -1,37 +1,45 @@ -/* USART0 control status register A */ -register int8 UCSR0A at 0xc0 { - bool MPCM0; - bool U2X0; - bool UPE0; - bool DOR0; - bool FE0; - bool UDRE0; - bool TXC0; - bool RXC0; +use avr5mcu; + +type UCSRA { + MPCM0 = false; + U2X0 = false; + UPE0 = false; + DOR0 = false; + FE0 = false; + UDRE0 = false; + TXC0 = false; + RXC0 = false; } -/* USART0 control status register B */ -register int8 UCSR0B at 0xc1 { - bool TXB80; - bool RXB80; - bool UCSZ02; - bool TXEN0; - bool RXEN0; - bool UDRIE0; - bool TXCIE0; - bool RXCIE0; +type UCSRB { + TXB80 = false; + RXB80 = false; + UCSZ02 = false; + TXEN0 = false; + RXEN0 = false; + UDRIE0 = false; + TXCIE0 = false; + RXCIE0 = false; } -/* USART0 control status register C */ -register int8 UCSR0C at 0xc2 { - bool UCPOL0; - int8 UCSZ0: 2; - bool USBS0; - int8 UPM0: 2; - int8 UMSEL0: 2; +type UCSRC { + UCPOL0 = false; + UCSZ0 = int2(0); + USBS0 = false; + UPM0 = int2(0); + UMSEL0 = int2(0); } +/* USART0 control status register A */ +register UCSRA UCSR0A at 0xc0; + +/* USART0 control status register B */ +register UCSRB UCSR0B at 0xc1; + +/* USART0 control status register C */ +register UCSRC UCSR0C at 0xc2; + /* USART0 baud rate register, 12 bits*/ register int16 UBRR0 at 0xc4; @@ -39,24 +47,35 @@ register int16 UBRR0 at 0xc4; register int8 UDR0 at 0xc6; type avr5_serial { + const test = 10; + volatile teste2 = int32(0); - void start(mcu m, int32 baud_rate) { - // set baudrate - UBRR0 = int16(((m.clock() / (8 * baud_rate)) -1)); - + void start(avr5mcu mcu, int32 baud) { // use 2x - UCSR0A.U2X0 = true; - + UCSR0A.U2X0 = false; + + multipl = 16; + if UCSR0A.U2X0 == true { + multipl = 8; + } + + div = int32(multipl) * baud; + velocity = (mcu.clock() / div) - 1; + + // set baudrate + UBRR0 = int16(velocity); + // 8 bit UCSR0B.UCSZ02 = false; UCSR0C.UCSZ0 = 0x3; - + // no parity UCSR0C.UPM0 = 0x0; - + // 1 stop bit UCSR0C.USBS0 = false; - + + // enable tx and rx UCSR0B.RXEN0 = true; UCSR0B.TXEN0 = true; } @@ -76,4 +95,3 @@ type avr5_serial { } } - diff --git a/testnew/avr328p/globals.rob b/testnew/avr328p/globals.rob new file mode 100644 index 0000000..f6b1e21 --- /dev/null +++ b/testnew/avr328p/globals.rob @@ -0,0 +1,17 @@ + +boolean = true; + +vint8 = int8(0); +vint16 = int16(30); +vint32 = int32(16000000); + +int16 main() { + ret = int16(1); + if boolean == true { + if vint8 + vint16 + vint32 == 16000030 { + ret = 0; + } + } + return ret; +} + diff --git a/testnew/avr328p/itoa.rob b/testnew/avr328p/itoa.rob index 9c8692a..903f8b3 100644 --- a/testnew/avr328p/itoa.rob +++ b/testnew/avr328p/itoa.rob @@ -1,4 +1,6 @@ +use serial; + chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; result = {0:18}; @@ -102,23 +104,35 @@ bool check16(int8 id) { return ret; } -void sleep_cpu(); +void print_result(avr5_serial s) { + i = 0; + while result[i] != 0 { + s.write(result[i]); + i++; + } + s.write('\n'); +} int16 main() { + mcu = avr5mcu(); + serial = avr5_serial(); + serial.start(mcu, 9600); + ret = true; i = 0; while i < numbers.size and ret == true { itoa(numbers[i], 10); ret = check10(i); + print_result(serial); + if ret == true { itoa(numbers[i], 16); ret = check16(i); + print_result(serial); } i++; } - sleep_cpu(); - if ret == true { return 0; } else { diff --git a/testnew/avr328p/out/itoa b/testnew/avr328p/out/itoa deleted file mode 100755 index 12d82656533337fcf4ffc0d6723eed56e81fe1ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6116 zcmb_g3vg3a8b0^lv<*#28y@ng+9D_@G)W&kT;(ZMkV>E}iYQ)^Hf;lK(@oMM?(UGZ zwq>6U853)F{=8TX88H z6j^yfS+6{F=@h-o;KvejXX%{1>3{7Anb~|9G|6zIB-OT6*i)BiFJ{TYAe_);H4WmBVImRz(*@ z9nmS#g-)kahBl49`a%{T{pAVAvT`rIoOjGbqpgd+dX+}{m2e89?EgB;b`z{-o!)$H z6l`vX&5Y9vhP$HSD2=LmV2oPh1D_p<3$a_eUz~p=>%vuQ{JHp%c>LmUT#RLOjqV<} z_ej>+tBjrR{=7TUozs)wGt_gw=hU%}j?LVk^NTNgKRTIn;?&9d9lLfM+~IbZhpS?) zBJ-uyvHZ4O+YWB)oBH5zIKHo)=m8|Z%`dF(?<$-EYDP{#v`$-8xFn~_zI6I7 zd*AeqnbDd1g&BEwn+jGfbeDdh9dcqoJgYU^RDw<#^~PgEB525exbi;J@C+!;(vkd|yYt%ihC4Cd z-te>G0~5@bem%5%gxx)nPRRal|I(hwNtiBHe(MZ{$(DZXPH=X^>)q{VhqUNV)kQxN zKiIyzeNx+wxD@LP_eA^J`$o+9P^8Oo;nKlym*f3Q@B$I*3l|jLnKNL2i_h=5^(UOO zBKjyDigZsHHGFnxa@(JVI>S@1i;^+=pS;-qeZ5%weZ9C%7mG=4;dp1e6x)S(?P}i@ z-t917DvWi8Lyl3ycY=Gs-j~y7+L_arACeC{zY#*=NO)u1(yOptVZ0?mxVf`E;M0SaUbARHvZM?| z&z(_Y6e%uM97V+?rL*VEop-m(U0vg;-PWck!xv58{w=}SB&0*Lb;10^)|5IcEGb40 zR#-%RSYc_&9AxRj*^VNp6c*1WMTe@b0yev-n6RqI)NZV#c~_`2 zUjGl73n zf+`52Br!pn2ikBy9vOnTA|*3Ok|Kx|z%r^Jlt@ypAk~02tivNi%;*rzlF+b$q?y9g z7*5C(BgPJnNe?KilOq}-ON?ahBV_J{Dp1A&LSvFL=^&wr)DJSTpU{k?OyIJagjj}I z>c*%WNxoVjQ#7hr$FZjWJfVu@IP3tSO0{>lG|?b5Y$ne7>w2#r(ff%Jy=ArcL_-X{ zX_E?@1aeh?uL2*fVT67o*Ee`bg&F*4upC>cVLlab`XxM%q4Kpsiz3DhXAELj!60a% zL};N#JYzUVJUUtkcO`j@&0*kuKs-~Dcg_$ey)(pHsq!S%2PRmB+bv@=Buj2)p5^T& zW~(p;u@g&~WLZ9Tq4@`_8$uLG><}ho z8-JTAJ@rneWUjSmN`baa$zrpgwVxPlH@1jN$7f2_V2v|=Vw?hvI^&f3E1A+-Tc&hZ zZNG5}{Yg{XvW<@xIySkD5ouPNv_`x`SZQ3C<`uL_F3ww=ZCtQi8ug&GrS=Qs>mM3l zKUtnBZQoiePKJ{^;gHB?;rSi6Z8kgp8@zDa)#@)Pp4ZIhfEm#oVg{*L$R1a;Q8GXH z&@H%Qn7)O3cW7mMqVD2Dfo-W__U{#!xDR8@o!Z>6L! z+WB6>?Ll882D7>%u?!u;it^h)nkA(&w#t*3F)aiou~FCIY|SIiH?Yfz(IYf2CnfoXSAc7D*a-T^I(#$eCw15k`cw2#i@;_B zFVM;FNzv;3|KIUl3j4J4Zbi+-O05D8VSg%+73JhavAu!1OQ4d)}xi= zs53YgSUYHKCzHMXz_h!m5Izh%klcpU{|(?XkRwHN`^SMhPAGz4ESAnZw`=;dh61~1De=a8`1IK_#PUB4hejI)1yGZ^zNS}r20c>FN zfxC6_DC2U~N9yk+jPa>I#cvI;_I~C9Zvdt}T7XLSy}+dyPm5m*@HzNHE|R^izxM4_4vXNw@jdBxY)K=q@s~bEnzw8bK(k zp2g{}I{a>IX{h%Gye0fQix0DQ9g*dwi>nsP2;Oq%O1Zpj7$gCdbyPJYahX+s3Ov;)>umR0-*yUDAb78or|>R`zrYFnAf9tx4Ror?)>eIo&1``!jX{?iZP2f_^%}*u zhmHGYLnN@xJ?@q|xw*yNqJ`ql)A~ppy>8a@}#6lU!lcbO=^u3@m9o2|RdXz_(z%b=v zt*Dudspox-iI((U)Zt_bW%q)o(IoyW^d@OWbh2eSn)DKIg1#AA(QG^nhDMX@r#KSc zr(TUrn5M<-dn7HFyLvEsKC9YeDR_6WTh;~Cq{d#Ddh?_Uf3cm)6e diff --git a/testnew/avr328p/out/register b/testnew/avr328p/out/register deleted file mode 100755 index 9e1e67b8dcc0baabda01972ab86f17e1f61f41c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5708 zcmb_geQ;FO6~FgA_QPGWBqWL$AR(YwYj>A`O8r0}EF|R9d{~+)&)sB67L)9{y9r|J zBw?8r?FWg;lTjH%vD%U8SQV7Ew8CpE+7D`Gbf(j>qlGuVp?~AndKO z1KP9TQYGFj)Gp&bBVojiKBL#@G43_C88M^V=rXn%QKQr7Fd|0SxW~|pEymr(UB)+z zcH`@YTR$-IJU=vXoIf>@C>UN?v~+agi#f@y`^HPz(-R{Fhf#ktF;p-LhFgD|?-`pI z^NnA}j*b3w^nlPm1;&f0WdGrNSNRW?9xeTh7aTuWcC_rDWm9Db<{fgq@A|}5e)d4= zA@BR%PrO^pwwLWLd#voL@!0u$^n^a7kLXYEpYUJtH@F+}5OiUEuyIf0M59}G`1gLg z=wmkS8}DLY`^+`z8xJwp1$DCF1*_$zF5D#v9VDDn?}FmluL~M%)BG6!n4nm z9`Vv>?fSFlX{2BBlNe?1r!M~$@ame}{@G>l`EB@gOs@WTL?6~^R5Jp%UXP^0ql`-caD4Z2G-jXGXHV@i_Y(=X*!SUS&gLzh#Awyo&l7%VdYfeq*5%Y*?V7 zu@kJ~(Y*h6N8cFDkGy!=$U~zi*ii7)zaAQm_ulYO8UPWhzvkzs4KGfgyjsJ}e zzwa9_=R3tSBc2Z<>TR2+Ryo5x;eX zxrCmv61035pH!4xd>>av%GZ;kjekOoN~B?-P^q7?j~^yZt58`S@?df@f^(RkAdY6| zT$|%u5S$Zyjlz4j5#@T*%`9b?*bcZ+*iL#vLGoA7?u8^)7O9||R6bC!CaPfKD|kOt9GcUl+eEtSEFEJvGU!@K z=e2aFm9xa#Lb?W1rv-cM7ve`Ao zx6fuwbuh(gs%naHQUO{Ff{vBbpmQlxeXG4*FY;H+RiD>OuJ8g2psy(=u*yTzxF~`) zCq=+68A0AD8>6&{&4Tk!eK=IjQC@OxP>RXI^)I)9DSKn1%-(6elt^f{Xx~RP^;8b58 z-04*R!2C}2r9nJSvQ4#JRFt_0VmAg;*!6f`6qer~z+X=cA%zE$D=JqdM0|*t;+s^| zO71CHzD=FIslHa-;`fx)Dhj;7c3QzG+*2Ho3Uu&r&*g#7ErQq_k971Vre`D2mWn1* zfpm8yp6rUI0*PdN8}_+W0I32wkdCI(ebMa!D?)uJ zV}0r6H?k$^?pTVgZ)^^-NIc%dHiUw#zNxA{$eK4-1z9US+A25WvA!9mwkCSe)(`u- zRf1ImRrBUh1F=bkKBQ_DDsbC_mDHPb)N>u4O^tN|vFHeLhyv*AUs)BLE=e3t+}44H1=gqwg*!2SR*#TO)hXsOWqsUd9hcPC-n z`|A~a8r0o_9I`j~ z7Oi%K7M?;e+rrAEbbfFE8G5fM&L z9AA6UzD{8I-8a3HY0GoXX`(lM{K=k}zR5#${W83|#;V#&gePtc=3NM0Y#Brd_}EOw zdo5q`CSgTN1BgRhrUGM`c`#o-%{PDP(6pACjSXvC+nPg{h(Ub0TCc(kLcR;iL+)jY zyP8JJAr+(d-_{ap{-1u$q{tMRqgV-)E0}3fN+zQv3zzw&4G;=7H8<8@B3|3d(XeYjhTedCKfN~rnFVf;Jt!C=_6bg z$-4szDU)pn{ztOJrjX*@7B5I7lzq7BbxR{KiB!9-7L6#gJdE8c0b1FGGA(5?uK|xf zt7Vb43=~o(+t0zHvq~0eqt=!N_DAr74%|JUr`*!}pnh~CMapvJ!W_o-*c8%V(G1>q N@wrU@Hjzd0{tFpKiW2|; diff --git a/testnew/avr328p/out/simple b/testnew/avr328p/out/simple deleted file mode 100755 index 78ef774b0ab4d14a4655c86e4b564a4395e0b4d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2940 zcmb_eO-x)>6h800(!vZ(fT6S%6l$SVV`glt6>V&X(gBgb%AYRK%M3hW2=n864+B^dTHzsbn>B2Qz7mczuX8g{5@6J4aG%P%M=bis^&%O8D``#z% zkpaUnNP|g}#8NNtC7@SFRHOJ#=+99D)hqiHbQbHn(nV-`%d=YU=9v@rysc+5Yz7 zorkge?G(FDRJ-NBH@9lHPGAfZNOTo=2AI#}3M^AU&{XP=z`Y6-BAZzdIp+h)Kyp`X zyCmjItJJM*xkApPQN^y=^Ip+$!4q8u`XiWXX-qn%^hC{|MlYqvRIj_8*H~d1uQ0I& z@vbpx1H@FL>u?@|t5M;g05e51WZvzZ2X9<7R+*SHG|Rdo3(p5SqD!pfq((H*&0@i! z`;2vCzRp@^0Z)_B9gEjkvBslqu?N@cn~Y{?%>*%%ideDNqL-sR^+WNi^+Z+|S+Oh8 zXq0331x_D5RN%`9Ht95{F#d`);H?^pYaut6FRj=Kr z3f}okRHGrP;vFr@IQ4I`Lr{{SpGJa%y~~MYSO-wuS0+1xkN} zcFGOAJa)>bAgfJR`knGwP@cOFJLM#pD_TT6-&?PT|PoQD@uWShRuMzwAnB`!b z*#CEkDPSv*^ZyA-^r?EY|KE!9bF%#yFLo#&-yO41aZ0wgvptl*7jn3sfj#jPkasiz~d7~QW*eT#*do=i{tXS`p#o{67L&C}+2 zVrkOp8x!NB2aK%NK?e?CpaXoS((g>|Q&Ym-$a|SAsOR`}NposH5^Ctgf}LGm6s6T{ zA(OXV3glej{i5bG*{ox)X^D4M^T?-JB=9y$)dWtafbWQE)kD47;Kl8#Z&m*1ngePG z+S>o}LTRx9XXSx*2&ig#@I7n}+1M`|lC@3!%Y^i;Fz~&jLHqSXp?S7FhTv$YknODy z&*tkme!nmifX?wQWaeKC^mUlfoq%V;HpZoZf++YBeq6H#oo^iq&9m(h{2H}W$i_bY vjo=%%;nxY|pCZ0Dd7U{9zry|+gDSvJ;giq+nr(s+;T3p-%kOqYs@C)m9(d7Z diff --git a/testnew/avr328p/register.c b/testnew/avr328p/register.c deleted file mode 100644 index 7ff51ab..0000000 --- a/testnew/avr328p/register.c +++ /dev/null @@ -1,29 +0,0 @@ -#include - -struct UCSRA { - uint8_t MPCM0:1; - uint8_t U2X0 :1; - uint8_t UPE0 :1; - uint8_t DOR0 :1; - uint8_t FE0 :1; - uint8_t UDRE0 :1; - uint8_t TXC0 :1; - uint8_t RXC0 :1; -}; - -/* USART0 control status register A */ -volatile struct UCSRA *UCSR0A = (struct UCSRA*)0xc0; -volatile uint8_t *SREG = (uint8_t*)0x3f; -volatile uint16_t *STACK = (uint16_t*)0x3d; - -void init() { -// *SREG = 0; - *STACK = 0x0AFF; -} - -int main() { - //init(); - UCSR0A->U2X0 = 1; - //int a = UCSR0A->RXC0; - return 10; -} diff --git a/testnew/avr328p/register.rob b/testnew/avr328p/register.rob deleted file mode 100644 index 2957c0b..0000000 --- a/testnew/avr328p/register.rob +++ /dev/null @@ -1,84 +0,0 @@ - -type UCSRA { - MPCM0 = false; - U2X0 = false; - UPE0 = false; - DOR0 = false; - FE0 = false; - UDRE0 = false; - TXC0 = false; - RXC0 = false; -} - -type UCSRB { - TXB80 = false; - RXB80 = false; - UCSZ02 = false; - TXEN0 = false; - RXEN0 = false; - UDRIE0 = false; - TXCIE0 = false; - RXCIE0 = false; -} - -type UCSRC { - UCPOL0 = false; - UCSZ0 = int2(0); - USBS0 = false; - UPM0 = int2(0); - UMSEL0 = int2(0); -} - -/* USART0 control status register A */ -register UCSRA UCSR0A at 0xc0; - -/* USART0 control status register B */ -register UCSRB UCSR0B at 0xc1; - -/* USART0 control status register C */ -register UCSRC UCSR0C at 0xc2; - -register int16 UBRR0 at 0xc4; -register int8 UDR0 at 0xc6; - -void start(int16 baud) { - // set baudrate - UBRR0 = int16(((16000000 / (16 * baud)) -1)); - //(((F_CPU) + 8 * (BAUD)) / (16 * (BAUD)) -1) - //UBRR0 = int16(((16000000 + 8*baud)/16*baud)-1); - - // use 2x - UCSR0A.U2X0 = false; - - // 8 bit - UCSR0B.UCSZ02 = false; - UCSR0C.UCSZ0 = 0x3; - - // no parity - UCSR0C.UPM0 = 0x0; - - // 1 stop bit - UCSR0C.USBS0 = false; - - UCSR0B.RXEN0 = true; - UCSR0B.TXEN0 = true; -} - -void write(int8 c) { - while UCSR0A.UDRE0 == false; - UDR0 = c; -} - -int16 main() { - a = 0; - if UCSR0A.UDRE0 == true { - a = 1; - } - start(9600); - write(65); - write(66); - write(67); - write(10); - asm "sleep"; - return 0; -} diff --git a/testnew/avr328p/runtest.sh b/testnew/avr328p/runtest.sh index 63b8505..7d46083 100755 --- a/testnew/avr328p/runtest.sh +++ b/testnew/avr328p/runtest.sh @@ -1,3 +1,21 @@ #!/bin/bash -#./run_avr -f 16000000 -m atmega328p -v -v -v -g 1234 $1 -./run_avr -f 16000000 -m atmega328p -v -v -v $1 +CMD="./robcmp-simavr-debug -c 16000000 -m atmega328p -f $2" + +GREEN="\033[0;32m" +RED="\033[0;31m" +NC="\033[0m" + +echo -n " $1" +make -s $2 &> /dev/null +if [ "$?" -eq 0 ]; then + timeout 10s ${CMD} &> /dev/null + #./$2 &> /dev/null + if [ "$?" -eq 0 ]; then + echo -e \\r${GREEN}[PASS]\\t\\t${NC} + else + echo -e \\r${RED}[FAILED]\\t${NC} + fi +else + echo -e \\r${RED}[BUILD FAILED]\\t${NC} +fi + diff --git a/testnew/avr328p/runtrace.sh b/testnew/avr328p/runtrace.sh new file mode 100755 index 0000000..6a76ccf --- /dev/null +++ b/testnew/avr328p/runtrace.sh @@ -0,0 +1,2 @@ +#!/bin/bash +./run_avr -g 1234 -t -f 16000000 -m atmega328p -v -v -v $1 diff --git a/testnew/avr328p/simple.rob b/testnew/avr328p/simple.rob deleted file mode 100644 index e271ea6..0000000 --- a/testnew/avr328p/simple.rob +++ /dev/null @@ -1,5 +0,0 @@ - -int16 main() { - asm "sleep"; -} - diff --git a/testnew/avr328p/uart.rob b/testnew/avr328p/uart.rob new file mode 100644 index 0000000..efadbad --- /dev/null +++ b/testnew/avr328p/uart.rob @@ -0,0 +1,17 @@ + +use serial; + +int16 main() { + mcu = avr5mcu(); + + serial = avr5_serial(); + serial.start(mcu, 9600); + + serial.write('A'); + serial.write('B'); + serial.write('C'); + serial.write('\n'); + + return 0; +} + diff --git a/testnew/general/Makefile b/testnew/general/Makefile index a98afa3..8c80588 100644 --- a/testnew/general/Makefile +++ b/testnew/general/Makefile @@ -4,8 +4,11 @@ ALL_TT=$(patsubst %.rob,out/%.tt,$(wildcard *.rob)) ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) ROBCMP=../../robcmp + +ifndef OPT #OPT=-g -O0 OPT=-Oz +endif all: out ${ALL} diff --git a/testnew/general/out/bellmanford b/testnew/general/out/bellmanford deleted file mode 100755 index a42e6da98d3c29f75b485be06c4055c992d37905..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33088 zcmeI*UuauZ90%~<$xUX()H{Vqr=mf{x;?b(wAi9-i6->~TNk>5+g^^Txz}c-S#57| zLpn0!9`X=Dec6-v=9>r#`VOFS2McX1Rr`kS2hujwEBm&bSWbt#S{$N2i%>UgERI9|F? zDRD0C0S>8S=gp}D_sl*0&U-Vzf4r~q(RW9AEX5J5X_(Q6{bR8wb=o@2oxeWGxv_6e z=2_w2y}!x#%KGJ;tl27!^1rFtt%d73d11|SmdBnORq4s_Uz^v z-JE=chq897<7TJ7zBrk0+?c!E_72V2t%V~aIlDD`-8EP_X|ba9pxR?&Ea?D zi*9n=Z}EYy-%5D*+O21g>fTrG^t5i~W8P0&v5EHStHIvo2mRTI`g_@jEc@MgkG3D5 zhI^JJm;KF2-k-cb-1*FD&{U6NaTT+a6;tt;6-!u3#jQW77wamrN29;!a`X^@00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009X6Hv%c1HhN}&d_(YVbUFHmcgib6cgh0? zC}EbDjC0<3b=`B!l2a@>tCU!DDwXA8)jhXbqGP4<8a@BoYH?+W=9i1*DxI>Zy+LvM zpr({VvvGbKy5h9PpBDXcQD$v#eBzfOUtz1@jqEaTpPvWMIgtEO$@$?152b^;`F-tv qJ`(0*VNPK_DLLOL?{k;?Q)F&azv-{vNd5BRkO@{{{8jMXM1KMJ0Og(l diff --git a/testnew/general/out/bitstruct b/testnew/general/out/bitstruct deleted file mode 100755 index a86b67886e7fa4906744757e2077b4d230bd77eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16664 zcmeI3!D|yy5XNUsi&a~blT;K96s(FQ+Iq-EjABTNRZH!mdU-U>rd@2JBpcg;kV5M{ zM=wGz-g^+wLcpun-o1F~Kj1<9=IsmFZ3X=Uz9F-3zIkt7W`68-zW+M9`^98VoE}A5U29V_ zCiJ($D2{aUzTSN_gN-S7MD@tKgPlSSKAkU0i4{yeqPk(Wod=z%uJ}0eTr)YnX(8fY$yFvEnD^ z;0y4$>3)JieDfdidF*H5K{#3)Rqd&dp0DR-7|673Tp7xxoP2+R$hP9xc=iBYj zZ{!~4P*+gJA=ovz-rp;VjA6auwDO{n011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011%5{}8C}u8m1$cUr!c&wBlO4~z8cx%AaN`*!cn*S?*jzU(fGuR0&C^X`}( zx3075YN~badK_FaR!9A**7@!<0-YCEeaq>6r?Z&kKUtSKR+q7LnUi(NA5CJ0?f?J) diff --git a/testnew/general/out/fibonacci b/testnew/general/out/fibonacci deleted file mode 100755 index 7ec8aa5ed39224eec288f3bce42dd0cbd244526c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16600 zcmeI3OK1~e5XZmWG+1eC0v4%SFv3zFNSpeA>Or%z!4!*D+iLB@k2VjQ(4>;4*rJs{ ztgr{6Ui9GEdk-SLh=o*pEC@ouOOFd}(Su$DjWfF&lBjs_;^jZ&pPBid^Zk%KGFsS3nD;~5c^3Hl9avrrSMSr`c)pSHKjKFW5(xLBq{sDgZ;Hj?ERtI zG2!N38fI~AY*OapvpFYr^4jw@&(mXQ;)A<{^Sa7%PV&{Mlrx#T$xKWpGl?mh__e;} z3(k4WfQ|EVEzU^ocZF9^_m#_Gqr3dpkaJG?U1h)FZs(e-Ii40G@8`LY5MAU>xp^1m z^s#GbA)lv&f4e2}N69ykdP&vB^Q?cdJ+vu6Y9w{cOlLbLlj9w+xycyiYzIkP$NQ&4 z*_Zmc!cyDo=vU*}wUaa!AUSVpq5_)i*seplc%c1AV=v_0Esx_ri{vZLoGqrIJ!KKW%+370r!E zVYPmEw3ul39eQY&mslLoZ|XPn{=P_II~ZA3sMA=b-sy;GXxf^go$!kEfs`Vx7j%wU zOsUd(&e7YHM_NxP(#?0NI%z$!!?l!GTKDX5HPtMwJG^v6YcwY{zhUOIX2ZO%wHRhh zYo+r8sV{?(g_Yc1-I=Aq}85# zq`Bvv`p0d(a{H+{=ici^+Ud7*_0=u9py zC*otVcvg55$?>VoSTvdx!Sq-%BhGll<~$X!_<*;NZO-$JPEWT_aXP{I-hCt=1?4{e X!*0%f;XEIp4*lQnla>3VeV_OVJCewl diff --git a/testnew/general/out/itoa b/testnew/general/out/itoa deleted file mode 100755 index 75cb5a02de39c2d71e0ad60f0b234f23fdd1bb4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33248 zcmeI5U1%It6vxjb8=Iu9la^X6ipi5!VUztxHi;zdY{}Lw37XniZA*LI?9PyFvI!&` z(m+2}lRy$#=|f)xA4Eias1QWzTe@x}Eq#gfsVZvT3ezb7p4AZs?1?DgOg! z?)=X^_sqS&nb&(~?ayBeJBYMuBC29`Dzp-WsS(vBw*gF>-Ychs9-XVoIgW3u))x(UtWY4)J2R<3o2+qCH#bA~NMt zsmal)5KKy0y-p@Ibh%&v5FL*0sGA{-t*yqm)X- z(lNPnOsU7$%a;<2ZR;$>-BzjiSSmF(S_*Hkmp7dG?JXs6>msxx<@XZU`Y!s8z1kb; zIaYe7nQiN2Ew=6!kfyv=D^W(iIe9A`+yq_S!TKZC!uo0U^$bxxx0!c{-sW~Edp~=* zNx%5Nu_t*@6Z!vOZ|HpqFQcWbhYq;fdB}A00@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p z2!H?x{PziDkN(#6`$X+(%_p)8b;X)1rjIZDVLiHM>Csz;e&eD4ZZx}lo;&-pH8*+J zt2LMF)0gk04_F^qj|x%!=G`NU`>Mk8`|84luX`5mZ2rVGruTU%0)wZZ+$Tvo>eF zv4?1QZO4)(b836QlZj@#&v5gZmTu%p5L!#XXD=pzZpJxqJK&2%Xa6up8tpQ^=HpFgwOFDx}r0G)lY@O`d5b+ z?r(ftC>9rf-smkBi`@5=M0*w$(m18rvsy1^EztwN#X4bXn%r~`X z!so*3>m{H)4c78_CfLn6G4-U`h9V}T3p8K@8o``lzmG9pC~(p>~w0k zEXyu}3kZM!2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x{0|5;@fu2J z2gq{doPm;gN;lhEO;Md3JU}~CYDk$E%=l#5R6}MgVUAPHU~Izl)A9HanaT86jApe| zEICRG+UR6z&>Wwj_qB0zVsa!+*EA0;W%!X*KI#q8DG&eRT_e8Qu^6W+Gd}F6scOny zva`lRbfuaym-%dis~7o_yUgiVIo(5f9_rZDi%XheIR8@DHTgrjv#$Nz>U=1I&v5i} zuFkkx{--YeIE}G->6{L2^)x>8kh?b)kq+iZo5FK%~{NG)4uV}8Ma&A3&xL$w7-*46Ttcb_3O|dqbbG>Z0 z7yJ;{^9`2J3=Y^2jqzx3!*kU3tD$rK?u)#ey1e`J84iB0??aJ~3}}qYTEb5KIplR` z_3rKD=4#n%E7Vo?Rjz~LI%}?STrk_8=2^>Z5zBlLFCxB*m^I8m&k@sqhc(7J4y{2| z<2m&&b{dyrXaZ{Xcea~b`DQcS+e#7BW+B#bn7lujUs?L`X8iTHx1SHbT*qDvg`Oty zK_54~_I9{tnTw7S!`#Z>N`a=9cGBSH6jt zU>6|fZ@0`&V!d3%B0az2{#)0iFi;;cH2G3Tx)aC6$<=I+p9xST1cXklhM_~jgZh$_#> z*(pC%KH@rUm+fXx`n}AxvyC*{wz1Ae-nH`$8@w#8ln$>D=8Ch-5v J=X^dK+b>MnU*iA( diff --git a/testnew/general/out/simplescope b/testnew/general/out/simplescope deleted file mode 100755 index f8b3a6d8394ea697a741e0dd5dc6820b51229250..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16560 zcmeI3KTi}<6vgkb5K%#>h(?Ps#=ixtVnN4hoG8I4Q3}`Q1)MQEgk25n2B@H+x3{&h z+`_`r#1CNWCondC0Sn_f@6BXq)XG?%o1A&~zBljgy}#M^e*W?O=P|RWVP<2{4DjuOP(c@@xJjd;@8ag-V?dHAI<-Hd#aqxS6?~8n7Kx16i5_am(5w8c! z4_A`A%Vn>vP*>Skxekl#thvhZmf7Jf&st`SSQd(S5%G1ztl>2D3NiiHSYxawp;f4A zJg5G}PT^7vO+n4U&USMv-)N@$TPb4NS%`JK`LKCnGgUb*o0CiY?|^fZkR zGVOi;U7~j58qR!wSZP<#AM@~gRgJ&P{&~h88tG;H9imY!sOQQ4PCx6;-SZe{2cYUB3X6id^G2$F+1+XS#=s?&RtL8=B&TX-I2v`Ia5y2!pwH?%Q^ZGRi2Tv z<9?`o%ym01+smF0`kCuw>uI)a6W#T^XBQhbJSeV|4zJ8aVe*^5Gw0(_H{%!+_DT5NH)cH72&C4XqD+ktoFErr07SP)r#DEX2k~ zM3N>hUAcAPh81Di$fm56m99+Ok)T^460GOUBb^dVbm8v5$>GkqcjorYH*D|Bho9en z?IY4^iKvFd%khwt=j7)jq9Yt}4yA5HdSipJTi0c@x@pzvo|&w(&Y@I)>~4ScDaQ5T z>M^qNIv$pg+N3F^r)PBY*vzZf3tZxx;fWX4DU!P?r%RG|rbb z%hq~gAWd?+7IUQfuiWQr4yB@z{)l5PY}RGp*X~~YC2UKjQb|2ox&BY<`R!A}m22%G zXJ2`aR}+0#V$p>C4D!3`;@oIfA=243$#@r0Uj9c!F~r?jD-UrlMq+cAW1e$)ZlAe7 z$$cZo4Gw3spRIH3Z;ub~iGB_@N9WXJu5&Ci)R~$cOK~pk7>Cqx`QC%zk5c!ich}U- zCwIQQIm2Uq4)dOx7`@3j7JJeLYEN@#+@Iv!xc0oPljrB|Z1THu|1u}{T$^g++tDhu za6PwYC-wArM^6XWl^NobxSimT_49e62JTN;xp<*L00Izz00bZa0SG_<0uX=z1Rwwb z2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$## zAOHafKmY>&CQ#@tdzMPU;Q(D+%jI&g7%wzsWu3yIY3ZJB zdG+S-LRUlhLYFsQ2y6Pc;bo0BYJ$aq6=ToxajSG^FME+?&pYqaHbVBROOssoIJ@~u zuW_}E618sElRFjiweM`Y5BlmGH@A1FzP{1TiLbRiWN)W7PsU#eKmY;|fB*y_009U< z00Izz00bZa0SG_<0uX=z1Rwwb2tWV=5P$##AOHafKmY;|fB*y_009U<00Izz00bZa z0SG_<0uX=z1Rwwb2tWV=5P$##{+ocGSGM05AV1>#-n&Z%_G+4<{qnK_s#D`5Dm|0F zKc%PDNIIEH=cq18!SQ4!OWirTI60BismH~iJlFUY1o_A0qF2V@;vCW9ocUFFS<0iC zUtX8r_em}x6 zfcx;z2%bp_k;rlQHMlX8nX%m6+^q@Cwp*fI?yK~jA8=!)bGN74kJ$U^_MAA~g|xcX zre;hOEJtx1>-P8VUqLh2m~ux{cQ%i!sI^LCDy1i3sbIoV@ewxm*7w%Erwr6oH)@G9 z?Vn9vH^y&X&s`mF^qP+AYV_4u=Nvp;TxcJ>BvR|sC@nII<)YK0(2LMo!!h^JBbD;f$b6U|DXh#Fpw&*mwT?Hhzpi~*yZmzVdu`~` z=lOacStmAK|NC| z<>J(-TMQwlk9Fu6zl%hL`Tu{{jD)C@nO4IPd{JnXgN@S zpX?UFmBth2-)-AD>VAi_b=CQ3op;CVxOJUXS5vKX*FCt|XK!n^X(@!~oNG3o+14n& z7e{+O6Gr+y`L>F&?AaiauCNqFa@3Pw$aH1~r8_$)IkPZlg5}^rB?`=3FjEMYWOiXD zEXhMpYE`_hSJU?Dy>bwlVi;huJnzYR6&2U3@yNGqRPjZ9YBu4cz{Z^aL6oI>5xr{N zN1U!Xt#jkLzwUI(>AKTrt&S(r^?t_fZ|t5onL(`*i>=dSW0~ER&BDz-{Tkb^`~?8z Bn416q From 0efc244a353f5a4f2b9c6782dbc6f85d80efe4de Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Fri, 11 Aug 2023 18:27:24 -0300 Subject: [PATCH 028/117] Fixes and impls to build robcmp on Windows, using msys2(mingw-w64) Howto: - Install msys2 on windows; - Inside msys2 shell, run: pacman -S bison flex git make mingw-w64-x86_64_{clang,cmake,lld,llvm} set PATH=/mingw64/bin:$PATH git clone https://thborges.github.com/thborges/robcmp git checkout add-debug mkdir build && cd build ../winbuild --- CMakeLists.txt | 3 +-- src/BackLLVM.cpp | 38 ++++++++++++++++++++++++++++++-------- src/BackLLVM.h | 19 +++++++++++-------- src/BuildTypes.h | 22 +++++++++++----------- src/FlexDependencies.h | 7 +++++++ src/FunctionImpl.cpp | 5 +++++ src/HeaderExternals.h | 1 + src/If.cpp | 3 ++- src/Language.l | 12 ++++++++++++ src/Load.cpp | 2 +- src/PrintAstVisitor.cpp | 22 +++++++++++----------- src/Program.cpp | 4 ++-- src/Scalar.cpp | 4 ++-- src/Scanner.cpp | 16 ++++++++-------- src/Scanner.h | 4 ++-- src/SourceLocation.h | 12 +++++++----- src/Variable.h | 2 +- src/While.cpp | 1 + src/main.cpp | 2 +- testnew/general/Makefile | 13 ++++++++++++- winbuild | 1 + 21 files changed, 129 insertions(+), 64 deletions(-) create mode 100644 winbuild diff --git a/CMakeLists.txt b/CMakeLists.txt index c234ba6..c0bb193 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,8 +60,7 @@ add_dependencies(robcmp parsers) llvm_map_components_to_libnames(llvm_libs support core irreader passes armasmparser armcodegen avrasmparser avrcodegen - x86asmparser x86codegen - xtensaasmparser xtensacodegen) + x86asmparser x86codegen) target_link_libraries(robcmp ${llvm_libs}) diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 0504cdb..d14c08e 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -1,4 +1,5 @@ +#include #include #include @@ -42,20 +43,41 @@ extern char *build_outputfilename; void print_llvm_ir(char opt_level) { - InitializeAllTargetInfos(); - InitializeAllTargets(); - InitializeAllTargetMCs(); - InitializeAllAsmParsers(); - InitializeAllAsmPrinters(); + if (currentTarget.backend == rb_native) { + // Native target init + InitializeNativeTarget(); + InitializeNativeTargetAsmParser(); + InitializeNativeTargetAsmPrinter(); + } else if (currentTarget.backend == rb_avr) { + // AVR target init + LLVMInitializeAVRTargetInfo(); + LLVMInitializeAVRTarget(); + LLVMInitializeAVRTargetMC(); + LLVMInitializeAVRAsmParser(); + LLVMInitializeAVRAsmPrinter(); + } else if (currentTarget.backend == rb_arm) { + // ARM target init + LLVMInitializeARMTargetInfo(); + LLVMInitializeARMTarget(); + LLVMInitializeARMTargetMC(); + LLVMInitializeARMAsmParser(); + LLVMInitializeARMAsmPrinter(); + } else { + cerr << "No backend set for target " << currentTarget.triple << ".\n"; + return; + } std::string defaultt = sys::getDefaultTargetTriple(); supportedTargets[0].triple = defaultt.c_str(); SubtargetFeatures Features; StringMap HostFeatures; - if (sys::getHostCPUFeatures(HostFeatures)) - for (auto &F : HostFeatures) + if (sys::getHostCPUFeatures(HostFeatures)) { + for (auto &F : HostFeatures) { Features.AddFeature(F.first(), F.second); - supportedTargets[0].features = Features.getString().c_str(); + } + } + static string nativeFeatures = Features.getString(); + supportedTargets[0].features = nativeFeatures.c_str(); TargetInfo ai = currentTarget; diff --git a/src/BackLLVM.h b/src/BackLLVM.h index 3c90d10..f36bbcf 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -5,7 +5,10 @@ extern std::unique_ptr> Builder; +enum RobBackend {rb_native, rb_avr, rb_arm, rb_xtensa}; + typedef struct { + enum RobBackend backend; const char *name; const char *triple; const char *cpu; @@ -16,20 +19,20 @@ typedef struct { extern unsigned int codeAddrSpace; extern unsigned int dataAddrSpace; -enum SupportedTargets {native, avr328p, stm32f1, esp32, __last_target}; +enum SupportedTargets {st_native, st_avr328p, st_stm32f1, st_esp32, __last_target}; extern enum SupportedTargets currentTargetId; #define currentTarget (supportedTargets[currentTargetId]) static TargetInfo supportedTargets[__last_target] = { - {"", "", "", "", tint64}, // default target - {"avr328p", "avr", "atmega328p", "+avr5", tint16}, - {"stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, - {"esp32", "xtensa", "", "", tint32}, + {rb_native, "", "", "", "", tint64}, // default target + {rb_avr, "avr328p", "avr", "atmega328p", "+avr5", tint16}, + {rb_arm, "stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, + {rb_xtensa, "esp32", "xtensa", "", "", tint32}, }; -static void initTarget(const char *targetarch) { - currentTargetId = native; //native - for(int t = native; t < __last_target; t++) { +static void setTarget(const char *targetarch) { + currentTargetId = st_native; //native + for(int t = st_native; t < __last_target; t++) { if (strcmp(targetarch, supportedTargets[t].name) == 0) { currentTargetId = static_cast(t); break; diff --git a/src/BuildTypes.h b/src/BuildTypes.h index f393819..cc7fd6c 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -65,53 +65,53 @@ class BuildTypes { DataType getType(const string& name, bool createUndefined = false); - const char *name(unsigned tid) { + const char *name(DataType tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].name.c_str(); } - const unsigned bitWidth(unsigned tid) { + const unsigned bitWidth(DataType tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].bitWidth; } - Type *llvmType(unsigned tid) { + Type *llvmType(DataType tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].llvmType; } - DIType *diType(unsigned tid) { + DIType *diType(DataType tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].diType; } - DIDerivedType *diPointerType(unsigned tid) { + DIDerivedType *diPointerType(DataType tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].diPointerType; } - SourceLocation *location(unsigned tid) { + SourceLocation *location(DataType tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].sl; } - bool isIntegerDataType(unsigned tid) const { + bool isIntegerDataType(DataType tid) const { return tid >= tint8 && tid <= tint64u; } - bool isSignedDataType(unsigned tid) const { + bool isSignedDataType(DataType tid) const { return tid >= tint8 && tid <= tint64; } - bool isUnsignedDataType(unsigned tid) const { + bool isUnsignedDataType(DataType tid) const { return tid >= tint8u && tid <= tint64u; } - bool isFloatDataType(unsigned tid) const { + bool isFloatDataType(DataType tid) const { return tid >= tfloat && tid <= tldouble; } - bool isComplex(unsigned tid) { + bool isComplex(DataType tid) { return tinfo[tid].isComplex; } diff --git a/src/FlexDependencies.h b/src/FlexDependencies.h index c59fe15..e2ada18 100644 --- a/src/FlexDependencies.h +++ b/src/FlexDependencies.h @@ -1,6 +1,8 @@ #pragma once +#include + #include #include using namespace std; @@ -21,3 +23,8 @@ class Field; #include "Colors.h" typedef void* yyscan_t; + +#ifdef __MINGW64__ +char* strndup(const char *src, size_t size); +#endif + diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 8240b06..25a07fe 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -39,6 +39,11 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo func = Function::Create(ftype, Function::ExternalLinkage, codeAddrSpace, getFinalName(), mainmodule); } +#ifdef __MINGW64__ + if (name == "main") + func->setName("__main"); +#endif + if (isExternal()) return NULL; diff --git a/src/HeaderExternals.h b/src/HeaderExternals.h index b3d471a..c8b8004 100644 --- a/src/HeaderExternals.h +++ b/src/HeaderExternals.h @@ -11,6 +11,7 @@ #include #include #include +#include using namespace std; diff --git a/src/If.cpp b/src/If.cpp index 1f408fe..edb752e 100644 --- a/src/If.cpp +++ b/src/If.cpp @@ -7,6 +7,7 @@ If::If(Node *e, vector &&tst): expr(e) { addChild(expr); thenst = new Node(std::move(tst)); addChild(thenst); + elsest = NULL; } If::If(Node *e, vector &&tst, vector &&est): If(e, std::move(tst)) { @@ -56,4 +57,4 @@ Value *If::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbloc void If::accept(Visitor& v) { v.visit(*this); -} \ No newline at end of file +} diff --git a/src/Language.l b/src/Language.l index 5237d11..097da91 100644 --- a/src/Language.l +++ b/src/Language.l @@ -166,3 +166,15 @@ void update_loc(location_t *loc, int lineno, int leng, char *text) { loc->last_column = text + leng - strrchr(text, '\n'); } } + +#ifdef __MINGW64__ +char *strndup(const char *s, size_t n) { + size_t len = strnlen(s, n); + char *newstr = (char*)malloc(len+1); + if (!newstr) + return NULL; + newstr[len] = '\0'; + return (char*)memcpy(newstr, s, len); +} +#endif + diff --git a/src/Load.cpp b/src/Load.cpp index b1b3f2d..856e06f 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -38,7 +38,7 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); - Value *alloc; + Value *alloc = NULL; if (ident.isComplex()) { Identifier istem = ident.getStem(); Node *stem = istem.getSymbol(getScope()); diff --git a/src/PrintAstVisitor.cpp b/src/PrintAstVisitor.cpp index ce5bf1d..e175198 100644 --- a/src/PrintAstVisitor.cpp +++ b/src/PrintAstVisitor.cpp @@ -12,7 +12,7 @@ template char* get_typename(T& object) } bool PrintAstVisitor::before(Node& n) { - this->os << "N" << std::hex << (long int)&n << + this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "\"];\n"; return false; } @@ -26,8 +26,8 @@ void PrintAstVisitor::visit_children(Node& n) { // print an edge between n and current child, // using object pointer as an identifier - this->os << "N" << std::hex << (long int)&n << "--" << - "N" << std::hex << (long int)c << ";\n"; + this->os << "N" << std::hex << (uint64_t)&n << "--" << + "N" << std::hex << (uint64_t)c << ";\n"; } } @@ -48,7 +48,7 @@ void PrintAstVisitor::visit(Program& p) { bool PrintAstVisitor::before(Program& p) { this->os << "graph {\nN" - << std::hex << (long int)&p + << std::hex << (uint64_t)&p << "[label=\"" << get_typename(p) << "\"];\n"; return false; @@ -59,17 +59,17 @@ void PrintAstVisitor::after(Program& p) { } void PrintAstVisitor::visit(Int8& n) { - this->os << "N" << std::hex << (long int)&n << + this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << std::dec << (int)n.getNumber() << ")\"];\n"; } void PrintAstVisitor::visit(Int16& n) { - this->os << "N" << std::hex << (long int)&n << + this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << std::dec << n.getNumber() << ")\"];\n"; } void PrintAstVisitor::visit(Int32& n) { - this->os << "N" << std::hex << (long int)&n << + this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << std::dec << n.getNumber() << ")\"];\n"; } @@ -93,27 +93,27 @@ const string PrintAstVisitor::getOperatorName(int op) { } void PrintAstVisitor::visit(CmpOp& n) { - this->os << "N" << std::hex << (long int)&n + this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << std::dec << getOperatorName(n.getOperator()) << ")\"];\n"; visit_children(n); } void PrintAstVisitor::visit(BinaryOp& n) { - this->os << "N" << std::hex << (long int)&n + this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << std::dec << getOperatorName(n.getOperator()) << ")\"];\n"; visit_children(n); } void PrintAstVisitor::visit(Load& n) { - this->os << "N" << std::hex << (long int)&n + this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << n.getName() << ")\"];\n"; visit_children(n); } void PrintAstVisitor::visit(Scalar& n) { - this->os << "N" << std::hex << (long int)&n + this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << n.getName() << ")\"];\n"; visit_children(n); } diff --git a/src/Program.cpp b/src/Program.cpp index 5ae1ae0..de1cbda 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -3,7 +3,7 @@ #include "BackLLVM.h" Program::Program() { - mainmodule = new Module(this->file, global_context); + mainmodule = new Module(this->getFile(), global_context); Builder = make_unique>(global_context); if (debug_info) { @@ -11,7 +11,7 @@ Program::Program() { mainmodule->addModuleFlag(Module::Warning, "Dwarf Version", 4); DBuilder = make_unique(*mainmodule); RobDbgInfo.cunit = DBuilder->createCompileUnit(dwarf::DW_LANG_C, - DBuilder->createFile(this->file, std::filesystem::current_path().string()), + DBuilder->createFile(this->getFile(), std::filesystem::current_path().string()), "Robcmp", false, "", 0); // global scope diff --git a/src/Scalar.cpp b/src/Scalar.cpp index ace8196..f319f2d 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -71,7 +71,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc // variable not allocated if (alloc == NULL) { - Value *ret; + Value *ret = NULL; setDataType(exprv_dt); auto sp = RobDbgInfo.currScope(); @@ -125,7 +125,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc return allocall; } else { - Value *nvalue; + Value *nvalue = NULL; // Pointers need a custom procedure: load the stem, set the // requested bit value through bit shifting, and store the new value diff --git a/src/Scanner.cpp b/src/Scanner.cpp index 55ba833..57f58aa 100644 --- a/src/Scanner.cpp +++ b/src/Scanner.cpp @@ -10,7 +10,7 @@ Program *program; int errorsfound = 0; char *build_outputfilename; -vector includeDirs; +vector includeDirs; vector buildStack; vector buildStackScanner; int buildStackTop; @@ -26,7 +26,7 @@ int USEparse(yyscan_t scanner); void yyerror(location_t *loc, yyscan_t scanner, const char *s) { fprintf(stderr, "%s:%d:%d: %s\n", - build_filename(), loc->first_line, loc->first_column, s); + build_file()->string().c_str(), loc->first_line, loc->first_column, s); errorsfound++; } @@ -62,9 +62,9 @@ bool parseFile(const string& source) { includeDirs.push_back(file_path.parent_path()); includeDirs.push_back("./"); - FILE *f = fopen(file_path.c_str(), "r"); + FILE *f = fopen(file_path.string().c_str(), "r"); if (f == NULL) { - fprintf(stderr, file_not_found, file_path.c_str()); + cerr << string_format(file_not_found, file_path.string().c_str()); return false; } @@ -88,7 +88,7 @@ FILE *findFile(string file_name, filesystem::path& file_path) { for(auto dirit = rbegin(includeDirs); dirit != rend(includeDirs); ++dirit) { filesystem::path test_path(*dirit); test_path /= file_name; - FILE *f = fopen(test_path.c_str(), "r"); + FILE *f = fopen(test_path.string().c_str(), "r"); if (f) { file_path = test_path; return f; @@ -155,6 +155,6 @@ int build_filecolno() { return MAINget_column(buildStackScanner[buildStackTop]); } -const char* build_filename() { - return buildStack[buildStackTop].c_str(); -} \ No newline at end of file +const filesystem::path* build_file() { + return &buildStack[buildStackTop]; +} diff --git a/src/Scanner.h b/src/Scanner.h index 29f8dfa..96e6847 100644 --- a/src/Scanner.h +++ b/src/Scanner.h @@ -13,7 +13,7 @@ static const char *file_not_found = "No such file or directory '%s'."; typedef void* yyscan_t; extern int errorsfound; -extern vector includeDirs; +extern vector includeDirs; extern vector buildStack; extern int buildStackTop; extern vector buildStackScanner; @@ -27,6 +27,6 @@ void yywarncpp(const string& s, SourceLocation *n); bool parseFile(const string &source); bool parseUseFile(const string& use, location_t loc); -const char* build_filename(); +const filesystem::path* build_file(); int build_filecolno(); int build_filelineno(); diff --git a/src/SourceLocation.h b/src/SourceLocation.h index 8fef4fa..762f81b 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -1,6 +1,8 @@ #pragma once +#include "HeaderExternals.h" + typedef struct { int first_line; int first_column; @@ -8,17 +10,17 @@ typedef struct { int last_column; } location_t; -extern const char *build_filename(); +extern const filesystem::path* build_file(); extern int build_filecolno(); extern int build_filelineno(); class SourceLocation { protected: location_t sloc; - const char* file; + const filesystem::path *file; public: SourceLocation() { - file = build_filename(); + file = build_file(); sloc.first_column = build_filecolno(); sloc.first_line = build_filelineno(); } @@ -47,7 +49,7 @@ class SourceLocation { return &sloc; } - virtual const char* getFile() const { - return file; + virtual const string getFile() const { + return file->string(); } }; diff --git a/src/Variable.h b/src/Variable.h index c6882f6..a59cad3 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -6,7 +6,7 @@ class Variable: public NamedNode { protected: - Value *alloc; + Value *alloc = NULL; Identifier ident; public: diff --git a/src/While.cpp b/src/While.cpp index 971cf04..0bf481e 100644 --- a/src/While.cpp +++ b/src/While.cpp @@ -4,6 +4,7 @@ While::While(Node *e) : expr(e) { addChild(e); + stmts = NULL; } While::While(Node *e, vector &&ss) : While(e) { diff --git a/src/main.cpp b/src/main.cpp index 5d9d64a..2ed0a6e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,7 +57,7 @@ int main(int argc, char *argv[]) { } // set current target and basic build types - initTarget(targetarch); + setTarget(targetarch); if (!parseFile(buildFileName)) exit(1); diff --git a/testnew/general/Makefile b/testnew/general/Makefile index 8c80588..5efd04b 100644 --- a/testnew/general/Makefile +++ b/testnew/general/Makefile @@ -3,7 +3,15 @@ ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) ALL_TT=$(patsubst %.rob,out/%.tt,$(wildcard *.rob)) ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) -ROBCMP=../../robcmp +OS=$(shell uname -o) + +ifeq ($(OS), Msys) +ROBCMP=../../build/robcmp.exe +ENTRY=__main +else +ROBCMP=../../build/robcmp +ENTRY=main +endif ifndef OPT #OPT=-g -O0 @@ -28,6 +36,9 @@ out/%.ll : %.rob ${ROBCMP} Makefile out/%.tt : %.rob @-./runtest.sh $< $(patsubst %.rob,out/%,$<) +% : %.o + ld.lld -e ${ENTRY} $< -o $@ + test: ${ALL_TT} diff --git a/winbuild b/winbuild new file mode 100644 index 0000000..b83d2b9 --- /dev/null +++ b/winbuild @@ -0,0 +1 @@ +cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug .. From 460ce28b0498c8d0c687dede2b30e720dc043ad7 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 9 Aug 2023 20:30:59 -0300 Subject: [PATCH 029/117] Implements enum types in the language. --- src/Array.h | 16 +----------- src/BuildTypes.cpp | 5 ++-- src/BuildTypes.h | 3 ++- src/Enum.cpp | 53 ++++++++++++++++++++++++++++++++++++++++ src/Enum.h | 15 ++++++++++++ src/Header.h | 1 + src/Int8.h | 9 ++++--- src/Language.l | 2 ++ src/Language.y | 28 +++++++++++++++++++-- src/LanguageHeader.y | 2 +- src/LanguageUse.y | 26 +++++++++++++++++++- src/NamedConst.h | 33 +++++++++++++++++++++++++ src/Scanner.cpp | 4 +-- testnew/general/enum.rob | 27 ++++++++++++++++++++ 14 files changed, 197 insertions(+), 27 deletions(-) create mode 100644 src/Enum.cpp create mode 100644 src/Enum.h create mode 100644 src/NamedConst.h create mode 100644 testnew/general/enum.rob diff --git a/src/Array.h b/src/Array.h index 66efe1a..cc56d93 100644 --- a/src/Array.h +++ b/src/Array.h @@ -4,24 +4,10 @@ #include "Node.h" #include "Variable.h" #include "ArrayElements.h" +#include "NamedConst.h" class ArrayElements; -class NamedConst: public NamedNode { -protected: - Node *value; -public: - NamedConst(const char *name, Node *value) : NamedNode(name), value(value) { - dt = value->getDataType(); - } - virtual Value *getLLVMValue(Node *stem) override { - return value->generate(NULL, NULL, NULL); //FIXME - } - virtual bool isConstExpr() override { - return true; - } -}; - class LinearDataStructure: public Variable { protected: DataType element_dt = BuildTypes::undefinedType; diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index f6cee26..e1e9e8f 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -50,7 +50,8 @@ DataType BuildTypes::getType(const string& name, bool createUndefined) { return undefinedType; } -DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBitWidth) { +DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBitWidth, + bool isEnum) { const string& name = userType->getName(); auto udt = namedTypes.find(name); DataType id; @@ -73,7 +74,7 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi info.sl = userType; info.llvmType = llvmType; info.isDefined = true; - info.isComplex = true; + info.isComplex = !isEnum; info.dwarfEnc = 0; info.bitWidth = bitWidth; diff --git a/src/BuildTypes.h b/src/BuildTypes.h index cc7fd6c..72a1fde 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -61,7 +61,8 @@ class BuildTypes { BuildTypes(DataType targetPointerType); - DataType addDataType(Node* userType, Type* llvmType, unsigned typeBitWidth = 0); + DataType addDataType(Node* userType, Type* llvmType, + unsigned typeBitWidth = 0, bool isEnum = false); DataType getType(const string& name, bool createUndefined = false); diff --git a/src/Enum.cpp b/src/Enum.cpp new file mode 100644 index 0000000..756c807 --- /dev/null +++ b/src/Enum.cpp @@ -0,0 +1,53 @@ + +#include "Enum.h" +#include "Int8.h" +#include "NamedConst.h" + +void Enum::createDataType() { + if (children().size() > 256) { + yyerrorcpp("Maximum number of elements for enum type was reached (256).", this); + return; + } + + /* set enum items values + * enum A {B=1, C, D, E, F=10, G, H=127, I} => C=2, D=3 ... G=11 ... I=-128 + * enum B {C=3, D=2, E, F} => E=4, F=5 + */ + int8_t v = 0; + map values; + for(Node *n : children()) { + NamedConst *nc = (NamedConst*)n; + Int8 *i8 = dynamic_cast(nc->getValue()); + if (i8) { + v = i8->getNumber(); + if (values.count(v) == 1) { + yyerrorcpp(string_format("Value %d alread taken for %s.", + v, values[v]->getName().c_str()), nc); + } else { + values[v] = nc; + } + } else { + while (values.count(v) == 1) + v++; + nc->setValue(new Int8(v)); + values[v] = nc; + } + } + + dt = buildTypes->addDataType(this, buildTypes->llvmType(tint8), + buildTypes->bitWidth(tint8), true); + if (dt == BuildTypes::undefinedType) { + yyerrorcpp("Type " + name + " alread defined.", this); + yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); + return; + } + + for(Node *n : children()) { + n->setDataType(dt); + } +} + +Value* Enum::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + createDataType(); + return NULL; +} \ No newline at end of file diff --git a/src/Enum.h b/src/Enum.h new file mode 100644 index 0000000..151a518 --- /dev/null +++ b/src/Enum.h @@ -0,0 +1,15 @@ + +#pragma once + +#include "Node.h" + +class Enum : public NamedNode { +private: + void createDataType(); + +public: + Enum(const string& name, vector &&items): NamedNode(name, std::move(items)) { + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; +}; diff --git a/src/Header.h b/src/Header.h index f41adac..f8b423a 100644 --- a/src/Header.h +++ b/src/Header.h @@ -57,5 +57,6 @@ #include "InlineAssembly.h" #include "Interface.h" #include "UserType.h" +#include "Enum.h" extern Node* getNodeForIntConst(int64_t i); diff --git a/src/Int8.h b/src/Int8.h index 96273d7..3867bad 100644 --- a/src/Int8.h +++ b/src/Int8.h @@ -5,13 +5,16 @@ class Int8: public Node { private: - char number; + int8_t number; bool IsSigned; public: - Int8(char n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} - char getNumber() const { return number; } + Int8(int8_t n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + + int8_t getNumber() const { return number; } + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual bool isConstExpr() override { return true; } diff --git a/src/Language.l b/src/Language.l index 097da91..f99c402 100644 --- a/src/Language.l +++ b/src/Language.l @@ -42,6 +42,8 @@ ID {A}({A}|{D})* "implements" { return TOK_IMPL; } "use" { return TOK_USE; } +"enum" { return TOK_ENUM; } + "if" { return TOK_IF; } "else" { return TOK_ELSE; } diff --git a/src/Language.y b/src/Language.y index 9b0aff6..6041b48 100644 --- a/src/Language.y +++ b/src/Language.y @@ -12,7 +12,7 @@ %type term term2 expr factor stmt gstmt condblock whileblock logicexpr %type logicterm logicfactor TOK_AND TOK_OR printstmt fe eventblock unary %type funcblock func_decl func_impl returnblock registerstmt -%type interfacestmt typestmt attribution +%type interfacestmt typestmt attribution enum_item enum %type typestmt_impls %type element %type elements relements @@ -31,7 +31,7 @@ %type TOK_STRING asminline %type TOK_STEPPER %type error -%type intf_decls +%type intf_decls enum_items %% @@ -70,10 +70,34 @@ gstmt : TOK_USE TOK_IDENTIFIER ';' { parseUseFile($2, @TOK_USE); $$ = NULL; | interfacestmt { $$ = $1; } | typestmt { $$ = $1; } | fe { $$ = $1; } + | enum { $$ = $1; } | error ';' { /* error recovery until next ';' */ $$ = new Int8(0); // evita falha de segmentacao }; + +enum : TOK_ENUM TOK_IDENTIFIER[id] '{' enum_items '}' { + $$ = new Enum($id, std::move(*$enum_items)); +} + +enum_items : enum_items[items] ',' enum_item { + $items->push_back($enum_item); + $$ = $1; +} + +enum_items : enum_item { + $$ = new vector(); + $$->push_back($enum_item); +} + +enum_item : TOK_IDENTIFIER[id] '=' TOK_INTEGER[intg] { + $$ = new NamedConst($id, new Int8($intg)); +} + +enum_item : TOK_IDENTIFIER[id] { + $$ = new NamedConst($id); +} + attribution : ident_or_xident[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index a8bb066..f258ccc 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -29,7 +29,7 @@ %token TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE %token TOK_FINT8 TOK_FINT16 TOK_FINT32 TOK_FINT64 %token TOK_FFLOAT TOK_FDOUBLE TOK_FCHAR TOK_FLONG TOK_FUNSIGNED TOK_FBOOL -%token TOK_TYPE TOK_INTF TOK_IMPL TOK_USE +%token TOK_TYPE TOK_INTF TOK_IMPL TOK_USE TOK_ENUM %token TOK_QUANDO TOK_ESTA %token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT diff --git a/src/LanguageUse.y b/src/LanguageUse.y index c170ed0..5b1be43 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -12,9 +12,10 @@ void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); } -%type globals type_stmts +%type globals type_stmts enum_items %type global register interface type ignore_stmt ignore use type_stmt %type function function_decl function_impl var_decl cast ignore_param +%type enum enum_item %type function_params %type function_param %type intf_decls @@ -54,6 +55,7 @@ global : use | type | register | function + | enum | var_decl { $$ = NULL; } // don't export global vars | qualifier var_decl { $$ = NULL; } @@ -62,6 +64,28 @@ use : TOK_USE TOK_IDENTIFIER ';' { $$ = NULL; } +enum : TOK_ENUM TOK_IDENTIFIER[id] '{' enum_items '}' { + $$ = new Enum($id, std::move(*$enum_items)); +} + +enum_items : enum_items[items] ',' enum_item { + $items->push_back($enum_item); + $$ = $1; +} + +enum_items : enum_item { + $$ = new vector(); + $$->push_back($enum_item); +} + +enum_item : TOK_IDENTIFIER[id] '=' TOK_INTEGER[intg] { + $$ = new NamedConst($id, new Int8($intg)); +} + +enum_item : TOK_IDENTIFIER[id] { + $$ = new NamedConst($id); +} + function : function_decl | function_impl function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER '(' function_params ')' ';' { diff --git a/src/NamedConst.h b/src/NamedConst.h new file mode 100644 index 0000000..0c44e23 --- /dev/null +++ b/src/NamedConst.h @@ -0,0 +1,33 @@ + +#pragma once + +#include "Node.h" + +class NamedConst: public NamedNode { +protected: + Node *value = NULL; + +public: + NamedConst(const char *name) : NamedNode(name) {} + + NamedConst(const char *name, Node *value) : NamedNode(name), value(value) { + dt = value->getDataType(); + } + + virtual Value *getLLVMValue(Node *stem) override { + return value->generate(NULL, NULL, NULL); //FIXME + } + + virtual bool isConstExpr() override { + return true; + } + + virtual void setValue(Node *n) { + value = n; + dt = value->getDataType(); + } + + Node *getValue() { + return value; + } +}; diff --git a/src/Scanner.cpp b/src/Scanner.cpp index 57f58aa..26acbfa 100644 --- a/src/Scanner.cpp +++ b/src/Scanner.cpp @@ -41,14 +41,14 @@ void MAINerror(location_t *loc, yyscan_t scanner, const char *s) { void yyerrorcpp(const string& s, SourceLocation *n) { string e = COLOR_RED "semantic error: " COLOR_RESET + s; fprintf(stderr, "%s:%d:%d: %s\n", - n->getFile(), n->getLineNo(), n->getColNo(), s.c_str()); + n->getFile().c_str(), n->getLineNo(), n->getColNo(), s.c_str()); errorsfound++; } void yywarncpp(const string& s, SourceLocation *n) { string e = COLOR_BLUE "semantic warning: " COLOR_RESET + s; fprintf(stderr, "%s:%d:%d %s\n", - n->getFile(), n->getLineNo(), n->getColNo(), e.c_str()); + n->getFile().c_str(), n->getLineNo(), n->getColNo(), e.c_str()); } bool parseFile(const string& source) { diff --git a/testnew/general/enum.rob b/testnew/general/enum.rob new file mode 100644 index 0000000..a9ddd40 --- /dev/null +++ b/testnew/general/enum.rob @@ -0,0 +1,27 @@ + +enum Enum {A = 0x24, B = 10, C, D, E = 200} + +type withenum { + value = Enum.A; +} + +Enum func(Enum e) { + if e == Enum.A { + return Enum.B; + } else { + return Enum.E; + } +} + +int16 main() { + a = Enum.B; + b = func(a); + c = withenum(); + + if a == b or c.value == Enum.B { + return 1; + } else { + return 0; + } +} + From 99f3926385783509ce7c18bbaa2a6e2f099b0160 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 12 Aug 2023 20:04:24 -0300 Subject: [PATCH 030/117] Fixes array/matrix with types and removes some invalid syntax constructs. --- .../syntaxes/rob.tmLanguage.json | 4 +- rob.vim | 2 +- src/Array.cpp | 46 +- src/Array.h | 6 + src/ArrayElements.cpp | 2 +- src/ArrayElements.h | 2 +- src/BackLLVM.cpp | 31 +- src/BackLLVM.h | 22 +- src/BuildTypes.cpp | 10 +- src/BuildTypes.h | 5 +- src/DebugInfo.cpp | 13 +- src/FunctionImpl.cpp | 2 +- src/Language.l | 18 - src/Language.y | 465 ++++++++++-------- src/LanguageHeader.y | 5 +- src/LanguageUse.y | 137 ++++-- src/LoadArray.cpp | 34 +- src/Matrix.cpp | 66 ++- src/Matrix.h | 7 + src/MatrixElements.cpp | 2 +- src/MatrixElements.h | 2 +- src/Node.h | 4 + src/Program.cpp | 7 +- src/Scalar.cpp | 20 - src/Scalar.h | 11 - src/Scanner.cpp | 1 + src/UserType.cpp | 26 +- src/UserType.h | 3 +- src/Variable.cpp | 24 + src/Variable.h | 13 +- testnew/general/Makefile | 6 +- testnew/general/typeandarrays.rob | 30 ++ 32 files changed, 613 insertions(+), 413 deletions(-) create mode 100644 src/Variable.cpp create mode 100644 testnew/general/typeandarrays.rob diff --git a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json index 1474363..8c44d99 100644 --- a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json +++ b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json @@ -42,7 +42,7 @@ "keywords": { "patterns": [{ "name": "keyword.control.rob", - "match": "\\b(while|loop|if|else|delay|print|return|register|at|volatile|const|type|interface|implements|use|and|or)\\b" + "match": "\\b(while|loop|if|else|delay|print|return|register|at|volatile|const|type|interface|implements|use|and|or|enum)\\b" }] }, "types": { @@ -73,7 +73,7 @@ "functions": { "patterns": [{ "name": "support.function.rob", - "match": "\\b(\\w+(?=\\())\\b" + "match": "\\b(\\w+(?=\\s*\\())\\b" }] }, "ident": { diff --git a/rob.vim b/rob.vim index 477c230..41ca3bd 100644 --- a/rob.vim +++ b/rob.vim @@ -7,7 +7,7 @@ if exists("b:current_syntax") finish endif -syn keyword keywords while loop if else delay print return register at volatile const asm type use +syn keyword keywords while loop if else delay print return register at volatile const asm type use enum syn keyword typeKeywords void char int8 int16 int32 int64 long unsigned float double bool syn keyword operatorKeywords and or quando esta servo syn keyword booleanKeyword true false diff --git a/src/Array.cpp b/src/Array.cpp index b601497..f7f52cf 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -4,23 +4,33 @@ #include "BackLLVM.h" #include "Visitor.h" #include "Int16.h" +#include "FunctionImpl.h" Array::Array(const char *n, ArrayElements *aes) : LinearDataStructure(n), elements(aes) { NamedConst *nc = new NamedConst("size", getNodeForIntConst(aes->getArraySize())); addChild(nc); + dt = tarray; } -Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { +void Array::createDataType() { + if (arrayType != NULL) + return; + //Create an Array of Type Int8, and Size = size. size = elements->getArraySize(); Value *array_size = ConstantInt::get(Type::getInt8Ty(global_context), size); //Get Type of elements in Array of Elements, and define as I. - element_dt = elements->getArrayType(func); + element_dt = elements->getArrayType(); Type* I = buildTypes->llvmType(element_dt); //Declare array type. - ArrayType* arrayType = ArrayType::get(I, size); + arrayType = ArrayType::get(I, size); +} + +Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + createDataType(); //Generate array elements unsigned int struct_size = elements->getStructSize(); @@ -29,15 +39,16 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb vector elementValues; elementValues.reserve(elements->getArraySize()); for (int i=0; igetStructElement(i); + Value *val = elValue->generate(func, block, allocblock); + if (!val) + return NULL; + val = Coercion::Convert(val, arrayType->getElementType(), block, elValue); + if (!dyn_cast(val)) + allConst = false; + unsigned elCount = elements->getElementCount(i); - for (int j=0; jgetStructElement(i); - Value *val = elValue->generate(func, block, allocblock); - if (!val) - return NULL; - val = Coercion::Convert(val, I, block, elValue); - if (!dyn_cast(val)) - allConst = false; + for (int j=0; j < elCount; j++) { elementValues.push_back(val); } } @@ -67,7 +78,7 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb if (debug_info) { auto di_ptr = DBuilder->createPointerType(buildTypes->diType(getElementDt()), - buildTypes->bitWidth(currentTarget.pointerType)); + buildTypes->bitWidth(currentTarget().pointerType)); auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", funit, this->getLineNo(), di_ptr, false); gv->addDebugInfo(d); @@ -75,7 +86,11 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb } else { Builder->SetInsertPoint(allocblock); - alloc = Builder->CreateAlloca(arrayType, dataAddrSpace, 0, name); + + if (getGEPIndex() != -1) + alloc = getLLVMValue(func); + else + alloc = Builder->CreateAlloca(arrayType, dataAddrSpace, 0, name); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); @@ -97,3 +112,8 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb void Array::accept(Visitor& v) { v.visit(*this); } + +Type* Array::getLLVMType() { + createDataType(); + return arrayType; +} diff --git a/src/Array.h b/src/Array.h index cc56d93..f9bf10c 100644 --- a/src/Array.h +++ b/src/Array.h @@ -23,6 +23,9 @@ class Array: public LinearDataStructure { private: unsigned int size; ArrayElements *elements; + ArrayType *arrayType = NULL; + void createDataType(); + public: Array(const char *n, ArrayElements *aes); @@ -37,4 +40,7 @@ class Array: public LinearDataStructure { } virtual void accept(Visitor& v) override; + + virtual Type *getLLVMType() override; + }; diff --git a/src/ArrayElements.cpp b/src/ArrayElements.cpp index 35a32e8..e465605 100644 --- a/src/ArrayElements.cpp +++ b/src/ArrayElements.cpp @@ -18,7 +18,7 @@ unsigned ArrayElements::getStructSize() { return elements.size(); } -DataType ArrayElements::getArrayType(FunctionImpl *func) { +DataType ArrayElements::getArrayType() { unsigned intsize = 0; unsigned floatsize = 0; for(auto& i : elements) { diff --git a/src/ArrayElements.h b/src/ArrayElements.h index 64dfe40..0694a97 100644 --- a/src/ArrayElements.h +++ b/src/ArrayElements.h @@ -21,7 +21,7 @@ class ArrayElements { unsigned getStructSize (); unsigned getElementCount (int position); Node *getStructElement (int position); - DataType getArrayType(FunctionImpl *func); + DataType getArrayType(); std::vector const& getElements() { return elements; diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index d14c08e..0d5e0ab 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -41,21 +41,29 @@ unsigned int dataAddrSpace = 0; enum SupportedTargets currentTargetId; extern char *build_outputfilename; +TargetInfo supportedTargets[__last_target] = { + {rb_native, "", "", "", "", tint64}, // default target + {rb_avr, "avr328p", "avr", "atmega328p", "+avr5", tint16}, + {rb_arm, "stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, + {rb_xtensa, "esp32", "xtensa", "", "", tint32}, +}; + void print_llvm_ir(char opt_level) { - if (currentTarget.backend == rb_native) { + const TargetInfo& ai = currentTarget(); + if (ai.backend == rb_native) { // Native target init InitializeNativeTarget(); InitializeNativeTargetAsmParser(); InitializeNativeTargetAsmPrinter(); - } else if (currentTarget.backend == rb_avr) { + } else if (ai.backend == rb_avr) { // AVR target init LLVMInitializeAVRTargetInfo(); LLVMInitializeAVRTarget(); LLVMInitializeAVRTargetMC(); LLVMInitializeAVRAsmParser(); LLVMInitializeAVRAsmPrinter(); - } else if (currentTarget.backend == rb_arm) { + } else if (ai.backend == rb_arm) { // ARM target init LLVMInitializeARMTargetInfo(); LLVMInitializeARMTarget(); @@ -63,7 +71,7 @@ void print_llvm_ir(char opt_level) { LLVMInitializeARMAsmParser(); LLVMInitializeARMAsmPrinter(); } else { - cerr << "No backend set for target " << currentTarget.triple << ".\n"; + cerr << "No backend set for target " << ai.triple << ".\n"; return; } @@ -78,8 +86,6 @@ void print_llvm_ir(char opt_level) { } static string nativeFeatures = Features.getString(); supportedTargets[0].features = nativeFeatures.c_str(); - - TargetInfo ai = currentTarget; std::string Error; auto Target = TargetRegistry::lookupTarget(ai.triple, Error); @@ -147,3 +153,16 @@ void print_llvm_ir(char opt_level) { } } +const TargetInfo& currentTarget() { + return supportedTargets[currentTargetId]; +} + +void setTarget(const char *targetarch) { + currentTargetId = st_native; //native + for(int t = st_native; t < __last_target; t++) { + if (strcmp(targetarch, supportedTargets[t].name) == 0) { + currentTargetId = static_cast(t); + break; + } + } +} diff --git a/src/BackLLVM.h b/src/BackLLVM.h index f36bbcf..4ab910a 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -21,21 +21,7 @@ extern unsigned int dataAddrSpace; enum SupportedTargets {st_native, st_avr328p, st_stm32f1, st_esp32, __last_target}; extern enum SupportedTargets currentTargetId; -#define currentTarget (supportedTargets[currentTargetId]) - -static TargetInfo supportedTargets[__last_target] = { - {rb_native, "", "", "", "", tint64}, // default target - {rb_avr, "avr328p", "avr", "atmega328p", "+avr5", tint16}, - {rb_arm, "stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, - {rb_xtensa, "esp32", "xtensa", "", "", tint32}, -}; - -static void setTarget(const char *targetarch) { - currentTargetId = st_native; //native - for(int t = st_native; t < __last_target; t++) { - if (strcmp(targetarch, supportedTargets[t].name) == 0) { - currentTargetId = static_cast(t); - break; - } - } -} + +extern TargetInfo supportedTargets[__last_target]; +void setTarget(const char *targetarch); +const TargetInfo& currentTarget(); diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index e1e9e8f..3413bf7 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -9,6 +9,11 @@ BuildTypes::BuildTypes(DataType targetPointerType) { tinfo[tbool] = {"bool", 1, Type::getInt1Ty(global_context), dwarf::DW_ATE_boolean}; tinfo[tchar] = {"char", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned_char}; tinfo[tint2] = {"int2", 2, Type::getIntNTy(global_context, 2), dwarf::DW_ATE_signed}; + tinfo[tint3] = {"int3", 3, Type::getIntNTy(global_context, 3), dwarf::DW_ATE_signed}; + tinfo[tint4] = {"int4", 4, Type::getIntNTy(global_context, 4), dwarf::DW_ATE_signed}; + tinfo[tint5] = {"int5", 5, Type::getIntNTy(global_context, 5), dwarf::DW_ATE_signed}; + tinfo[tint6] = {"int6", 6, Type::getIntNTy(global_context, 6), dwarf::DW_ATE_signed}; + tinfo[tint7] = {"int7", 7, Type::getIntNTy(global_context, 7), dwarf::DW_ATE_signed}; tinfo[tint8] = {"int8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_signed}; tinfo[tint16] = {"int16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_signed}; tinfo[tint32] = {"int32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_signed}; @@ -60,9 +65,8 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi uint32_t align = dl.getABITypeAlign(llvmType).value(); uint64_t bitWidth = typeBitWidth; - if (typeBitWidth == 0) + if (typeBitWidth == 0 && llvmType->isSized()) typeBitWidth = dl.getTypeAllocSizeInBits(llvmType); - if (udt == namedTypes.end()) { DataTypeInfo info(name.c_str(), bitWidth, llvmType, 0); @@ -108,7 +112,7 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi info.diType = DBuilder->createClassType(RobDbgInfo.currScope(), name, RobDbgInfo.currFile(), userType->getLineNo(), bitWidth, align, 0, DINode::DIFlags::FlagZero, nullptr, dielems); - unsigned ptbw = tinfo[currentTarget.pointerType].bitWidth; + unsigned ptbw = tinfo[currentTarget().pointerType].bitWidth; info.diPointerType = DBuilder->createPointerType(info.diType, 8); } return id; diff --git a/src/BuildTypes.h b/src/BuildTypes.h index 72a1fde..3f7d619 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -6,8 +6,9 @@ typedef int DataType; -enum BasicDataType {tvoid, tbool, tchar, tint2, tint8, tint16, tint32, tint64, - tint8u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, tarray, +enum BasicDataType {tvoid, tbool, tchar, tint2, tint3, tint4, tint5, tint6, tint7, + tint8, tint16, tint32, tint64, tint8u, tint16u, tint32u, tint64u, + tfloat, tdouble, tldouble, tarray, /* new types here! */ __bdt_last}; diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index 7755621..f4820e4 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -1,6 +1,7 @@ #include "HeaderGlobals.h" #include "SourceLocation.h" #include "Node.h" +#include "BackLLVM.h" void DebugInfo::emitLocation(SourceLocation *s) { if (!debug_info) @@ -45,10 +46,14 @@ DIScope* DebugInfo::currScope() { DIExpression *DebugInfo::getFixedOffsetExpression() { // TODO: For some unknown reason (to me), we need to offset // the var declaration by one to see its actual value - SmallVector Ops; - DIExpression *ex = DBuilder->createExpression(); - ex->appendOffset(Ops, 1); - return DIExpression::prependOpcodes(ex, Ops, false); + if (currentTarget().backend == rb_avr) { + SmallVector Ops; + DIExpression *ex = DBuilder->createExpression(); + ex->appendOffset(Ops, 1); + return DIExpression::prependOpcodes(ex, Ops, false); + } else { + return DBuilder->createExpression(); + } } void DebugInfo::declareVar(Node *n, Value *alloc, BasicBlock *allocblock) { diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 25a07fe..a53255b 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -50,7 +50,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo func->setDSOLocal(true); llvm::AttrBuilder attrs(global_context); //attrs.addAttribute(Attribute::MinSize); - attrs.addAttribute("target-cpu", currentTarget.cpu); + attrs.addAttribute("target-cpu", currentTarget().cpu); attrs.addAttribute("frame-pointer", "all"); attrs.addAttribute("stack-protector-buffer-size", "8"); diff --git a/src/Language.l b/src/Language.l index f99c402..6193eb1 100644 --- a/src/Language.l +++ b/src/Language.l @@ -50,27 +50,9 @@ ID {A}({A}|{D})* "while" { return TOK_WHILE; } "loop" { return TOK_LOOP; } -"print" { return TOK_PRINT; } - -"in"[0-9]+ { yylval->port = strndup(yytext+2, yyleng-2); - return TOK_IN; - } - -"out"[0-9]+ { yylval->port = strndup(yytext+3, yyleng-3); - return TOK_OUT; - } - -"stepper"[0-2]+ { yylval->nint = atoi(strndup(yytext+7, yyleng-7)); - return TOK_STEPPER; - } - -"servo" { return TOK_SERVO; } - "quando" { return TOK_QUANDO; } "esta" { return TOK_ESTA; } -"delay" { return TOK_DELAY; } - "and" { return TOK_AND; } "or" { return TOK_OR; } diff --git a/src/Language.y b/src/Language.y index 6041b48..e98fbc3 100644 --- a/src/Language.y +++ b/src/Language.y @@ -9,72 +9,72 @@ void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); } -%type term term2 expr factor stmt gstmt condblock whileblock logicexpr -%type logicterm logicfactor TOK_AND TOK_OR printstmt fe eventblock unary -%type funcblock func_decl func_impl returnblock registerstmt -%type interfacestmt typestmt attribution enum_item enum -%type typestmt_impls +%type globals type_stmts enum_items interface_decls +%type stmts elseblock +%type global register interface type type_stmt use +%type function function_decl function_impl returnblock +%type enum enum_item interface_impl +%type simplevar_decl call_or_cast complexvar_set +%type term term2 expr factor stmt condblock whileblock logicexpr +%type logicterm logicfactor TOK_AND TOK_OR event unary +%type type_impls + %type element -%type elements relements -%type funcparam -%type funcparams -%type paramscall +%type elements relements array %type melement -%type matrix -%type stmts gstmts elseblock -%type TOK_OUT TOK_IN +%type melements matrix + +%type function_params +%type function_param +%type paramscall + +%type TOK_IDENTIFIER TOK_XIDENTIFIER ident_or_xident %type TOK_INTEGER qualifier %type TOK_FLOAT %type TOK_DOUBLE %type TOK_LDOUBLE -%type TOK_IDENTIFIER TOK_XIDENTIFIER ident_or_xident %type TOK_STRING asminline %type TOK_STEPPER -%type error -%type intf_decls enum_items %% -programa : gstmts { - for(auto stmt : *($gstmts)) { +programa : globals { + for(auto stmt : *($globals)) { program->addChild(stmt); } - /*std::fstream fs; - fs.open("ast", std::fstream::out); - PrintAstVisitor(fs).visit(p); - fs.close();*/ - if (errorsfound == 0) program->generate(); }; -gstmts : gstmts gstmt { - if ($gstmt) { // TOK_USE returns NULL - $1->push_back($gstmt); +globals : globals global { + if ($global) { + $1->push_back($global); } } -gstmts : gstmt { +globals : global { $$ = new vector(); - if ($gstmt) { - $$->push_back($gstmt); - $gstmt->setLocation(@gstmt); + if ($global) { + $global->setLocation(@global); + $$->push_back($global); } } -gstmt : TOK_USE TOK_IDENTIFIER ';' { parseUseFile($2, @TOK_USE); $$ = NULL; } - | attribution ';' { $$ = $1; } - | qualifier attribution ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } - | registerstmt { $$ = $1; } - | interfacestmt { $$ = $1; } - | typestmt { $$ = $1; } - | fe { $$ = $1; } - | enum { $$ = $1; } - | error ';' { /* error recovery until next ';' */ - $$ = new Int8(0); // evita falha de segmentacao - }; - +global : use + | interface + | type + | register + | function + | event + | enum + | simplevar_decl ';' + | qualifier simplevar_decl ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } + +use : TOK_USE TOK_IDENTIFIER ';' { + parseUseFile($2, @TOK_USE); + $$ = NULL; +} enum : TOK_ENUM TOK_IDENTIFIER[id] '{' enum_items '}' { $$ = new Enum($id, std::move(*$enum_items)); @@ -98,42 +98,21 @@ enum_item : TOK_IDENTIFIER[id] { $$ = new NamedConst($id); } -attribution : ident_or_xident[id] '=' expr { - $$ = new Scalar($id, $expr); - $$->setLocation(@id); -} - -attribution : ident_or_xident[id] '=' '{' elements '}' { - $$ = new Array($id, $elements); - $$->setLocation(@id); -} +function : function_decl | function_impl -attribution : ident_or_xident[id] '=' '{' matrix '}' { - $$ = new Matrix($id, $matrix); - $$->setLocation(@id); -} - -qualifier : TOK_CONST { $$ = qconst; } - | TOK_VOLATILE { $$ = qvolatile; } - -fe : funcblock { $$ = $1; } - | eventblock { $$ = $1; } - ; - -funcblock : func_decl | func_impl ; - -func_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' funcparams ')' ';' { - $$ = new FunctionDecl(buildTypes->getType($type, true), $id, $funcparams); +function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' ';' { + $$ = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params); $$->setLocation(@type); } -func_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' funcparams ')' '{' stmts '}'[ef] { - $$ = new FunctionImpl(buildTypes->getType($type, true), $id, $funcparams, - std::move(*$stmts), @ef); - $$->setLocation(@type); - } - ; -eventblock : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { +function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' '{' stmts '}'[ef] { + FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, + std::move(*$stmts), @ef); + func->setLocation(@type); + $$ = func; +} + +event : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { /*char funcname[100]; snprintf(funcname, 100, "__callback_int_p%d_e%d", (int)$2, (int)$4); vectorglobal.push_back(new AttachInterrupt($2, funcname, $4)); @@ -143,127 +122,216 @@ eventblock : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { } ; -stmts : stmts stmt { - $1->push_back($stmt); +qualifier : TOK_CONST { $$ = qconst; } + | TOK_VOLATILE { $$ = qvolatile; } + +function_params: function_params ',' function_param { + $1 -> append($3); + $$ = $1; } -stmts : stmt { +function_params: function_param { + FunctionParams *fps = new FunctionParams(); + fps->append($1); + $$ = fps; +} + +function_params: %empty { + FunctionParams *fps = new FunctionParams(); + $$ = fps; +} + +function_param : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] { + $$ = new FunctionParam($id, buildTypes->getType($type, true)); +} + +register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT expr ';' { + $$ = new Pointer($name, buildTypes->getType($type, true), $5); + $$->setQualifier(qvolatile); + $$->setLocation(@name); +} + +interface : TOK_INTF TOK_IDENTIFIER '{' interface_decls[intf] '}' { + $$ = new Interface($TOK_IDENTIFIER, std::move(*$intf)); + $$->setLocation(@TOK_INTF); +} + +interface : TOK_INTF TOK_IDENTIFIER '{' '}' { + $$ = new Interface($TOK_IDENTIFIER); + $$->setLocation(@TOK_INTF); +} + +interface_decls : interface_decls function_decl { + $1->push_back($function_decl); + $$ = $1; +} + +interface_decls : function_decl { $$ = new vector(); - $$->push_back($stmt); - $stmt->setLocation(@stmt); + $$->push_back($function_decl); } -stmt : gstmt { $$ = $1; } - | TOK_OUT '=' expr ';' { $$ = new OutPort($1, $3); } - | ident_or_xident[id] '(' paramscall ')' ';' { $$ = new FunctionCall($id, $3); $$->setLocation(@id);} - | TOK_IDENTIFIER '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '+', new Int8(1))); } - | TOK_IDENTIFIER '-' '-' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '-', new Int8(1))); } - | TOK_IDENTIFIER '+' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '+', $4)); } - | TOK_IDENTIFIER '-' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '-', $4)); } - | TOK_IDENTIFIER '*' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '*', $4)); } - | TOK_IDENTIFIER '/' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '/', $4)); } - | TOK_IDENTIFIER '|' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '|', $4)); } - | TOK_IDENTIFIER '&' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '&', $4)); } - | TOK_IDENTIFIER '^' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '^', $4)); } - | TOK_DELAY expr';' { $$ = new Delay($2); } - | condblock { $$ = $1; } - | whileblock { $$ = $1; } - | returnblock ';' { $$ = $1; } - | printstmt ';' { $$ = $1; } - | asminline ';' { $$ = new InlineAssembly($1); $$->setLocation(@1); } - | TOK_IDENTIFIER '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6);} - | TOK_IDENTIFIER '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9); } - - -matrix : matrix ',' melement { $1->append($3); - $$ = $1; } - | melement { MatrixElements *mes = new MatrixElements(); - mes->append($1); - $$ = mes; } - ; +//FIXME: Interface only allows function_decls! +interface_impl : TOK_IDENTIFIER[id] '=' TOK_IDENTIFIER[intfname] '{' type_stmts '}' { + vector intf; + intf.push_back($intfname); + UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(intf)); + ut->setLocation(@id); + $$ = ut; +} + +type : TOK_TYPE TOK_IDENTIFIER TOK_IMPL type_impls '{' type_stmts '}' { + UserType *ut = new UserType($TOK_IDENTIFIER, std::move(*$type_stmts), std::move(*$type_impls)); + ut->setLocation(@TOK_TYPE); + $$ = ut; +} + +type : TOK_TYPE TOK_IDENTIFIER '{' type_stmts '}' { + UserType *ut = new UserType($TOK_IDENTIFIER, std::move(*$type_stmts)); + ut->setLocation(@TOK_TYPE); + $$ = ut; +} +type_impls : type_impls ',' TOK_IDENTIFIER { + $1->push_back($TOK_IDENTIFIER); + $$ = $1; +} + +type_impls : TOK_IDENTIFIER { + $$ = new vector(); + $$->push_back($1); +} + +type_stmts : type_stmts type_stmt { + if ($type_stmt) + $$->push_back($type_stmt); +} + +type_stmts : type_stmt { + $$ = new vector(); + if ($type_stmt) + $$->push_back($type_stmt); +} + +type_stmt : simplevar_decl ';' + | qualifier[q] simplevar_decl ';' { $simplevar_decl->setQualifier((DataQualifier)$q); $$ = $2; } + | function_impl + | interface_impl + | enum + +simplevar_decl : TOK_IDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } + +array : '{' elements '}' { $$ = $elements; } +matrix : '{' melements '}' { $$ = $melements; } + +melements : melements ',' melement { + $1->append($3); + $$ = $1; +} + +melements : melement { + MatrixElements *mes = new MatrixElements(); + mes->append($1); + $$ = mes; +} melement : relements ':' TOK_INTEGER { $$ = new MatrixElement($1, (unsigned)$3); } | relements { $$ = new MatrixElement($1, 1);} - ; relements : '{' elements '}' { $$ = $2; } - ; elements : elements ',' element { $1->append($3); $$ = $1; } | element { ArrayElements *aes = new ArrayElements(); aes->append($1); $$ = aes; } - ; -element : factor ':' TOK_INTEGER { $$ = new ArrayElement($1, (unsigned)$3); } - | factor { $$ = new ArrayElement($1, 1); } - ; +element : expr ':' TOK_INTEGER { $$ = new ArrayElement($1, (unsigned)$3); } + | expr { $$ = new ArrayElement($1, 1); } + +asminline : TOK_ASM TOK_STRING { $$ = $2; } -funcparams: funcparams ',' funcparam { - $1 -> append($3); - $$ = $1; - } - | funcparam { - FunctionParams *fps = new FunctionParams(); - fps->append($1); - $$ = fps; - } - | %empty { - FunctionParams *fps = new FunctionParams(); - $$ = fps; - } - ; +stmts : stmts stmt { + $1->push_back($stmt); +} -funcparam : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] { - $$ = new FunctionParam($id, buildTypes->getType($type, true)); - } +stmts : stmt { + $$ = new vector(); + $$->push_back($stmt); + $stmt->setLocation(@stmt); +} -paramscall : paramscall ',' expr {$1 -> append($3); - $$ = $1;} - | expr { ParamsCall *pc = new ParamsCall(); - pc->append($1); - $$ = pc;} - | %empty { ParamsCall *pc = new ParamsCall(); - $$ = pc; - } - ; +stmt : ident_or_xident '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '+', new Int8(1))); } + | ident_or_xident '-' '-' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '-', new Int8(1))); } + | ident_or_xident '+' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '+', $4)); } + | ident_or_xident '-' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '-', $4)); } + | ident_or_xident '*' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '*', $4)); } + | ident_or_xident '/' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '/', $4)); } + | ident_or_xident '|' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '|', $4)); } + | ident_or_xident '&' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '&', $4)); } + | ident_or_xident '^' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '^', $4)); } + | ident_or_xident '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6);} + | ident_or_xident '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9); } + | asminline ';' { $$ = new InlineAssembly($1); $$->setLocation(@1); } + | simplevar_decl ';' + | complexvar_set ';' + | returnblock ';' + | call_or_cast ';' + | condblock + | whileblock + | interface_impl + +complexvar_set : TOK_XIDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } +complexvar_set : TOK_XIDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } +complexvar_set : TOK_XIDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } returnblock : TOK_RETURN expr { $$ = new Return($2); } - | TOK_RETURN logicexpr { $$ = new Return($2); } - | TOK_RETURN { $$ = new Return(); } - ; +returnblock : TOK_RETURN logicexpr { $$ = new Return($2); } +returnblock : TOK_RETURN { $$ = new Return(); } + +/* + * Conditional + */ condblock : TOK_IF logicexpr '{' stmts '}' { - $logicexpr->setLocation(@logicexpr); - $$ = new If($logicexpr, std::move(*$stmts)); - $$->setLocation(@TOK_IF); - } - | TOK_IF logicexpr '{' stmts '}' elseblock { - $logicexpr->setLocation(@logicexpr); - $$ = new If($logicexpr, std::move(*$stmts), std::move(*$elseblock)); - $$->setLocation(@TOK_IF); - } - ; + $logicexpr->setLocation(@logicexpr); + $$ = new If($logicexpr, std::move(*$stmts)); + $$->setLocation(@TOK_IF); +} +condblock : TOK_IF logicexpr '{' stmts '}' elseblock { + $logicexpr->setLocation(@logicexpr); + $$ = new If($logicexpr, std::move(*$stmts), std::move(*$elseblock)); + $$->setLocation(@TOK_IF); +} elseblock : TOK_ELSE '{' stmts '}' { $$ = $stmts; } +/* + * Repetition + */ + whileblock : TOK_WHILE logicexpr '{' stmts '}' { - $logicexpr->setLocation(@logicexpr); - $$ = new While($logicexpr, std::move(*$stmts)); - $$->setLocation(@TOK_WHILE); - } - | TOK_WHILE logicexpr ';' { - $logicexpr->setLocation(@logicexpr); - $$ = new While($logicexpr); - $$->setLocation(@TOK_WHILE); - } - | TOK_LOOP '{' stmts '}' { - $$ = new Loop(std::move(*$stmts)); - $$->setLocation(@TOK_LOOP); - } - ; + $logicexpr->setLocation(@logicexpr); + $$ = new While($logicexpr, std::move(*$stmts)); + $$->setLocation(@TOK_WHILE); +} + +whileblock : TOK_WHILE logicexpr ';' { + $logicexpr->setLocation(@logicexpr); + $$ = new While($logicexpr); + $$->setLocation(@TOK_WHILE); +} + +whileblock : TOK_LOOP '{' stmts '}' { + $$ = new Loop(std::move(*$stmts)); + $$->setLocation(@TOK_LOOP); +} + +/* + * Logic + */ logicexpr : logicexpr TOK_OR logicterm { $$ = new BinaryOp($1, TOK_OR, $3); } | logicterm { $$ = $1; } @@ -282,6 +350,10 @@ logicfactor : '(' logicexpr ')' { $$ = $2; } | expr '>' expr { $$ = new CmpOp($1, GT_OP, $3); } ; +/* + * Arithmetic + */ + expr : expr '+' term { $$ = new BinaryOp($1, '+', $3); } | expr '-' term { $$ = new BinaryOp($1, '-', $3); } | expr '|' term { $$ = new BinaryOp($1, '|', $3); } @@ -303,17 +375,16 @@ term2 : term2 '&' factor { $$ = new BinaryOp($1, '&', $3); } factor : '(' expr ')' { $$ = $2; } | ident_or_xident { $$ = new Load($1); } - | TOK_IDENTIFIER '[' expr ']' { $$ = new LoadArray($1, $3);} - | TOK_IDENTIFIER '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6);} | TOK_TRUE { $$ = new Int1(1); } | TOK_FALSE { $$ = new Int1(0); } | TOK_INTEGER { $$ = getNodeForIntConst($1); } | TOK_FLOAT { $$ = new Float($1); } | TOK_DOUBLE { $$ = new Double($1); } | TOK_LDOUBLE { $$ = new Float128($1); } - | TOK_IN { $$ = new InPort($1); } - | ident_or_xident[id] '(' paramscall ')' { $$ = new FunctionCall($id, $paramscall); $$->setLocation(@id); } - | unary { $$ = $1; } + | ident_or_xident[id] '[' expr ']' { $$ = new LoadArray($1, $3);} + | ident_or_xident[id] '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6);} + | call_or_cast + | unary ; ident_or_xident: TOK_IDENTIFIER | TOK_XIDENTIFIER @@ -322,56 +393,22 @@ unary : '-' factor { $$ = new BinaryOp($2, '*', getNodeForIntConst(-1)); } | '~' factor { $$ = new FlipOp($2); } ; -printstmt : TOK_PRINT TOK_STRING { $$ = new Print(new StringConst($2)); } - | TOK_PRINT expr { $$ = new Print($2); } - -registerstmt : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT expr ';' { - $$ = new Pointer($name, buildTypes->getType($type, true), $5); - $$->setQualifier(qvolatile); - $$->setLocation(@name); +call_or_cast : ident_or_xident[id] '(' paramscall ')' { + $$ = new FunctionCall($id, $paramscall); + $$->setLocation(@id); } -asminline : TOK_ASM TOK_STRING { $$ = $2; } - ; - -interfacestmt : TOK_INTF TOK_IDENTIFIER '{' intf_decls '}' { - $$ = new Interface($TOK_IDENTIFIER, std::move(*$intf_decls)); - $$->setLocation(@TOK_INTF); -}; - -interfacestmt : TOK_INTF TOK_IDENTIFIER '{' '}' { - $$ = new Interface($TOK_IDENTIFIER); - $$->setLocation(@TOK_INTF); -}; - -intf_decls : intf_decls func_decl { - $1->push_back($func_decl); +paramscall : paramscall ',' expr { + $1 -> append($3); $$ = $1; -}; - -intf_decls : func_decl { - $$ = new vector(); - $$->push_back($func_decl); -}; - -typestmt : TOK_TYPE TOK_IDENTIFIER TOK_IMPL typestmt_impls '{' stmts '}' { - $$ = new UserType($TOK_IDENTIFIER, std::move(*$stmts), std::move(*$typestmt_impls)); - $$->setLocation(@TOK_TYPE); } -typestmt : TOK_TYPE TOK_IDENTIFIER '{' stmts '}' { - $$ = new UserType($TOK_IDENTIFIER, std::move(*$stmts)); - $$->setLocation(@TOK_TYPE); +paramscall : expr { + ParamsCall *pc = new ParamsCall(); + pc->append($1); + $$ = pc; } -typestmt_impls : typestmt_impls ',' TOK_IDENTIFIER { - $1->push_back($TOK_IDENTIFIER); - $$ = $1; -} - -typestmt_impls : TOK_IDENTIFIER { - $$ = new vector(); - $$->push_back($1); -} +paramscall : %empty { $$ = new ParamsCall(); } %% diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index f258ccc..fa30c65 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -22,9 +22,7 @@ %token TOK_VOID TOK_RETURN TOK_REGISTER TOK_AT TOK_VOLATILE TOK_CONST TOK_ASM %token TOK_IF TOK_ELSE %token TOK_LOOP TOK_WHILE -%token TOK_PRINT -%token TOK_IN TOK_OUT TOK_STEPPER TOK_SERVO -%token TOK_DELAY TOK_AND TOK_OR +%token TOK_AND TOK_OR %token TOK_IDENTIFIER TOK_XIDENTIFIER %token TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE %token TOK_FINT8 TOK_FINT16 TOK_FINT32 TOK_FINT64 @@ -35,7 +33,6 @@ %token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT %union { - char *port; char *ident; char *str; int64_t nint; diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 5b1be43..d2f637e 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -4,7 +4,7 @@ %define parse.error verbose // enable this to trace the parser. Also, set USEDebug=1 at Scanner.cpp. -//%define parse.trace +%define parse.trace %code provides { #define YY_DECL int USElex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) @@ -12,18 +12,25 @@ void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); } -%type globals type_stmts enum_items -%type global register interface type ignore_stmt ignore use type_stmt -%type function function_decl function_impl var_decl cast ignore_param -%type enum enum_item -%type function_params -%type function_param -%type intf_decls -%type const_expr -%type TOK_IDENTIFIER -%type TOK_INTEGER -%type type_impls -%type qualifier +%type globals type_stmts enum_items interface_decls +%type stmts +%type global register interface type type_stmt use +%type function function_decl function_impl +%type enum enum_item const_expr expr interface_impl +%type simplevar_decl cast constructor +%type ignore_stmt ignore_param ignore +%type type_impls + +%type element +%type elements relements array +%type melement +%type melements matrix + +%type function_params +%type function_param + +%type TOK_IDENTIFIER +%type TOK_INTEGER qualifier %printer { fprintf(yyo, "'%s'", $$); } %printer { fprintf(yyo, "'%s'", $$ ? $$->getName().c_str() : ""); } @@ -56,8 +63,8 @@ global : use | register | function | enum - | var_decl { $$ = NULL; } // don't export global vars - | qualifier var_decl { $$ = NULL; } + | simplevar_decl ';' { $$ = NULL; } // don't export global vars + | qualifier simplevar_decl ';' { $$ = NULL; } use : TOK_USE TOK_IDENTIFIER ';' { parseUseFile($2, @TOK_USE); @@ -88,20 +95,23 @@ enum_item : TOK_IDENTIFIER[id] { function : function_decl | function_impl -function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER '(' function_params ')' ';' { - $$ = new FunctionDecl(buildTypes->getType($type, true), $2, $4); +function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' ';' { + $$ = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params); $$->setLocation(@type); } -function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' '{' ignore_stmts '}'[ef] { - vector auxvec; +function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' '{' stmts '}'[ef] { + vector stmts; FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, - std::move(auxvec), @ef); + std::move(stmts), @ef); func->setExternal(true); func->setLocation(@type); $$ = func; } +qualifier : TOK_CONST { $$ = qconst; } + | TOK_VOLATILE { $$ = qvolatile; } + function_params: function_params ',' function_param { $1 -> append($3); $$ = $1; @@ -128,8 +138,8 @@ register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT const_e $$->setLocation(@name); } -interface : TOK_INTF TOK_IDENTIFIER '{' intf_decls '}' { - $$ = new Interface($TOK_IDENTIFIER, std::move(*$intf_decls)); +interface : TOK_INTF TOK_IDENTIFIER '{' interface_decls[intf] '}' { + $$ = new Interface($TOK_IDENTIFIER, std::move(*$intf)); $$->setLocation(@TOK_INTF); } @@ -138,16 +148,25 @@ interface : TOK_INTF TOK_IDENTIFIER '{' '}' { $$->setLocation(@TOK_INTF); } -intf_decls : intf_decls function_decl { +interface_decls : interface_decls function_decl { $1->push_back($function_decl); $$ = $1; } -intf_decls : function_decl { +interface_decls : function_decl { $$ = new vector(); $$->push_back($function_decl); } +//FIXME: Interface only allows function_decls! +interface_impl : TOK_IDENTIFIER[id] '=' TOK_IDENTIFIER[intfname] '{' type_stmts '}' { + vector intf; + intf.push_back($intfname); + UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(intf)); + ut->setLocation(@id); + $$ = ut; +} + type : TOK_TYPE TOK_IDENTIFIER TOK_IMPL type_impls '{' type_stmts '}' { UserType *ut = new UserType($TOK_IDENTIFIER, std::move(*$type_stmts), std::move(*$type_impls)); ut->setLocation(@TOK_TYPE); @@ -173,28 +192,63 @@ type_impls : TOK_IDENTIFIER { } type_stmts : type_stmts type_stmt { - $$->push_back($type_stmt); + if ($type_stmt) + $$->push_back($type_stmt); } type_stmts : type_stmt { $$ = new vector(); - $$->push_back($type_stmt); + if ($type_stmt) + $$->push_back($type_stmt); } -type_stmt : var_decl - | qualifier[q] var_decl { $var_decl->setQualifier((DataQualifier)$q); $$ = $2; } +type_stmt : simplevar_decl ';' + | qualifier[q] simplevar_decl ';' { $simplevar_decl->setQualifier((DataQualifier)$q); $$ = $2; } | function_impl + | interface_impl + | enum -qualifier : TOK_CONST { $$ = qconst; } - | TOK_VOLATILE { $$ = qvolatile; } +simplevar_decl : TOK_IDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } + +array : '{' elements '}' { $$ = $elements; } +matrix : '{' melements '}' { $$ = $melements; } + +melements : melements ',' melement { + $1->append($3); + $$ = $1; +} + +melements : melement { + MatrixElements *mes = new MatrixElements(); + mes->append($1); + $$ = mes; +} -var_decl : TOK_IDENTIFIER '=' const_expr ';' { $$ = new Scalar($1, $3); } -var_decl : TOK_IDENTIFIER '=' cast ';' { $$ = new Scalar($1, $3); } +melement : relements ':' TOK_INTEGER { $$ = new MatrixElement($1, (unsigned)$3); } + | relements { $$ = new MatrixElement($1, 1);} + +relements : '{' elements '}' { $$ = $2; } + +elements : elements ',' element { $1->append($3); + $$ = $1; } + | element { ArrayElements *aes = new ArrayElements(); + aes->append($1); + $$ = aes; } + +element : expr ':' TOK_INTEGER { $$ = new ArrayElement($1, (unsigned)$3); } + | expr { $$ = new ArrayElement($1, 1); } const_expr : TOK_INTEGER { $$ = getNodeForIntConst($1); } | TOK_TRUE { $$ = new Int1(1); } | TOK_FALSE { $$ = new Int1(0); } //TODO: Add other constant nodes here! + +expr : const_expr + | cast + | constructor + //TODO: Add other expr nodes here! cast : TOK_IDENTIFIER[id] '(' ignore_param ')' { ParamsCall *pc = new ParamsCall(); @@ -203,6 +257,13 @@ cast : TOK_IDENTIFIER[id] '(' ignore_param ')' { $$->setLocation(@id); } +constructor : TOK_IDENTIFIER[id] '(' ')' { + ParamsCall *pc = new ParamsCall(); + pc->append(new Node()); + $$ = new FunctionCall($id, pc); + $$->setLocation(@id); +} + ignore_param : ignore_p { $$ = NULL; } | error { $$ = NULL; } @@ -211,13 +272,13 @@ ignore_param : ignore_p { $$ = NULL; } */ ignore_p : TOK_INTEGER { YYERROR; } | TOK_IDENTIFIER { YYERROR; } + +stmts : stmts ignore_stmt { $$ = NULL; } + | ignore_stmt { $$ = NULL; } -ignore_stmts : ignore_stmts ignore_stmt - | ignore_stmt - -ignore_stmt : ignore { $$ = NULL; } - | error '{' ignore_stmts '}' { $$ = NULL; } - | error ';' { $$ = NULL; } +ignore_stmt : ignore { $$ = NULL; } + | error '{' stmts '}' { $$ = NULL; } + | error ';' { $$ = NULL; } /* put here any symbol that can start a stmt (except globals). * to be precise, the FIRST(stmt) of Language.y diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index 7135439..4423f2f 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -25,22 +25,22 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al yyerrorcpp("Variable " + ident.getFullName() + " not defined or not an array/matrix.", this); return NULL; } - auto sym = rsym->getLLVMValue(func); - - // sym type can be GlobalVariable or AllocInst - Type *ty = NULL; - if (auto *aux = dyn_cast(sym)) - ty = aux->getAllocatedType(); - else if (auto *aux = dyn_cast(sym)) - ty = aux->getValueType(); - - ArrayType *arrayTy = NULL; - if (ty->isArrayTy()) { - arrayTy = (ArrayType*)ty; - } - else { - yyerrorcpp("LLVM Symbol " + ident.getFullName() + " is not an array.", this); - return NULL; + + Value *alloc = NULL; + if (ident.isComplex()) { + Identifier istem = ident.getStem(); + Node *stem = istem.getSymbol(getScope()); + alloc = rsym->getLLVMValue(stem); + + if (stem->hasQualifier(qvolatile)) + rsym->setQualifier(qvolatile); + + // TODO: When accessing a.x.func(), need to load a and gep x + //Load loadstem(ident.getStem()); + //loadstem.setParent(this->parent); + //stem = loadstem.generate(func, block, allocblock); + } else { + alloc = rsym->getLLVMValue(func); } Node *indn = getElementIndex(rsym); @@ -52,7 +52,7 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); Value* indexList[2] = {zero, indice}; - GetElementPtrInst* ptr = GetElementPtrInst::Create(arrayTy, sym, ArrayRef(indexList), "", block); + GetElementPtrInst* ptr = GetElementPtrInst::Create(rsym->getLLVMType(), alloc, ArrayRef(indexList), "", block); LoadInst *ret = new LoadInst(ptr->getResultElementType(), ptr, ident.getFullName(), false, block); return ret; } diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 63d0041..a89d5a1 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -4,12 +4,15 @@ #include "BinaryOp.h" #include "Visitor.h" #include "Int16.h" +#include "BackLLVM.h" +#include "FunctionImpl.h" Matrix::Matrix(const char *n, MatrixElements *me) : LinearDataStructure(n), melements(me) { NamedConst *rows = new NamedConst("rows", getNodeForIntConst(me->getLineCount())); NamedConst *cols = new NamedConst("cols", getNodeForIntConst(me->getColumnCount())); addChild(rows); addChild(cols); + dt = tarray; //FIXME } Node* Matrix::getElementIndex(Node *p1, Node *p2) { @@ -23,15 +26,7 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc /* * Matrix is generated as an array and accessed latter accordingly! */ - - //Get Type of elements in Vector of Elements, and define as I. - element_dt = melements->getMatrixType(func); - Type* I = buildTypes->llvmType(element_dt); - - // The matrix size - unsigned int lines = melements->getLineCount(); - unsigned int cols = melements->getColumnCount(); - ArrayType* arrayType = ArrayType::get(I, lines * cols); + createDataType(); // Allocate elements. Supported formats: // {{1:3}:3, {1:2,2}:2} @@ -48,7 +43,7 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Value *val = elValue->generate(func, block, allocblock); if (!val) return NULL; - val = Coercion::Convert(val, I, block, elValue); + val = Coercion::Convert(val, matrixType->getElementType(), block, elValue); if (!dyn_cast(val)) allConst = false; for (int l=0; l < k->count; l++) @@ -63,6 +58,9 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc return NULL; } + auto sp = RobDbgInfo.currScope(); + auto funit = RobDbgInfo.currFile(); + //Allocate matrix as a vector. //Allocate array. if (allocblock == global_alloc) { // when alloc is global @@ -71,23 +69,40 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc for(auto &a : elementValues) constantValues.push_back(dyn_cast(a)); ArrayRef constantRefs(constantValues); - GlobalVariable *gv = new GlobalVariable(*mainmodule, arrayType, + GlobalVariable *gv = new GlobalVariable(*mainmodule, matrixType, false, GlobalValue::InternalLinkage, - ConstantArray::get(arrayType, constantRefs), name); + ConstantArray::get(matrixType, constantRefs), name); gv->setDSOLocal(true); gv->setAlignment(Align(2)); alloc = gv; + + if (debug_info) { + auto di_ptr = DBuilder->createPointerType(buildTypes->diType(getElementDt()), + buildTypes->bitWidth(currentTarget().pointerType)); + auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", + funit, this->getLineNo(), di_ptr, false); + gv->addDebugInfo(d); + } + } else { - alloc = new AllocaInst(arrayType, 0, name, allocblock); + Builder->SetInsertPoint(allocblock); + + if (getGEPIndex() != -1) + alloc = getLLVMValue(func); + else + alloc = Builder->CreateAlloca(matrixType, dataAddrSpace, 0, name); + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); StoreInst *store = NULL; for(unsigned index = 0; index < elementValues.size(); index++) { Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), index); Value* indexList[2] = {zero, idx}; - GetElementPtrInst* gep = GetElementPtrInst::Create(arrayType, alloc, - ArrayRef(indexList), "", block); - store = new StoreInst(elementValues[index], gep, false, block); + Value* gep = Builder->CreateGEP(matrixType, alloc, + ArrayRef(indexList), "elem"); + store = Builder->CreateStore(elementValues[index], gep, false); } } @@ -97,3 +112,22 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc void Matrix::accept(Visitor& v) { v.visit(*this); } + +void Matrix::createDataType() { + if (matrixType != NULL) + return; + + //Get Type of elements in Vector of Elements, and define as I. + element_dt = melements->getMatrixType(); + Type* I = buildTypes->llvmType(element_dt); + + // The matrix size + lines = melements->getLineCount(); + cols = melements->getColumnCount(); + matrixType = ArrayType::get(I, lines * cols); +} + +Type* Matrix::getLLVMType() { + createDataType(); + return matrixType; +} diff --git a/src/Matrix.h b/src/Matrix.h index e7d98cf..ccbd312 100644 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -7,6 +7,11 @@ class Matrix: public LinearDataStructure { private: MatrixElements *melements; + ArrayType *matrixType = NULL; + void createDataType(); + unsigned int lines = 0; + unsigned int cols = 0; + public: Matrix(const char *n, MatrixElements *me); @@ -19,4 +24,6 @@ class Matrix: public LinearDataStructure { } void accept(Visitor& v) override; + + virtual Type *getLLVMType() override; }; diff --git a/src/MatrixElements.cpp b/src/MatrixElements.cpp index 1af9bb0..5507edf 100644 --- a/src/MatrixElements.cpp +++ b/src/MatrixElements.cpp @@ -27,7 +27,7 @@ unsigned MatrixElements::getColumnCount() { return biggest_r; } -DataType MatrixElements::getMatrixType(FunctionImpl *func) { +DataType MatrixElements::getMatrixType() { unsigned intsize = 0; unsigned floatsize = 0; for(auto& j : elements) { diff --git a/src/MatrixElements.h b/src/MatrixElements.h index 828b952..6210d81 100644 --- a/src/MatrixElements.h +++ b/src/MatrixElements.h @@ -21,7 +21,7 @@ class MatrixElements { unsigned getColumnCount(); unsigned getLineCount(); unsigned getElementCount(int position); - DataType getMatrixType(FunctionImpl *func); + DataType getMatrixType(); std::vector const& getElements() { return elements; diff --git a/src/Node.h b/src/Node.h index 48474b9..922e72b 100644 --- a/src/Node.h +++ b/src/Node.h @@ -67,6 +67,10 @@ class Node : public SourceLocation { return dt; } + virtual Type *getLLVMType() { + return buildTypes->llvmType(getDataType()); + } + void setQualifier(DataQualifier dq) { qualifiers.insert(dq); } diff --git a/src/Program.cpp b/src/Program.cpp index de1cbda..5548afb 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -18,7 +18,7 @@ Program::Program() { RobDbgInfo.push_scope(RobDbgInfo.cunit->getFile(), RobDbgInfo.cunit); } - buildTypes = make_unique(currentTarget.pointerType); + buildTypes = make_unique(currentTarget().pointerType); global_alloc = BasicBlock::Create(global_context, "global"); } @@ -117,6 +117,11 @@ void Program::generate() { SymbolizeTree st; st.visit(*this); + /*std::fstream fs; + fs.open("ast", std::fstream::out); + PrintAstVisitor(fs).visit(p); + fs.close();*/ + // generate the program! for(auto n: children()) n->generate(NULL, NULL, global_alloc); diff --git a/src/Scalar.cpp b/src/Scalar.cpp index f319f2d..c16d534 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -167,26 +167,6 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc } } -Value *Scalar::getLLVMValue(Node *stem) { - int gepidx = getGEPIndex(); - if (gepidx != -1) { - Value *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); - Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), gepidx); - Value* indexList[2] = {zero, idx}; - - if (FunctionImpl *func = dynamic_cast(stem)) { - // generating a function of a type: get the gep on the #this parameter - Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); - alloc = Builder->CreateStructGEP(thisTy, func->getThisArg(), gepidx, "gepthis"); - } else { - // accessing a var of a user type: get the gep in the scope (user type) of the scalar - Type *udt = buildTypes->llvmType(stem->getDataType()); - alloc = Builder->CreateStructGEP(udt, stem->getLLVMValue(NULL), gepidx, "gepu"); // FIXME - } - } - return alloc; -} - DataType Scalar::getDataType() { if (dt == BuildTypes::undefinedType) return dt = expr->getDataType(); diff --git a/src/Scalar.h b/src/Scalar.h index 051bbe2..10a3fe6 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -6,7 +6,6 @@ class Scalar: public Variable { private: Node *expr; - int gepIndex = -1; public: Scalar(const char* ident, Node *e); @@ -15,16 +14,6 @@ class Scalar: public Variable { virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual Value* getLLVMValue(Node *stem) override; - - virtual void setGEPIndex(int idx) { - gepIndex = idx; - } - - int getGEPIndex() const { - return gepIndex; - } - virtual bool isConstExpr() override { return hasQualifier(qconst) && expr->isConstExpr(); } diff --git a/src/Scanner.cpp b/src/Scanner.cpp index 26acbfa..fdb90d5 100644 --- a/src/Scanner.cpp +++ b/src/Scanner.cpp @@ -140,6 +140,7 @@ bool parseUseFile(const string& use, location_t loc) { buildStackTop--; buildStackScanner.pop_back(); + buildStack.pop_back(); return true; } diff --git a/src/UserType.cpp b/src/UserType.cpp index 40ffb42..97ad398 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -12,10 +12,9 @@ void UserType::createDataType() { int idx = 0; unsigned startBit = 0; for(auto child : this->children()) { - Scalar *s = dynamic_cast(child); + Variable *s = dynamic_cast(child); if (s) { - DataType sdt = s->getDataType(); - elements.push_back(buildTypes->llvmType(sdt)); + elements.push_back(s->getLLVMType()); s->setGEPIndex(idx++); //FIXME: Fix for data alignment on non-packed structure/type @@ -58,11 +57,20 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all // get vars vector fields; for(auto & [key, stmt] : getSymbols()) { - if (Scalar *c = dynamic_cast(stmt)) { + if (Variable *c = dynamic_cast(stmt)) { fields.push_back(c); } } - + + // generate init function/constructor + FunctionParams *fp = new FunctionParams(); + FunctionImpl *finit = new FunctionImpl((DataType)tvoid, "init", fp, + std::move(fields), *this->getLoct(), true); + finit->addThisArgument(dt); + finit->setUserTypeName(name); + finit->setExternal(declaration); + finit->generate(func, block, allocblock); + // generate functions for(auto & [key, stmt] : getSymbols()) { if (FunctionImpl *f = dynamic_cast(stmt)) { @@ -75,16 +83,8 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all } } - FunctionParams *fp = new FunctionParams(); - FunctionImpl *finit = new FunctionImpl((DataType)tvoid, "init", fp, - std::move(fields), *this->getLoct(), true); - finit->addThisArgument(dt); - finit->setUserTypeName(name); - finit->setExternal(declaration); addChild(finit); addSymbol(finit); - finit->generate(func, block, allocblock); - return NULL; } diff --git a/src/UserType.h b/src/UserType.h index 6696b63..4312337 100644 --- a/src/UserType.h +++ b/src/UserType.h @@ -10,10 +10,11 @@ class Visitor; class UserType: public NamedNode { private: vector implements; - void createDataType(); map startBits; bool declaration = false; + void createDataType(); + public: UserType(const string name, vector &&stmts): NamedNode(name, std::move(stmts)) { } diff --git a/src/Variable.cpp b/src/Variable.cpp new file mode 100644 index 0000000..bef398d --- /dev/null +++ b/src/Variable.cpp @@ -0,0 +1,24 @@ + +#include "Variable.h" +#include "FunctionImpl.h" + +Value *Variable::getLLVMValue(Node *stem) { + int gepidx = getGEPIndex(); + if (gepidx != -1) { + Value *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); + Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), gepidx); + Value* indexList[2] = {zero, idx}; + + FunctionImpl *func = dynamic_cast(stem); + if (func && func->getThisArg()) { + // generating a function of a type: get the gep on the #this parameter + Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); + alloc = Builder->CreateStructGEP(thisTy, func->getThisArg(), gepidx, "gepthis"); + } else { + // accessing a var of a user type: get the gep in the scope (user type) of the scalar + Type *udt = buildTypes->llvmType(stem->getDataType()); + alloc = Builder->CreateStructGEP(udt, stem->getLLVMValue(NULL), gepidx, "gepu"); // FIXME + } + } + return alloc; +} diff --git a/src/Variable.h b/src/Variable.h index a59cad3..38f54cc 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -8,11 +8,18 @@ class Variable: public NamedNode { protected: Value *alloc = NULL; Identifier ident; + int gepIndex = -1; public: Variable(const string &name): NamedNode(name), ident(name) {} - virtual Value* getLLVMValue(Node *stem) override { - return alloc; - } + virtual Value* getLLVMValue(Node *stem) override; + + virtual void setGEPIndex(int idx) { + gepIndex = idx; + } + + int getGEPIndex() const { + return gepIndex; + } }; diff --git a/testnew/general/Makefile b/testnew/general/Makefile index 5efd04b..ffa3943 100644 --- a/testnew/general/Makefile +++ b/testnew/general/Makefile @@ -7,10 +7,8 @@ OS=$(shell uname -o) ifeq ($(OS), Msys) ROBCMP=../../build/robcmp.exe -ENTRY=__main else ROBCMP=../../build/robcmp -ENTRY=main endif ifndef OPT @@ -36,8 +34,10 @@ out/%.ll : %.rob ${ROBCMP} Makefile out/%.tt : %.rob @-./runtest.sh $< $(patsubst %.rob,out/%,$<) +ifeq ($(OS), Msys) % : %.o - ld.lld -e ${ENTRY} $< -o $@ + ${LD} -e __main $< -o $@ +endif test: ${ALL_TT} diff --git a/testnew/general/typeandarrays.rob b/testnew/general/typeandarrays.rob new file mode 100644 index 0000000..e6a2c18 --- /dev/null +++ b/testnew/general/typeandarrays.rob @@ -0,0 +1,30 @@ + +type array_capsule { + + a = {10, 30, 10:2}; + b = {{1, 2, 3}, {4, 5, 6}}; + + int16 getarr(int16 i) { + return a[i]; + } + + int16 getmatrix(int16 i, int16 j) { + return b[i][j]; + } +} + +int16 main() { + c = array_capsule(); + d = c.getarr(2); + e = c.a[1]; + f = c.getmatrix(1, 1); + g = c.b[0][0]; + + if d == 10 and f == 5 { + if e == 30 and g == 1 { + return 0; + } + } + return 1; +} + From 0ca8b3c181bbc9b61c03f18854b88db79a239a7d Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 16 Aug 2023 10:10:26 -0300 Subject: [PATCH 031/117] Partial implementation: implement interface as subtypes --- .../syntaxes/rob.tmLanguage.json | 4 +- rob.vim | 8 +- src/BackLLVM.cpp | 10 ++ src/BuildTypes.cpp | 16 +- src/BuildTypes.h | 32 +++- src/FunctionCall.cpp | 86 +++++++--- src/FunctionCall.h | 11 +- src/FunctionDecl.cpp | 13 +- src/FunctionDecl.h | 27 +++- src/FunctionImpl.cpp | 72 ++++++--- src/FunctionImpl.h | 29 ++-- src/FunctionParams.cpp | 9 +- src/FunctionParams.h | 2 +- src/Header.h | 1 + src/Interface.cpp | 43 ++++- src/Interface.h | 6 +- src/Language.y | 11 +- src/LanguageUse.y | 2 - src/Load.cpp | 29 ++-- src/MemCopy.cpp | 51 ++++++ src/MemCopy.h | 21 +++ src/Node.cpp | 32 ++-- src/Node.h | 11 +- src/Scalar.cpp | 121 +++++++------- src/Scalar.h | 2 +- src/Scanner.cpp | 24 +-- src/Scanner.h | 3 - src/UserType.cpp | 148 +++++++++++++++--- src/UserType.h | 21 ++- src/Variable.cpp | 2 +- src/Variable.h | 16 ++ testnew/general/byref.rob | 38 +++++ testnew/general/intfinternal.rob | 40 +++++ testnew/general/intfscope.rob | 46 ++++++ testnew/general/replace_buildfail.rob | 23 +++ testnew/general/simpleptr.rob | 19 +++ testnew/general/simplesubtype.rob | 18 +++ 37 files changed, 822 insertions(+), 225 deletions(-) create mode 100644 src/MemCopy.cpp create mode 100644 src/MemCopy.h create mode 100644 testnew/general/byref.rob create mode 100644 testnew/general/intfinternal.rob create mode 100644 testnew/general/intfscope.rob create mode 100644 testnew/general/replace_buildfail.rob create mode 100644 testnew/general/simpleptr.rob create mode 100644 testnew/general/simplesubtype.rob diff --git a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json index 8c44d99..1ca058e 100644 --- a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json +++ b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json @@ -42,13 +42,13 @@ "keywords": { "patterns": [{ "name": "keyword.control.rob", - "match": "\\b(while|loop|if|else|delay|print|return|register|at|volatile|const|type|interface|implements|use|and|or|enum)\\b" + "match": "\\b(while|loop|if|else|delay|print|return|register|at|volatile|const|type|interface|implements|use|and|or|copy)\\b" }] }, "types": { "patterns": [{ "name": "storage.type.rob", - "match": "\\b(void|char|int8|int16|int32|int64|long|unsigned|float|double|bool)\\b" + "match": "\\b(void|char|int8|int16|int32|int64|long|unsigned|float|double|bool|enum)\\b" }, { "match": "(\\w+)\\s+(\\w+)[\\(\\),]", diff --git a/rob.vim b/rob.vim index 41ca3bd..807ba7c 100644 --- a/rob.vim +++ b/rob.vim @@ -7,8 +7,8 @@ if exists("b:current_syntax") finish endif -syn keyword keywords while loop if else delay print return register at volatile const asm type use enum -syn keyword typeKeywords void char int8 int16 int32 int64 long unsigned float double bool +syn keyword keywords while loop if else delay print return register at volatile const asm type use interface copy +syn keyword typeKeywords void char int8 int16 int32 int64 long unsigned float double bool enum syn keyword operatorKeywords and or quando esta servo syn keyword booleanKeyword true false @@ -21,9 +21,9 @@ syn match outPortKey "\" syn match stringSpecial "\\." syn match commentLine "\/\/.*" -syn region commentBlock start="/\*" end="\*/" fold containedin=stmtBlock +syn region stmtBlock start="{" end="}" fold contains=ALL transparent syn region stringConstant start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=stringSpecial -syn region stmtBlock start="{" end="}" keepend transparent fold +syn region commentBlock start="/\*" end="\*/" fold contains=ALL let b:current_syntax = "rob" diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 0d5e0ab..e82f12a 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -116,6 +116,7 @@ void print_llvm_ir(char opt_level) { passBuilder.crossRegisterProxies( loopAnalysisManager, functionAnalysisManager, cGSCCAnalysisManager, moduleAnalysisManager); + bool debugopt = false; OptimizationLevel ol; switch (opt_level) { case '0': ol = OptimizationLevel::O0; break; @@ -123,10 +124,19 @@ void print_llvm_ir(char opt_level) { case '2': ol = OptimizationLevel::O2; break; case '3': ol = OptimizationLevel::O3; break; case 's': ol = OptimizationLevel::Os; break; + case 'd': debugopt = true; break; case 'z': default : ol = OptimizationLevel::Oz; break; } + // This is used to see the llvm IR prior to any analysis. + // Sometimes when adding new features, we want to see the IR even + // it being invalid. + if (debugopt) { + mainmodule->print(outs(), nullptr); + return; + } + ModulePassManager modulePassManager; if (ol == OptimizationLevel::O0) modulePassManager = passBuilder.buildO0DefaultPipeline(ol); diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 3413bf7..c3dc131 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -62,7 +62,6 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi DataType id; const DataLayout &dl = mainmodule->getDataLayout(); - uint32_t align = dl.getABITypeAlign(llvmType).value(); uint64_t bitWidth = typeBitWidth; if (typeBitWidth == 0 && llvmType->isSized()) @@ -81,6 +80,8 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi info.isComplex = !isEnum; info.dwarfEnc = 0; info.bitWidth = bitWidth; + info.isInternal = false; + info.isInterface = false; if (debug_info) { unsigned offset = 0; @@ -97,6 +98,10 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi int i = 0; elems.reserve(members.size()); for(Node *m : members) { + DataType mdt = m->getDataType(); + if (mdt == -1 || tinfo[mdt].bitWidth == 0) { + continue; + } Type *memberTy = llvmType->getContainedType(i); uint64_t memberBitWidth = dl.getTypeSizeInBits(memberTy); uint32_t memberAlign = dl.getABITypeAlign(memberTy).value(); @@ -110,10 +115,17 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi } auto dielems = DBuilder->getOrCreateArray(elems); info.diType = DBuilder->createClassType(RobDbgInfo.currScope(), name, - RobDbgInfo.currFile(), userType->getLineNo(), bitWidth, align, 0, + RobDbgInfo.currFile(), userType->getLineNo(), bitWidth, 1, 0, DINode::DIFlags::FlagZero, nullptr, dielems); unsigned ptbw = tinfo[currentTarget().pointerType].bitWidth; info.diPointerType = DBuilder->createPointerType(info.diType, 8); } return id; } + +Type *BuildTypes::llvmType(DataType tid) { + if (tid == -1) + return NULL; + else + return tinfo[tid].llvmType; +} diff --git a/src/BuildTypes.h b/src/BuildTypes.h index 3f7d619..a0f8609 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -25,6 +25,8 @@ struct DataTypeInfo { SourceLocation *sl; bool isDefined; bool isComplex; + bool isInterface; + bool isInternal; DataTypeInfo() {} @@ -37,11 +39,14 @@ struct DataTypeInfo { this->diPointerType = NULL; this->isDefined = false; this->isComplex = false; + this->isInternal = false; + this->isInterface = false; } DataTypeInfo(const char* name, unsigned bitWidth, Type *llvmType, unsigned dwarfEnc): name(name), bitWidth(bitWidth), llvmType(llvmType), dwarfEnc(dwarfEnc), diType(NULL), - diPointerType(NULL), sl(NULL), isDefined(true), isComplex(false) {}; + diPointerType(NULL), sl(NULL), isDefined(true), isComplex(false), isInternal(false), + isInterface(false) {}; }; class BuildTypes { @@ -77,10 +82,7 @@ class BuildTypes { return tinfo[tid].bitWidth; } - Type *llvmType(DataType tid) { - assert(tid != -1 && "Undefined type"); - return tinfo[tid].llvmType; - } + Type *llvmType(DataType tid); DIType *diType(DataType tid) { assert(tid != -1 && "Undefined type"); @@ -114,9 +116,29 @@ class BuildTypes { } bool isComplex(DataType tid) { + assert(tid != -1 && "Undefined type"); return tinfo[tid].isComplex; } + bool isInternal(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isInternal; + } + + void setInternal(DataType tid, bool v) { + assert(tid != -1 && "Undefined type"); + tinfo[tid].isInternal = v; + } + + void setInterface(DataType tid, bool v) { + assert(tid != -1 && "Undefined type"); + tinfo[tid].isInterface = v; + } + + bool isInterface(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isInterface; + } }; // TODO: Replace all places with buildType::name diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 8f1d494..4c2e488 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -7,11 +7,12 @@ #include "Load.h" #include "Visitor.h" #include "BackLLVM.h" +#include "UserType.h" DataType FunctionCall::getDataType() { if (dt == BuildTypes::undefinedType) { - // is a cast? + // is a cast or constructor? dt = buildTypes->getType(ident.getFullName()); if (parameters->getNumParams() <= 1 && dt != BuildTypes::undefinedType) { return dt; @@ -32,6 +33,7 @@ void FunctionCall::loadFunctionStem(FunctionImpl *func, BasicBlock *block, Basic Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + RobDbgInfo.emitLocation(this); string name = ident.getFullName(); // check if it is a cast call @@ -45,25 +47,37 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock Cast ca(dt, parameters->getParamElement(0)); return ca.generate(func, block, allocblock); - } else if (p == 0) { // it's a constructor - RobDbgInfo.emitLocation(this); - + } else if (p == 0) { // it's a constructor // alloc - Value *var = leftValue; - if (leftValue == NULL) { + Value *var = leftValue->getLLVMValue(func); + if (var == NULL) { Builder->SetInsertPoint(allocblock); - var = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, 0, leftName); + var = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, 0, + leftValue->getName()); + leftValue->setAlloca(var); + leftValue->setDataType(dt); + if (debug_info) + RobDbgInfo.declareVar(this, var, allocblock); } vector args; args.push_back(var); // call #init Node *type = findSymbol(name); + if (!type) + return NULL; Node *fsymbol = type->findMember("init"); - FunctionImpl *initfunc = dynamic_cast(fsymbol); + if (!fsymbol) + return NULL; + FunctionBase *initfunc = dynamic_cast(fsymbol); + + if (initfunc->needsParent()) { + args.push_back(initfunc->findMember("#this")->getLLVMValue(NULL)); + } + Builder->SetInsertPoint(block); Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); - return var; + return NULL; } } @@ -76,32 +90,49 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock } FunctionBase *fsymbol = dynamic_cast(symbol); - Function *cfunc = dyn_cast(symbol->getLLVMValue(func)); - if (fsymbol == NULL || cfunc == NULL) { + if (fsymbol == NULL) { yyerrorcpp("Symbol " + name + " is not a function.", this); return NULL; } dt = fsymbol->getDataType(); - bool this_param = false; - Value *stem = NULL; + int additionalParams = 0; + Value *parent = NULL; + DataType parentdt = BuildTypes::undefinedType; + Value *stem = func->getThisArg(); + DataType stemdt = func->getThisArgDt(); + if (stem) + additionalParams = 1; + + Builder->SetInsertPoint(block); if (ident.isComplex()) { Identifier istem = ident.getStem(); Node *n = istem.getSymbol(getScope()); - stem = n->getLLVMValue(func); + + if (buildTypes->isInternal(n->getDataType())) { + parent = func->getThisArg(); + parentdt = func->getThisArgDt(); + stem = n->getLLVMValue(func); + stemdt = n->getDataType(); + additionalParams = 2; + } + else { + stem = n->getLLVMValue(func); + stemdt = n->getDataType(); + additionalParams = 1; + } // TODO: When accessing a.x.func(), need to load a and gep x //Load loadstem(ident.getStem()); //loadstem.setParent(this->parent); //stem = loadstem.generate(func, block, allocblock); - - this_param = true; } - if (fsymbol->getNumParams() != parameters->getNumParams() + this_param) { + if (fsymbol->getNumCodedParams() != parameters->getNumParams()) { yyerrorcpp(string_format("Function %s has %d argument(s) but was called with %d.", - name.c_str(), fsymbol->getNumParams(), parameters->getNumParams()), this); + name.c_str(), fsymbol->getNumCodedParams(), + parameters->getNumParams()), this); yywarncpp("The function declaration is here.", symbol); return NULL; } @@ -113,7 +144,9 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock return NULL; DataType pdt = fsymbol->getParameters().getParamType(i); - if (!buildTypes->isComplex(pdt)) { + if (buildTypes->isInterface(pdt)) { + valor = Builder->CreateLoad(valor->getType()->getPointerTo(), valor, "defer"); + } else if (!buildTypes->isComplex(pdt)) { //TODO: we don't support cohercion between user types yet Type *pty = buildTypes->llvmType(pdt); valor = Coercion::Convert(valor, pty, block, this); @@ -121,12 +154,23 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock args.push_back(valor); } - if (this_param) + if (stem) { + if (buildTypes->isInterface(stemdt)) + stem = Builder->CreateLoad(stem->getType()->getPointerTo(), stem, "defer"); args.push_back(stem); + } + if (parent) { + if (buildTypes->isInterface(parentdt)) + parent = Builder->CreateLoad(parent->getType()->getPointerTo(), parent, "defer"); + args.push_back(parent); + } ArrayRef argsRef(args); - RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(allocblock); + Value *vfunc = symbol->getLLVMValue(func); + Function *cfunc = dyn_cast(vfunc); + Builder->SetInsertPoint(block); return Builder->CreateCall(cfunc, argsRef); } diff --git a/src/FunctionCall.h b/src/FunctionCall.h index 6b09b05..b4b0020 100644 --- a/src/FunctionCall.h +++ b/src/FunctionCall.h @@ -4,17 +4,17 @@ #include "Node.h" #include "ParamsCall.h" #include "Identifier.h" +#include "Variable.h" class FunctionCall: public Node { private: Identifier ident; ParamsCall *parameters; Node *symbol = NULL; - Value *leftValue = NULL; - string leftName; + Variable *leftValue = NULL; public: - FunctionCall(const char *name, ParamsCall *pc): ident(name) { + FunctionCall(const string& name, ParamsCall *pc): ident(name) { parameters = pc; } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; @@ -22,9 +22,8 @@ class FunctionCall: public Node { virtual DataType getDataType() override; - virtual void setLeftValue(Value *lv, const string& name) override { - leftValue = lv; - leftName = name; + virtual void setLeftValue(Variable *symbol) override { + leftValue = symbol; } std::vector const& getParameters() { diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index e438dfe..20a7aa1 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -2,6 +2,15 @@ #include "FunctionDecl.h" #include "BackLLVM.h" +void FunctionBase::addThisArgument(DataType dt) { + thisArgDt = dt; + FunctionParam *fp = new FunctionParam("#this", dt); + fp->setScope(this); + parameters->append(fp); + symbols[fp->getName()] = fp; +} + + bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { bool valid = true; Type *xtype = buildTypes->llvmType(dt); @@ -9,7 +18,7 @@ bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { yyerrorcpp(string_format("Type %s not defined.", buildTypes->name(dt)), this); valid = false; } - for (int i = 0; i < parameters->getNumParams(); i++) { + for (int i = 0; i < parameters->getParameters().size(); i++) { DataType dt = parameters->getParamType(i); Type *atype = buildTypes->llvmType(dt); if (buildTypes->isComplex(dt)) { @@ -41,7 +50,7 @@ Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocbloc Type *xtype = buildTypes->llvmType(dt); FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, codeAddrSpace, name, mainmodule); + Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, codeAddrSpace, getFinalName(), mainmodule); nfunc->setDSOLocal(true); nfunc->setCallingConv(CallingConv::C); diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index feb52eb..1528e2e 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -11,6 +11,8 @@ class FunctionBase: public NamedNode { bool declaration = true; bool constructor = false; bool external = false; + DataType thisArgDt = BuildTypes::undefinedType; + string userTypeName; bool validateAndGetArgsTypes(std::vector &args); @@ -40,8 +42,8 @@ class FunctionBase: public NamedNode { return func; } - unsigned getNumParams() const { - return parameters->getNumParams(); + unsigned getNumCodedParams() const { + return parameters->getNumCodedParams(); } bool isDeclaration() { @@ -59,6 +61,27 @@ class FunctionBase: public NamedNode { bool isExternal() { return external; } + + void addThisArgument(DataType dt); + + DataType getThisArgDt() const { + return thisArgDt; + } + + void setUserTypeName(const string& ut) { + userTypeName = ut; + } + + string getFinalName() { + if (userTypeName == "") + return name; + else + return userTypeName + "#" + name; + } + + virtual bool needsParent() { + return false; + } }; class FunctionDecl: public FunctionBase { diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index a53255b..c54599f 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -8,21 +8,21 @@ FunctionImpl::FunctionImpl(DataType dt, string name, FunctionParams *fp, vector< this->declaration = false; this->endfunction = ef; - // params needs to be the first inserted children - // to fill the symbols table prior to their use in stmts for(auto p: fp->getParameters()) { - node_children.insert(node_children.begin(), p); - } + symbols[p->getName()] = p; + p->setScope(this); + } } -Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblock) { - +bool FunctionImpl::preGenerate() { + preGenerated = true; + Node *symbol = findSymbol(name); FunctionDecl *fsymbol = dynamic_cast(symbol); if (symbol != NULL && symbol != this && fsymbol != NULL && !fsymbol->isDeclaration()) { yyerrorcpp("Function/symbol " + name + " already defined.", this); yyerrorcpp(name + " was first defined here.", symbol); - return NULL; + return false; } Type *xtype = buildTypes->llvmType(dt); @@ -33,7 +33,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo } else { std::vector arg_types; if (!validateAndGetArgsTypes(arg_types)) - return NULL; + return false; FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); func = Function::Create(ftype, Function::ExternalLinkage, codeAddrSpace, getFinalName(), mainmodule); @@ -43,9 +43,6 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo if (name == "main") func->setName("__main"); #endif - - if (isExternal()) - return NULL; func->setDSOLocal(true); llvm::AttrBuilder attrs(global_context); @@ -54,8 +51,11 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo attrs.addAttribute("frame-pointer", "all"); attrs.addAttribute("stack-protector-buffer-size", "8"); - if (name == "init") // inline constructors + /*if (name == "init") // inline constructors attrs.addAttribute(Attribute::InlineHint); + else + if (node_children.size() == 1) + attrs.addAttribute(Attribute::AlwaysInline);*/ if (name == "__vectors") { // FIXME: remove after adding functions attributes to language func->setSection(".vectors"); @@ -75,8 +75,11 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo RobDbgInfo.push_scope(funit, sp); } - BasicBlock *falloc = BasicBlock::Create(global_context, "entry", func); - BasicBlock *fblock = BasicBlock::Create(global_context, "body", func); + if (isExternal()) + return true; + + falloc = BasicBlock::Create(global_context, "entry", func); + fblock = BasicBlock::Create(global_context, "body", func); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(falloc); @@ -88,6 +91,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo const string& argname = fp->getName(); Arg.setName(argname); + //Arg.addAttr(Attribute::NoUndef); Value *variable = &Arg; if (!buildTypes->isComplex(ptype)) @@ -95,6 +99,8 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo if (argname == "#this") { thisArg = variable; + } else if (argname == "#parent") { + parentArg = variable; } fp->setAlloca(variable); @@ -113,6 +119,19 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo Idx++; } + return true; +} + +Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblock) { + + if (!preGenerated) { + if (!preGenerate()) + return NULL; + } + + if (isExternal()) + return NULL; + Value *last_block = generateChildren(this, fblock, falloc); if (!last_block) last_block = fblock; @@ -123,6 +142,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo Builder->SetInsertPoint(lb); RobDbgInfo.emitLocation(&endfunction); if (lb->getTerminator() == NULL) { + Type *xtype = buildTypes->llvmType(dt); if (!xtype->isVoidTy()) { Value *ret = ConstantInt::get(xtype, 0); Builder->CreateRet(ret); @@ -151,13 +171,15 @@ DISubroutineType *FunctionImpl::getFunctionDIType() { bool FunctionImpl::validateImplementation(FunctionDecl *decl) { bool result = true; FunctionParams& decl_parameters = decl->getParameters(); - if (parameters->getNumParams() != decl_parameters.getNumParams()) { + unsigned pnum_decl = decl_parameters.getNumCodedParams(); + unsigned pnum_impl = parameters->getNumCodedParams(); + if (pnum_impl != pnum_decl) { yyerrorcpp(string_format("The number of arguments differs between function declaration(%d) and definition(%d).", - decl_parameters.getNumParams(), parameters->getNumParams()), this); + pnum_decl, pnum_impl), this); yywarncpp("The function declaration is here.", decl); result = false; } - int compareno = std::min(parameters->getNumParams(), decl_parameters.getNumParams()); + int compareno = std::min(pnum_impl, pnum_decl); for(int i = 0; i < compareno; i++) { FunctionParam *p = decl_parameters.getParameters()[i]; if (p->getDataType() != parameters->getParamType(i)) { @@ -175,14 +197,24 @@ bool FunctionImpl::validateImplementation(FunctionDecl *decl) { yywarncpp("The function declaration is here.", decl); result = false; } + return result; } -void FunctionImpl::addThisArgument(DataType dt) { - thisArgDt = dt; - parameters->append(new FunctionParam("#this", dt)); +void FunctionImpl::addParentArgument(DataType dt) { + parentArgDt = dt; + FunctionParam *fp = new FunctionParam("#parent", dt); + fp->setScope(this); + parameters->append(fp); + symbols[fp->getName()] = fp; } void FunctionImpl::accept(Visitor& v) { v.visit(*this); } + +Value* FunctionImpl::getLLVMValue(Node *) { + if (!preGenerated) + preGenerate(); + return func; +} diff --git a/src/FunctionImpl.h b/src/FunctionImpl.h index 7b5f26c..bc3897b 100644 --- a/src/FunctionImpl.h +++ b/src/FunctionImpl.h @@ -9,9 +9,14 @@ class Visitor; class FunctionImpl: public FunctionBase { private: SourceLocation endfunction; - DataType thisArgDt = BuildTypes::undefinedType; Value *thisArg = NULL; - string userTypeName; + DataType parentArgDt = BuildTypes::undefinedType; + Value *parentArg = NULL; + bool preGenerated = false; + BasicBlock *falloc = NULL; + BasicBlock *fblock = NULL; + + bool preGenerate(); public: FunctionImpl(DataType dt, string name, FunctionParams *fp, vector &&stmts, location_t ef, @@ -23,27 +28,25 @@ class FunctionImpl: public FunctionBase { bool validateImplementation(FunctionDecl *decl); - void addThisArgument(DataType dt); + void addParentArgument(DataType dt); Value *getThisArg() const { return thisArg; } - DataType getThisArgDt() const { - return thisArgDt; + Value *getParentArg() const { + return parentArg; } - void setUserTypeName(const string& ut) { - userTypeName = ut; + DataType getParentArgDt() const { + return parentArgDt; } - string getFinalName() { - if (userTypeName == "") - return name; - else - return userTypeName + "#" + name; + virtual bool needsParent() override { + return parentArg != NULL; } virtual void accept(Visitor& v) override; - + + virtual Value *getLLVMValue(Node *) override; }; diff --git a/src/FunctionParams.cpp b/src/FunctionParams.cpp index 8d0193f..0fa6247 100644 --- a/src/FunctionParams.cpp +++ b/src/FunctionParams.cpp @@ -7,8 +7,13 @@ void FunctionParams::append(FunctionParam *e) { parameters.push_back(e); }; -unsigned FunctionParams::getNumParams() { - return parameters.size(); +unsigned FunctionParams::getNumCodedParams() { + unsigned num = 0; + for(auto p : parameters) { + if (p->getName()[0] != '#') // don't count parameters #this and #parent + num++; + } + return num; }; DataType FunctionParams::getParamType(int position) { diff --git a/src/FunctionParams.h b/src/FunctionParams.h index 7042c94..2e77e0b 100644 --- a/src/FunctionParams.h +++ b/src/FunctionParams.h @@ -28,7 +28,7 @@ class FunctionParams { FunctionParams(); void append(FunctionParam *fp); - unsigned getNumParams(); + unsigned getNumCodedParams(); DataType getParamType (int position); const string getParamName (int position); diff --git a/src/Header.h b/src/Header.h index f8b423a..808cd39 100644 --- a/src/Header.h +++ b/src/Header.h @@ -58,5 +58,6 @@ #include "Interface.h" #include "UserType.h" #include "Enum.h" +#include "MemCopy.h" extern Node* getNodeForIntConst(int64_t i); diff --git a/src/Interface.cpp b/src/Interface.cpp index affc9da..9ef4484 100644 --- a/src/Interface.cpp +++ b/src/Interface.cpp @@ -2,10 +2,24 @@ #include "Interface.h" #include "UserType.h" #include "FunctionImpl.h" +#include "FunctionDecl.h" +#include "Int1.h" void Interface::createDataType() { - StructType *intftype = StructType::create(global_context, name); - unsigned dt = buildTypes->addDataType(this, intftype); + // TRY: prevent opaque type + // the interface type is replaced at link stage + /*Scalar *no_opaque = new Scalar("no_opaque", new Int1(0)); + no_opaque->setGEPIndex(0); + addChild(no_opaque); + addSymbol(no_opaque); + + std::vector elements; + elements.push_back(Type::getInt1Ty(global_context)); + + StructType *intftype = StructType::create(global_context, ArrayRef(elements), getName());*/ + StructType *intftype = StructType::create(global_context, getName()); + dt = buildTypes->addDataType(this, intftype); + buildTypes->setInterface(dt, true); if (dt == BuildTypes::undefinedType) { yyerrorcpp("Type " + name + " alread defined.", this); yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); @@ -13,10 +27,27 @@ void Interface::createDataType() { } Value *Interface::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - /*printf("Interface %s defined with:\n", name.c_str()); - for(const auto n : getSymbols()) { - printf("\t%s\n", n.first.c_str()); - }*/ + + // generate init function/constructor + /*FunctionParams *fp = new FunctionParams(); + FunctionDecl *finit = new FunctionDecl((DataType)tvoid, "init", fp); + finit->addThisArgument(dt); + finit->setUserTypeName(getName()); + finit->setExternal(true); + addChild(finit); + addSymbol(finit);*/ + + // set function parameters + for(Node *n : node_children) { + FunctionDecl *fd = dynamic_cast(n); + if (fd) { + fd->setUserTypeName(getName()); + fd->addThisArgument(dt); + fd->setExternal(true); + fd->generate(func, block, allocblock); + } + } + return NULL; } diff --git a/src/Interface.h b/src/Interface.h index c9a21d9..5920ae5 100644 --- a/src/Interface.h +++ b/src/Interface.h @@ -8,7 +8,9 @@ class Interface: public NamedNode { void createDataType(); public: - Interface(const string& name) : NamedNode(name) {} + Interface(const string& name) : NamedNode(name) { + createDataType(); + } Interface(const string& name, vector stmts): NamedNode(name, std::move(stmts)) { createDataType(); @@ -17,4 +19,6 @@ class Interface: public NamedNode { virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; bool validateImplementation(UserType *ut); + + }; diff --git a/src/Language.y b/src/Language.y index e98fbc3..ff2c275 100644 --- a/src/Language.y +++ b/src/Language.y @@ -34,7 +34,6 @@ %type TOK_DOUBLE %type TOK_LDOUBLE %type TOK_STRING asminline -%type TOK_STEPPER %% @@ -275,6 +274,7 @@ stmt : ident_or_xident '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Lo | ident_or_xident '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6);} | ident_or_xident '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9); } | asminline ';' { $$ = new InlineAssembly($1); $$->setLocation(@1); } + | qualifier simplevar_decl ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } | simplevar_decl ';' | complexvar_set ';' | returnblock ';' @@ -394,12 +394,17 @@ unary : '-' factor { $$ = new BinaryOp($2, '*', getNodeForIntConst(-1)); } ; call_or_cast : ident_or_xident[id] '(' paramscall ')' { - $$ = new FunctionCall($id, $paramscall); + if (strncmp("copy", $id, 4) == 0 && $paramscall->getNumParams() == 1) + $$ = new MemCopy($paramscall->getParamElement(0)); + //else if buildTypes->get($id) && complex, call constructor + else { + $$ = new FunctionCall($id, $paramscall); + } $$->setLocation(@id); } paramscall : paramscall ',' expr { - $1 -> append($3); + $1->append($3); $$ = $1; } diff --git a/src/LanguageUse.y b/src/LanguageUse.y index d2f637e..11ca2d3 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -293,8 +293,6 @@ ignore : TOK_IDENTIFIER { YYERROR; } | TOK_ELSE { YYERROR; } | TOK_LOOP { YYERROR; } | TOK_ASM { YYERROR; } - | TOK_PRINT { YYERROR; } - | TOK_DELAY { YYERROR; } %% diff --git a/src/Load.cpp b/src/Load.cpp index 856e06f..59f4ae4 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -8,7 +8,7 @@ DataType Load::getDataType() { if (dt == BuildTypes::undefinedType) { - Node *rsym = ident.getSymbol(getScope()); + Node *rsym = ident.getSymbol(getScope(), false); if (rsym) { dt = rsym->getDataType(); } @@ -18,13 +18,20 @@ DataType Load::getDataType() { Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - Node *isymbol = ident.getSymbol(getScope()); + Node *isymbol = ident.getSymbol(getScope(), false); + if (!isymbol) + isymbol = ident.getSymbol(func, false); + if (isymbol && isymbol->isConstExpr()) return isymbol->getLLVMValue(func); Variable *symbol = dynamic_cast(isymbol); - if (!symbol) + if (!symbol) { + yyerrorcpp("Symbol " + ident.getFullName() + " not found.", this); return NULL; + } + + dt = isymbol->getDataType(); if (block == NULL && (allocblock == NULL || allocblock == global_alloc)) { // trying to load a variable to initialize a global one. @@ -79,26 +86,12 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl if (!alloc) return NULL; // Caused by an error on previous statement that defines the symbol - if (buildTypes->isComplex(symbol->getDataType())) + if (buildTypes->isComplex(symbol->getDataType())) return alloc; else { Type *ty = buildTypes->llvmType(symbol->getDataType()); return Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), ident.getFullName()); } - - /*if (complexIdent) { - // this code does: - // v = symbol->value << pointerbits - field_start - field_width - // v = v >> pointer_bits - field_width - // - - int bs = buildTypes->bitWidth(rsym->dt) - field.bitWidth; - if (bs - field.startBit > 0) - v = Builder->CreateShl(v, ConstantInt::get(ty, bs - field.startBit)); - if (bs > 0) - v = Builder->CreateAShr(v, ConstantInt::get(ty, bs)); - v = Builder->CreateTrunc(v, buildTypes->llvmType(field.fieldDataType)); - }*/ } bool Load::isConstExpr() { diff --git a/src/MemCopy.cpp b/src/MemCopy.cpp new file mode 100644 index 0000000..4ae7aa7 --- /dev/null +++ b/src/MemCopy.cpp @@ -0,0 +1,51 @@ + +#include "MemCopy.h" +#include "Load.h" +#include "BackLLVM.h" +#include "FunctionImpl.h" + +void MemCopy::setLeftValue(Variable *symbol) { + leftValue = symbol; +} + +Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + Value *exprv = expr->generate(func, block, allocblock); + dt = expr->getDataType(); + Type *exprvty = exprv->getType(); + + Type *leftvty; + Builder->SetInsertPoint(allocblock); + Value *dest = leftValue->getLLVMValue(func); + if (dest) { + leftvty = dest->getType(); + } else { + leftvty = buildTypes->llvmType(dt); + dest = Builder->CreateAlloca(leftvty, dataAddrSpace, nullptr, leftValue->getName()); + leftValue->setAlloca(dest); + leftValue->setDataType(dt); + if (debug_info) + RobDbgInfo.declareVar(this, dest, allocblock); + } + + if (!dest || !expr || !leftvty->isPointerTy() || + !exprvty->isPointerTy()) { + yyerrorcpp("Can not copy these operands.", this); + return NULL; + } + + Value *srcalloc = Builder->CreateAlloca(exprvty, dataAddrSpace, nullptr, "src"); + + Builder->SetInsertPoint(block); + Value *src = Builder->CreateStore(exprv, srcalloc); + + const DataLayout &dl = mainmodule->getDataLayout(); + Value *size = ConstantInt::get(Type::getInt32Ty(global_context), dl.getTypeAllocSize(leftvty)); + + Builder->CreateMemCpy(dest, Align(1), srcalloc, Align(1), size); + + return NULL; +} diff --git a/src/MemCopy.h b/src/MemCopy.h new file mode 100644 index 0000000..1003d1b --- /dev/null +++ b/src/MemCopy.h @@ -0,0 +1,21 @@ + +#pragma once + +#include "Node.h" +#include "Variable.h" + +class MemCopy: public Node { +private: + Node *expr; + Variable *leftValue = NULL; + +public: + MemCopy(Node *expr) { + addChild(expr); + this->expr = expr; + } + + virtual void setLeftValue(Variable *symbol) override; + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; +}; diff --git a/src/Node.cpp b/src/Node.cpp index ea8e347..02d9a2a 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -22,14 +22,17 @@ void Node::accept(Visitor& v) { Node* Node::findMember(const string& name) { // look for pseudo fields (array, matrix, register) Node *m = findSymbol(name, false); + if (!m) { + // getDataType forces getting the dataType, case it was not queried yet + DataType this_dt = getDataType(); + if (this_dt == BuildTypes::undefinedType) + return m; - // force getting dataType in case it was not queried yet - DataType this_dt = getDataType(); - - if (!m && this_dt != BuildTypes::undefinedType) { // look for fields in the base type const char *ut_name = buildTypes->name(this_dt); Node *ut = findSymbol(ut_name); + if (!ut) + return NULL; m = ut->findSymbol(name, false); } return m; @@ -53,8 +56,8 @@ void Node::addChild(Node *n) { } void Node::addSymbol(NamedNode *nm) { - // if the variable is already defined in a parent scope, - // don't add it to symbols table in inner scopes. + // if the variable is already defined here or in a parent + // scope, don't add it again. if (!findSymbol(nm->getName(), true)) { symbols[nm->getName()] = nm; } @@ -68,12 +71,6 @@ void Node::setScope(Node *s) { if (scope != NULL) assert(scope == NULL && "node already has a scope"); scope = s; -/* if (hasName()) - s->symbols[getName()] = dynamic_cast(this); - for(auto& n : node_children) { - if (!n->scope) - n->setScope(s); - }*/ } Value* Node::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { @@ -89,7 +86,16 @@ Value* Node::generateChildren(FunctionImpl *func, BasicBlock *block, BasicBlock return block; } -extern Node* getNodeForIntConst(int64_t i) { +Type* Node::getLLVMType() { + DataType aux = getDataType(); + Type *taux = buildTypes->llvmType(getDataType()); + if (buildTypes->isInterface(aux)) + return taux->getPointerTo(); + else + return taux; +} + +Node* getNodeForIntConst(int64_t i) { if (i >= SCHAR_MIN && i <= SCHAR_MAX) return new Int8(i); else if (i >= SHRT_MIN && i <= SHRT_MAX) diff --git a/src/Node.h b/src/Node.h index 922e72b..a8137c9 100644 --- a/src/Node.h +++ b/src/Node.h @@ -8,6 +8,7 @@ class Visitor; class NamedNode; class UserType; class FunctionImpl; +class Variable; class Node : public SourceLocation { protected: @@ -39,7 +40,7 @@ class Node : public SourceLocation { return false; } - virtual string const getName() const { + virtual const string getName() const { return ""; } @@ -67,9 +68,7 @@ class Node : public SourceLocation { return dt; } - virtual Type *getLLVMType() { - return buildTypes->llvmType(getDataType()); - } + virtual Type *getLLVMType(); void setQualifier(DataQualifier dq) { qualifiers.insert(dq); @@ -83,7 +82,7 @@ class Node : public SourceLocation { return NULL; } - virtual void setLeftValue(Value *lv, const string& name) {} + virtual void setLeftValue(Variable *symbol) {} friend class UserType; friend class Program; @@ -99,7 +98,7 @@ class NamedNode: public Node { NamedNode(const string &name, vector &&children) : Node(std::move(children)), name(name) {} - string const getName() const override { + virtual const string getName() const override { return name; } diff --git a/src/Scalar.cpp b/src/Scalar.cpp index c16d534..6d9f341 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -17,8 +17,10 @@ Scalar::Scalar(const char* ident, Node *e): Variable(ident), expr(e) { Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(allocblock); - Node *symbol = ident.getSymbol(getScope()); + Node *isymbol = ident.getSymbol(getScope()); + Variable *symbol = dynamic_cast(isymbol); if (!symbol) return NULL; @@ -43,32 +45,20 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc //Load loadstem(ident.getStem()); //loadstem.setParent(this->parent); //stem = loadstem.generate(func, block, allocblock); - } else { - alloc = symbol->getLLVMValue(func); } // tell the allocated left value to an eventual // constructor initializing a user type field - if (getGEPIndex() != -1) - expr->setLeftValue(alloc, name); + expr->setLeftValue(symbol); Value *exprv = expr->generate(func, block, allocblock); if (!exprv) return NULL; DataType exprv_dt = expr->getDataType(); - // is the result of a constructor()? - Value *allocall = dyn_cast(exprv); - if (!allocall) - allocall = dyn_cast(exprv); - - if (allocall) { - setDataType(exprv_dt); - alloc = allocall; - if (debug_info) - RobDbgInfo.declareVar(this, alloc, allocblock); - } - + if (!alloc) + alloc = symbol->getLLVMValue(func); + // variable not allocated if (alloc == NULL) { Value *ret = NULL; @@ -116,54 +106,67 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc yyerrorcpp("Constant '" + symbol->getName() + "' can not be changed.", this); return NULL; } + + DataType currdt = symbol->getDataType(); + enum PointerMode pm = symbol->getPointerMode(); + + if (buildTypes->isComplex(currdt)) { + if (pm == pm_unknown) { + symbol->setPointer(pm_pointer); + pm = pm_pointer; + + } else if (pm == pm_nopointer && !func->isConstructor() && + exprv->getType()->isPointerTy()) { + // as any complex type is passed by ref, one must deref it before assigning + // to leftv, using the copy operator. + yyerrorcpp("Use the copy operator to dereference the rvalue.", this); + return NULL; + } + } + + Type *currty = buildTypes->llvmType(currdt); + if (pm == pm_pointer) + currty = currty->getPointerTo(); - Type *currty = buildTypes->llvmType(symbol->getDataType()); Builder->SetInsertPoint(block); + Value *nvalue = NULL; + + // Pointers need a custom procedure: load the stem, set the + // requested bit value through bit shifting, and store the new value + if (reg && buildTypes->isComplex(reg->getDataType())) { + /* this code does: + * symbol->value &= ~(0x11... << fieldStartBit) + * symbol->value |= (exprv << fieldStartBit) + */ + Type *req_eq_ty = Type::getIntNTy(global_context, buildTypes->bitWidth(reg->getDataType())); + Value *v = Builder->CreateLoad(req_eq_ty, alloc, reg->hasQualifier(qvolatile), "ptrvalue"); + + // Prepare the mask + unsigned bitWidth = buildTypes->bitWidth(symbol->getDataType()); + Constant *allone = Constant::getAllOnesValue(Type::getIntNTy(global_context, bitWidth)); + Constant *ones = ConstantExpr::getZExt(allone, req_eq_ty); + + // Coerce the rvalue to the req size + exprv = Coercion::Convert(exprv, req_eq_ty, block, expr); + exprv = Builder->CreateAnd(exprv, ones, "truncrval"); + + unsigned fieldStartBit = reg->getFieldStartBit(symbol); + if (fieldStartBit > 0) { + Constant *shiftl = ConstantInt::get(req_eq_ty, fieldStartBit); + ones = ConstantExpr::getShl(ones, shiftl); + exprv = Builder->CreateShl(exprv, shiftl, "shift"); + } + Constant *mask = ConstantExpr::getNot(ones); - if (allocall) { - // constructor result - return allocall; + // Apply mask, than or + Value *vaftermask = Builder->CreateAnd(v, mask, "mask"); + nvalue = Builder->CreateOr(vaftermask, exprv, "setbits"); } else { - Value *nvalue = NULL; - - // Pointers need a custom procedure: load the stem, set the - // requested bit value through bit shifting, and store the new value - if (reg && buildTypes->isComplex(reg->getDataType())) { - /* this code does: - * symbol->value &= ~(0x11... << fieldStartBit) - * symbol->value |= (exprv << fieldStartBit) - */ - Type *req_eq_ty = Type::getIntNTy(global_context, buildTypes->bitWidth(reg->getDataType())); - Value *v = Builder->CreateLoad(req_eq_ty, alloc, reg->hasQualifier(qvolatile), "ptrvalue"); - - // Prepare the mask - unsigned bitWidth = buildTypes->bitWidth(symbol->getDataType()); - Constant *allone = Constant::getAllOnesValue(Type::getIntNTy(global_context, bitWidth)); - Constant *ones = ConstantExpr::getZExt(allone, req_eq_ty); - - // Coerce the rvalue to the req size - exprv = Coercion::Convert(exprv, req_eq_ty, block, expr); - exprv = Builder->CreateAnd(exprv, ones, "truncrval"); - - unsigned fieldStartBit = reg->getFieldStartBit(symbol); - if (fieldStartBit > 0) { - Constant *shiftl = ConstantInt::get(req_eq_ty, fieldStartBit); - ones = ConstantExpr::getShl(ones, shiftl); - exprv = Builder->CreateShl(exprv, shiftl, "shift"); - } - Constant *mask = ConstantExpr::getNot(ones); - - // Apply mask, than or - Value *vaftermask = Builder->CreateAnd(v, mask, "mask"); - nvalue = Builder->CreateOr(vaftermask, exprv, "setbits"); - - } else { - nvalue = Coercion::Convert(exprv, currty, block, expr); - } - - return Builder->CreateStore(nvalue, alloc, symbol->hasQualifier(qvolatile)); + nvalue = Coercion::Convert(exprv, currty, block, symbol); } + + return Builder->CreateStore(nvalue, alloc, symbol->hasQualifier(qvolatile)); } } diff --git a/src/Scalar.h b/src/Scalar.h index 10a3fe6..8b20e88 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -4,7 +4,7 @@ #include "Variable.h" class Scalar: public Variable { -private: +protected: Node *expr; public: diff --git a/src/Scanner.cpp b/src/Scanner.cpp index fdb90d5..afe2c80 100644 --- a/src/Scanner.cpp +++ b/src/Scanner.cpp @@ -13,7 +13,7 @@ char *build_outputfilename; vector includeDirs; vector buildStack; vector buildStackScanner; -int buildStackTop; +int buildStackCurrent; int USElex(YYSTYPE *yylval_param, location_t *yylloc_param, yyscan_t yyscanner) { return MAINlex(yylval_param, yylloc_param, yyscanner); @@ -25,8 +25,8 @@ int MAINlex_destroy(yyscan_t yyscanner); int USEparse(yyscan_t scanner); void yyerror(location_t *loc, yyscan_t scanner, const char *s) { - fprintf(stderr, "%s:%d:%d: %s\n", - build_file()->string().c_str(), loc->first_line, loc->first_column, s); + fprintf(stderr, ":%d:%d: %s\n", + loc->first_line, loc->first_column, s); errorsfound++; } @@ -55,7 +55,7 @@ bool parseFile(const string& source) { filesystem::path file_path(source); buildStack.push_back(file_path); - buildStackTop = 0; + buildStackCurrent = 0; // search for use files in the path of build_filename; // next in the working dir; next in the -I dirs (right from left) @@ -113,6 +113,8 @@ bool parseUseFile(const string& use, location_t loc) { auto it = find(buildStack.begin(), buildStack.end(), file_path); if (it != buildStack.end()) { // circular dependency + //#define PRINT_DEPENDENCY_LOOP + #ifdef PRINT_DEPENDENCY_LOOP SourceLocation sl(loc); yywarncpp(string_format("circular dependency for %s", file_path.c_str()), &sl); while (it != buildStack.end()) { @@ -120,12 +122,14 @@ bool parseUseFile(const string& use, location_t loc) { it++; } fprintf(stderr, "\t%s\n", file_path.c_str()); + #endif fclose(f); return true; } + static int buildStackBackup = buildStackCurrent; buildStack.push_back(file_path); - buildStackTop++; + buildStackCurrent = buildStack.size()-1; yyscan_t scanner; MAINlex_init(&scanner); @@ -138,9 +142,9 @@ bool parseUseFile(const string& use, location_t loc) { MAINlex_destroy(scanner); fclose(f); - buildStackTop--; + buildStackCurrent = buildStackBackup; buildStackScanner.pop_back(); - buildStack.pop_back(); + //buildStack.pop_back(); return true; } @@ -149,13 +153,13 @@ int MAINget_lineno(yyscan_t yyscanner); int MAINget_column(yyscan_t yyscanner); int build_filelineno() { - return MAINget_lineno(buildStackScanner[buildStackTop]); + return MAINget_lineno(buildStackScanner[buildStackScanner.size()-1]); } int build_filecolno() { - return MAINget_column(buildStackScanner[buildStackTop]); + return MAINget_column(buildStackScanner[buildStackScanner.size()-1]); } const filesystem::path* build_file() { - return &buildStack[buildStackTop]; + return &buildStack[buildStackCurrent]; } diff --git a/src/Scanner.h b/src/Scanner.h index 96e6847..c7ab40d 100644 --- a/src/Scanner.h +++ b/src/Scanner.h @@ -14,9 +14,6 @@ static const char *file_not_found = "No such file or directory '%s'."; typedef void* yyscan_t; extern int errorsfound; extern vector includeDirs; -extern vector buildStack; -extern int buildStackTop; -extern vector buildStackScanner; void yyerror(location_t *loc, yyscan_t scanner, const char *s); void USEerror(location_t *loc, yyscan_t scanner, const char *s); diff --git a/src/UserType.cpp b/src/UserType.cpp index 97ad398..09fe684 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -3,44 +3,116 @@ #include "Interface.h" #include "FunctionImpl.h" #include "FunctionParams.h" +#include "FunctionCall.h" +#include "ParamsCall.h" #include "Program.h" #include "Visitor.h" +#include "Enum.h" +#include "Load.h" +#include "BackLLVM.h" + +class ParentScalar: public Scalar { +public: + ParentScalar(DataType parentDt) : Scalar("parent", new Load("#parent")) { + expr->setScope(this); + dt = parentDt; + pointer = pm_pointer; + } + virtual DataType getDataType() override { + return dt; + } + virtual Type* getLLVMType() override { + return PointerType::get(global_context, dataAddrSpace); + } +}; + +bool UserType::createDataType() { + + if (dt != BuildTypes::undefinedType) + return true; + else { + // create an undefined type to use in recursive subtypes + dt = buildTypes->getType(getName(), true); + } -void UserType::createDataType() { std::vector elements; int idx = 0; unsigned startBit = 0; + vector addedVars; for(auto child : this->children()) { - Variable *s = dynamic_cast(child); - if (s) { - elements.push_back(s->getLLVMType()); - s->setGEPIndex(idx++); + Variable *v = NULL; + + if (UserType *ut = dynamic_cast(child)) { + // internal user type: + // add a var in the internal type to store a reference to his parent + ParentScalar *s = new ParentScalar(dt); + s->setScope(ut); + ut->addChild(s); + ut->addSymbol(s); + + string varname = ut->getName(); + ut->setParent(this); // name changes after setting parent + ut->createDataType(); + + // create a new var in the parent to store the intf implementation + FunctionCall *fc = new FunctionCall(ut->getName(), new ParamsCall()); + v = new Scalar(varname, fc); + fc->setScope(v); + v->setScope(this); + addedVars.push_back(v); + + // fix the symbol table due to the renaming + getScope()->addSymbol(ut); + symbols[ut->getName()] = ut; + symbols[v->getName()] = v; + + } else { + v = dynamic_cast(child); + } + + if (v) { + if (v->getPointerMode() == pm_unknown) + v->setPointer(pm_nopointer); + + Type *llvmType = v->getLLVMType(); + assert(llvmType && "Can not construct a type without its LLVM type."); + if (!llvmType) + return false; + + elements.push_back(llvmType); + v->setGEPIndex(idx++); //FIXME: Fix for data alignment on non-packed structure/type - startBits[s->getName()] = startBit; - startBit += buildTypes->bitWidth(s->getDataType()); + startBits[v->getName()] = startBit; + startBit += buildTypes->bitWidth(v->getDataType()); } } - unsigned bitWidth = startBit; + bitWidth = startBit; - StructType *uttype = StructType::create(global_context, ArrayRef(elements), name, true); + for(auto a: addedVars) { + addChild(a); + addSymbol(a); + } + + StructType *uttype = StructType::create(global_context, ArrayRef(elements), getName()); dt = buildTypes->addDataType(this, uttype, bitWidth); + if (parent) + buildTypes->setInternal(dt, true); + if (dt == BuildTypes::undefinedType) { yyerrorcpp("Type " + name + " alread defined.", this); yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); - return; + return false; } - /*printf("Type %s defined with:\n", name.c_str()); - for(const auto n : symbols) { - printf("\t%s\n", n.first.c_str()); - }*/ + return true; } Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - createDataType(); + if (!createDataType()) + return NULL; // semantic analysis for(auto n : implements) { @@ -61,24 +133,46 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all fields.push_back(c); } } - + + // generate user types and enums + for(auto & [key, stmt] : getSymbols()) { + if (UserType *ut = dynamic_cast(stmt)) { + ut->setDeclaration(declaration); + ut->generate(func, block, allocblock); + } else if (Enum *en = dynamic_cast(stmt)) { + en->generate(func, block, allocblock); + } + } + // generate init function/constructor FunctionParams *fp = new FunctionParams(); FunctionImpl *finit = new FunctionImpl((DataType)tvoid, "init", fp, std::move(fields), *this->getLoct(), true); finit->addThisArgument(dt); - finit->setUserTypeName(name); + if (parent) + finit->addParentArgument(parent->getDataType()); + finit->setUserTypeName(getName()); finit->setExternal(declaration); finit->generate(func, block, allocblock); - - // generate functions + + /* set function parameters before generate + * A function can call others that are still not generated + * and request their type info. So, here we set all needed + * info to pre-generate their type. + */ for(auto & [key, stmt] : getSymbols()) { if (FunctionImpl *f = dynamic_cast(stmt)) { - f->setUserTypeName(name); + f->setUserTypeName(getName()); f->addThisArgument(dt); for(auto &field : fields) f->addSymbol(dynamic_cast(field)); f->setExternal(declaration); + } + } + + // generate functions + for(auto & [key, stmt] : getSymbols()) { + if (FunctionImpl *f = dynamic_cast(stmt)) { f->generate(func, block, allocblock); } } @@ -94,4 +188,16 @@ void UserType::accept(Visitor& v) { unsigned UserType::getFieldStartBit(Node *field) { return startBits[field->getName()]; -} \ No newline at end of file +} + +const string UserType::getName() const { + if (parent) + return parent->getName() + "#" + NamedNode::getName(); + else + return NamedNode::getName(); +} + +void UserType::addSymbol(NamedNode *nm) { + // overrided here as UserType has its own scope + symbols[nm->getName()] = nm; +} diff --git a/src/UserType.h b/src/UserType.h index 4312337..88fd18e 100644 --- a/src/UserType.h +++ b/src/UserType.h @@ -12,8 +12,10 @@ class UserType: public NamedNode { vector implements; map startBits; bool declaration = false; + UserType *parent = NULL; + unsigned bitWidth = 0; - void createDataType(); + bool createDataType(); public: @@ -31,4 +33,21 @@ class UserType: public NamedNode { void setDeclaration(bool d) { declaration = d; } + + UserType* getParent() { + return parent; + } + + void setParent(UserType *ut) { + parent = ut; + } + + virtual const string getName() const override; + + virtual void addSymbol(NamedNode *nm) override; + + unsigned getBitWidth() { + return bitWidth; + } + }; diff --git a/src/Variable.cpp b/src/Variable.cpp index bef398d..12ed0c5 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -11,7 +11,7 @@ Value *Variable::getLLVMValue(Node *stem) { FunctionImpl *func = dynamic_cast(stem); if (func && func->getThisArg()) { - // generating a function of a type: get the gep on the #this parameter + // generating a function of a type: get the gep on #this or #parent parameters Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); alloc = Builder->CreateStructGEP(thisTy, func->getThisArg(), gepidx, "gepthis"); } else { diff --git a/src/Variable.h b/src/Variable.h index 38f54cc..bad7d5f 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -4,11 +4,14 @@ #include "Node.h" #include "Identifier.h" +enum PointerMode {pm_unknown, pm_pointer, pm_nopointer}; + class Variable: public NamedNode { protected: Value *alloc = NULL; Identifier ident; int gepIndex = -1; + enum PointerMode pointer = pm_unknown; public: Variable(const string &name): NamedNode(name), ident(name) {} @@ -22,4 +25,17 @@ class Variable: public NamedNode { int getGEPIndex() const { return gepIndex; } + + void setPointer(enum PointerMode v) { + pointer = v; + } + + enum PointerMode getPointerMode() { + return pointer; + } + + void setAlloca(Value *alloc) { + this->alloc = alloc; + } + }; diff --git a/testnew/general/byref.rob b/testnew/general/byref.rob new file mode 100644 index 0000000..0c9a722 --- /dev/null +++ b/testnew/general/byref.rob @@ -0,0 +1,38 @@ + +interface intf { + void print(int8 v); +} + +type sub_t { + y = 18; +} + +type main_t { + a = 0; + ss = sub_t(); + + void setSubt(sub_t v) { + ss = copy(v); + } + + ii = intf { + void print(int8 v) { + return; + } + } +} + +int16 main() { + a = main_t(); + ss = a.ss; + + x = sub_t(); + x.y = 17; + a.setSubt(x); + + if (ss.y == 18) { + return 0; + } + return 1; +} + diff --git a/testnew/general/intfinternal.rob b/testnew/general/intfinternal.rob new file mode 100644 index 0000000..595e29e --- /dev/null +++ b/testnew/general/intfinternal.rob @@ -0,0 +1,40 @@ + +interface bus { + void setup(int32 speed); + void write(int8 b); +} + +type mcu { + + spi = bus { + speed = int32(0); + lastb = 0; + + void setup(int32 s) { + speed = s; + } + + void write(int8 b) { + lastb = b; + } + } +} + +int16 main() { + m = mcu(); + spi = m.spi; + + if spi.speed != 0 or spi.lastb != 0 { + return 1; + } + + spi.setup(1000); + spi.write(8); + + if spi.speed != 1000 or spi.lastb != 8 { + return 1; + } + + return 0; +} + diff --git a/testnew/general/intfscope.rob b/testnew/general/intfscope.rob new file mode 100644 index 0000000..62c1ee4 --- /dev/null +++ b/testnew/general/intfscope.rob @@ -0,0 +1,46 @@ + +interface intf { + int16 get(); + void set(int16 s); +} + +type somevar { + a = int16(0); + + pa = intf { + a = int8(0); + int16 get() { return a; } + void set(int16 s) { a = s; } + } + + int16 internaltest() { + pa.set(22); + return pa.get(); + } + + void set(int16 v) { + a = v; + } + + int16 get() { + return a; + } +} + +int16 main() { + sv = somevar(); + + in = sv.internaltest(); + + sv.set(18); + sva = sv.get(); + + ex = 33; + + if (in == 22 and ex == 33 and sva == 18) { + return 0; + } else { + return 1; + } +} + diff --git a/testnew/general/replace_buildfail.rob b/testnew/general/replace_buildfail.rob new file mode 100644 index 0000000..d5af85f --- /dev/null +++ b/testnew/general/replace_buildfail.rob @@ -0,0 +1,23 @@ + +type stt { + a = false; +} + +type tt { + b = 15; + s = stt(); + + void reinit() { + s = stt(); + } +} + +int16 main() { + a = tt(); + a = tt(); + if a.b == 15 { + return 0; + } + return 1; +} + diff --git a/testnew/general/simpleptr.rob b/testnew/general/simpleptr.rob new file mode 100644 index 0000000..15c3cd9 --- /dev/null +++ b/testnew/general/simpleptr.rob @@ -0,0 +1,19 @@ + +type tt { + a = int16(0); +} + +void set_a(tt value) { + value.a = 10; +} + +int32 main() { + t = tt(); + set_a(t); + if t.a == 10 { + return 0; + } else { + return 1; + } +} + diff --git a/testnew/general/simplesubtype.rob b/testnew/general/simplesubtype.rob new file mode 100644 index 0000000..ab547de --- /dev/null +++ b/testnew/general/simplesubtype.rob @@ -0,0 +1,18 @@ + +interface a { + void print(); +} + +type b { + x = a { + void print() { + return; + } + } +} + +int16 main() { + y = b(); + return 0; +} + From 02734dc3afae769987b69d2a9d2d2a6811ff24fc Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Fri, 18 Aug 2023 13:33:37 -0300 Subject: [PATCH 032/117] 0.2 release. --- .../avr328p-blink/.gitignore | 0 .../avr328p-blink/platformio.ini | 0 .../examples/avr328p-blink/src/main.rob | 46 +++++++ .../avr328p-blink/src/wait.rob} | 0 .../avr328p-ssd1306}/.gitignore | 0 .../examples/avr328p-ssd1306/platformio.ini | 12 ++ .../examples/avr328p-ssd1306/src/avr5mcu.rob | 97 +++++++++++++ .../examples/avr328p-ssd1306/src/avr5regs.rob | 45 +++++++ .../examples/avr328p-ssd1306/src/databus.rob | 9 ++ .../examples/avr328p-ssd1306/src/main.rob | 32 +++++ .../examples/avr328p-ssd1306/src/mcu.rob | 6 + .../examples/avr328p-ssd1306/src/ports.rob | 14 ++ .../examples/avr328p-ssd1306/src/ssd1306.rob | 127 ++++++++++++++++++ platformio/examples/stm32f1-blink/.gitignore | 5 + .../stm32f1-blink/platformio.ini | 0 .../stm32f1-blink/src/main.rob | 0 .../examples/stm32f1-blink/src/newmain.rob | 106 +++++++++++++++ .../stm32f1-blink/src/two.rob | 0 platformio/install | 6 +- platformio/pkg | 2 +- platformio/platform/builder/main.py | 12 +- platformio/platform/platform.py | 15 ++- platformio/samples/avr328p-blink/src/main.rob | 63 --------- platformio/toolchain-robcmp/Makefile | 20 ++- platformio/toolchain-robcmp/libllvmpathosx.sh | 5 + platformio/toolchain-robcmp/version | 2 +- platformio/vscode-syntax/Makefile | 2 + .../vscode-syntax/robcmpsyntax-0.0.1.vsix | Bin 0 -> 3281 bytes .../vscode-syntax/robcmpsyntax-0.1.0.vsix | Bin 3020 -> 0 bytes 29 files changed, 547 insertions(+), 79 deletions(-) rename platformio/{samples => examples}/avr328p-blink/.gitignore (100%) rename platformio/{samples => examples}/avr328p-blink/platformio.ini (100%) create mode 100644 platformio/examples/avr328p-blink/src/main.rob rename platformio/{samples/avr328p-blink/src/two.rob => examples/avr328p-blink/src/wait.rob} (100%) rename platformio/{samples/stm32f1-blink => examples/avr328p-ssd1306}/.gitignore (100%) create mode 100644 platformio/examples/avr328p-ssd1306/platformio.ini create mode 100644 platformio/examples/avr328p-ssd1306/src/avr5mcu.rob create mode 100644 platformio/examples/avr328p-ssd1306/src/avr5regs.rob create mode 100644 platformio/examples/avr328p-ssd1306/src/databus.rob create mode 100644 platformio/examples/avr328p-ssd1306/src/main.rob create mode 100644 platformio/examples/avr328p-ssd1306/src/mcu.rob create mode 100644 platformio/examples/avr328p-ssd1306/src/ports.rob create mode 100644 platformio/examples/avr328p-ssd1306/src/ssd1306.rob create mode 100644 platformio/examples/stm32f1-blink/.gitignore rename platformio/{samples => examples}/stm32f1-blink/platformio.ini (100%) rename platformio/{samples => examples}/stm32f1-blink/src/main.rob (100%) create mode 100644 platformio/examples/stm32f1-blink/src/newmain.rob rename platformio/{samples => examples}/stm32f1-blink/src/two.rob (100%) delete mode 100644 platformio/samples/avr328p-blink/src/main.rob create mode 100755 platformio/toolchain-robcmp/libllvmpathosx.sh create mode 100644 platformio/vscode-syntax/Makefile create mode 100644 platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix delete mode 100644 platformio/vscode-syntax/robcmpsyntax-0.1.0.vsix diff --git a/platformio/samples/avr328p-blink/.gitignore b/platformio/examples/avr328p-blink/.gitignore similarity index 100% rename from platformio/samples/avr328p-blink/.gitignore rename to platformio/examples/avr328p-blink/.gitignore diff --git a/platformio/samples/avr328p-blink/platformio.ini b/platformio/examples/avr328p-blink/platformio.ini similarity index 100% rename from platformio/samples/avr328p-blink/platformio.ini rename to platformio/examples/avr328p-blink/platformio.ini diff --git a/platformio/examples/avr328p-blink/src/main.rob b/platformio/examples/avr328p-blink/src/main.rob new file mode 100644 index 0000000..055fe7b --- /dev/null +++ b/platformio/examples/avr328p-blink/src/main.rob @@ -0,0 +1,46 @@ +/* + * Robcmp examples: Blink + * Blinks the led on PIN13 + */ + +use wait; + +type PORTB { + pin8 = false; + pin9 = false; + pin10 = false; + pin11 = false; + pin12 = false; + pin13 = false; +} + +register PORTB portb at 0x25; + +type DDRB { + pin8 = false; + pin9 = false; + pin10 = false; + pin11 = false; + pin12 = false; + pin13 = false; +} + +register PORTB ddrb at 0x24; + +int16 main() { + /* pin 13 is controlled by bit 5 of DDRB and PORTB registers + * - bit 5 of DDRB indicates if the pin is input (0) or output (1) + * - bit 5 of PORTB toggles pin HIGH or LOW + */ + + // set pin 13 as output + ddrb.pin13 = true; + + loop { + portb.pin13 = true; + wait(100000); + + portb.pin13 = false; + wait(100000); + } +} diff --git a/platformio/samples/avr328p-blink/src/two.rob b/platformio/examples/avr328p-blink/src/wait.rob similarity index 100% rename from platformio/samples/avr328p-blink/src/two.rob rename to platformio/examples/avr328p-blink/src/wait.rob diff --git a/platformio/samples/stm32f1-blink/.gitignore b/platformio/examples/avr328p-ssd1306/.gitignore similarity index 100% rename from platformio/samples/stm32f1-blink/.gitignore rename to platformio/examples/avr328p-ssd1306/.gitignore diff --git a/platformio/examples/avr328p-ssd1306/platformio.ini b/platformio/examples/avr328p-ssd1306/platformio.ini new file mode 100644 index 0000000..b75fd8c --- /dev/null +++ b/platformio/examples/avr328p-ssd1306/platformio.ini @@ -0,0 +1,12 @@ + +[env] +platform = robcmp +board = avr328p +upload_protocol = serial + +[env:release] +build_type = release + +[env:debug] +build_type = debug +debug_tool = robcmp diff --git a/platformio/examples/avr328p-ssd1306/src/avr5mcu.rob b/platformio/examples/avr328p-ssd1306/src/avr5mcu.rob new file mode 100644 index 0000000..e1d88bd --- /dev/null +++ b/platformio/examples/avr328p-ssd1306/src/avr5mcu.rob @@ -0,0 +1,97 @@ + +use mcu; +use ports; +use databus; + +use avr5regs; + +type avr5mcu implements mcu { + + /* implement this idea later! + template digport { + void mode(m port_mode) { port_config = mode; } + void set(bool v) { port = v; } + bool get() { return port; } + } + b0 = digport + */ + + b0 = digitalport { + void mode(port_mode m) { ddrb.b0 = m; } + void set(bool v) { portb.b0 = v; } + bool get() { return portb.b0; } + } + + b1 = digitalport { + void mode(port_mode m) { ddrb.b1 = m; } + void set(bool v) { portb.b1 = v; } + bool get() { return portb.b1; } + } + + b2 = digitalport { + void mode(port_mode m) { ddrb.b2 = m; } + void set(bool v) { portb.b2 = v; } + bool get() { return portb.b2; } + } + + b3 = digitalport { + void mode(port_mode m) { ddrb.b3 = m; } + void set(bool v) { portb.b3 = v; } + bool get() { return portb.b3; } + } + + b4 = digitalport { + void mode(port_mode m) { ddrb.b4 = m; } + void set(bool v) { portb.b4 = v; } + bool get() { return portb.b4; } + } + + b5 = digitalport { + void mode(port_mode m) { ddrb.b5 = m; } + void set(bool v) { portb.b5 = v; } + bool get() { return portb.b5; } + } + + void enable_led() { + b5.mode(port_mode.output); + } + + void set_led(bool s) { + b5.set(s); + } + + void wait(int32 q) { + volatile i = q; + while i > 0 { + i--; + } + } + + spi = databus { + void setup(int32 speed) { + b3.mode(port_mode.output); + b4.mode(port_mode.output); + b5.mode(port_mode.output); + spcr.MSTR = true; // master? + } + void enable() { + spcr.SPE = true; + } + void disable() { + spcr.SPE = false; + } + void write(int8 b) { + sprd = b; + while spsr.SPIF == false; + } + int8 read() { + //FIXME + while spsr.SPIF == false; + return spdr; + } + bool has_data() { + //FIXME + return spsr.SPIF; + } + } +} diff --git a/platformio/examples/avr328p-ssd1306/src/avr5regs.rob b/platformio/examples/avr328p-ssd1306/src/avr5regs.rob new file mode 100644 index 0000000..77a405a --- /dev/null +++ b/platformio/examples/avr328p-ssd1306/src/avr5regs.rob @@ -0,0 +1,45 @@ + +type portb_t { + b0 = false; + b1 = false; + b2 = false; + b3 = false; + b4 = false; + b5 = false; + ignore = int2(); +} + +register portb_t portb at 0x25; +register portb_t ddrb at 0x24; + +/* + * SPI stuff + */ + +type spcr_t { + SPR0 = false; + SPR1 = false; + CPHA = false; + CPOL = false; + MSTR = false; + DORD = false; + SPE = false; + SPIE = false; +} + +// SPI Control Register +register spcr_t spcr at 0x4c; + +type spsr_t { + SPI2x = false; + _reserved = int5(0); + WCOL = false; + SPIF = false; +} + +// SPI Status Register +register spsr_t spsr at 0x4d; + +// SPI Data Register +register int8 spdr at 0x4e; + diff --git a/platformio/examples/avr328p-ssd1306/src/databus.rob b/platformio/examples/avr328p-ssd1306/src/databus.rob new file mode 100644 index 0000000..b3f6af1 --- /dev/null +++ b/platformio/examples/avr328p-ssd1306/src/databus.rob @@ -0,0 +1,9 @@ + +interface databus { + void setup(int32 speed); + void enable(); + void disable(); + void write(int8 b); + int8 read(); + bool has_data(); +} diff --git a/platformio/examples/avr328p-ssd1306/src/main.rob b/platformio/examples/avr328p-ssd1306/src/main.rob new file mode 100644 index 0000000..c47dd94 --- /dev/null +++ b/platformio/examples/avr328p-ssd1306/src/main.rob @@ -0,0 +1,32 @@ +/* + * Robcmp examples: SSD1306 SPI + */ + +use avr5mcu; +use ssd1306; + +//bind avr5mcu to mmcu; +//bind avr5mcu.b0 to ssd1306.reset +//bind avr5mcu.spi1 to ssd1306.spi +//alias avr5mcu.b5 to ; +//led[digital,pwm,asdfs] +// + +int16 main() { + + mmcu = avr5mcu(); + spi = mmcu.spi; + spi.init(); + + display = ssd1306(); + display.init(); + + loop { + led = true; + //mcu.set_led(true); + mcu.wait(100000); + + //mcu.set_led(false); + mcu.wait(100000); + } +} diff --git a/platformio/examples/avr328p-ssd1306/src/mcu.rob b/platformio/examples/avr328p-ssd1306/src/mcu.rob new file mode 100644 index 0000000..15d7d5a --- /dev/null +++ b/platformio/examples/avr328p-ssd1306/src/mcu.rob @@ -0,0 +1,6 @@ + +interface mcu { + void wait(int32 us); + void enable_led(); + void set_led(bool s); +} diff --git a/platformio/examples/avr328p-ssd1306/src/ports.rob b/platformio/examples/avr328p-ssd1306/src/ports.rob new file mode 100644 index 0000000..f91d241 --- /dev/null +++ b/platformio/examples/avr328p-ssd1306/src/ports.rob @@ -0,0 +1,14 @@ + +enum port_mode { input, output } + +interface digitalport { + void mode(port_mode m); + void set(bool v); + bool get(); +} + +interface analogport { + void mode(port_mode m); + void set(int16 v); + int16 get(); +} diff --git a/platformio/examples/avr328p-ssd1306/src/ssd1306.rob b/platformio/examples/avr328p-ssd1306/src/ssd1306.rob new file mode 100644 index 0000000..3ed23a8 --- /dev/null +++ b/platformio/examples/avr328p-ssd1306/src/ssd1306.rob @@ -0,0 +1,127 @@ + +use mcu; +use ports; +use databus; + +type ssd1306 { + mmcu = mcu(); + datacmd = digitalport(); + reset = digitalport(); + select = digitalport(); + spi = databus(); + + enum powerstate { + SLEEP = 0xAE, + ON = 0xAF + } + + enum commands { + SET_DISP_START_LINE = 0x40, + SET_SEG_REMAP_0 = 0xA0, + SET_SEG_REMAP_127 = 0xA1, + SET_MULTIPLEX_RATIO = 0xA8, + SET_COM_SCAN_NORMAL = 0xC0, + SET_COM_SCAN_INVERTED = 0xC8, + SET_VERTICAL_OFFSET = 0xD3, + SET_WIRING_SCHEME = 0xDA, + SET_DISP_CLOCK = 0xD5, + SET_PRECHARGE_PERIOD = 0xD9, + SET_VCOM_DESELECT_LEVEL = 0xDB, + SET_CONTRAST = 0x81, + RESUME_TO_RAM_CONTENT = 0xA4, + DISPLAY_MODE_NORMAL = 0xA6, + DISPLAY_MODE_INVERTED = 0xA7, + MEM_ADDRESSING = 0x20, + CHARGE_PUMP_REGULATOR = 0x8D, + CHARGE_PUMP_ON = 0x14, + NOP = 0xE3 + } + + enum displayorientation {NORMAL, NORMAL_MIRRORED, UPSIDE_DOWN, UPSIDE_DOWN_MIRRORED} + + void init_display() { + datacmd.mode(port_mode.output); + reset.mode(port_mode.output); + select.mode(port_mode.output); + + reset_display(); + write_command(powerstate.SLEEP); + + write_command(commands.SET_MULTIPLEX_RATIO); + write_command(0x3F); + + write_command(commands.SET_VERTICAL_OFFSET); + write_command(0x00); + + write_command(commands.SET_DISP_START_LINE); + + set_display_orientation(displayorientation.NORMAL); + + write_command(commands.SET_WIRING_SCHEME); + write_command(0x12); + + set_contrast(0x7F); + + write_command(commands.RESUME_TO_RAM_CONTENT); + + write_command(commands.DISPLAY_MODE_NORMAL); + + // Horizontal memory addressing mode + write_command(commands.MEM_ADDRESSING); + write_command(0x00); + + write_command(commands.SET_DISP_CLOCK); + + //FIXME on RobCmp: The warning here is due to write_command + // receiving a signed parameter. We need to implement/fix unsignedness + write_command(0x80); + + write_command(commands.CHARGE_PUMP_REGULATOR); + write_command(commands.CHARGE_PUMP_ON); + + write_command(powerstate.ON); + } + + void set_display_orientation(displayorientation o) { + if (o == displayorientation.NORMAL or + o == displayorientation.NORMAL_MIRRORED) { + write_command(commands.SET_SEG_REMAP_0); + } else { + write_command(commands.SET_SEG_REMAP_127); + } + + if (o == displayorientation.NORMAL_MIRRORED or + o == displayorientation.UPSIDE_DOWN) { + write_command(commands.SET_COM_SCAN_INVERTED); + } else { + write_command(commands.SET_COM_SCAN_NORMAL); + } + } + + void set_contrast(int8 c) { + write_command(commands.SET_CONTRAST); + write_command(c); + } + + void reset_display() { + reset.set(true); + mcu.wait(3); + reset.set(false); + mcu.wait(3); + reset.set(true); + } + + void write_command(int8 c) { + datacmd.set(false); + select.set(false); + spi.write(c); + select.set(true); + } + + void write_data(int8 d) { + datacmd.set(true); + select.set(false); + spi.write(d); + select.set(true); + } +} diff --git a/platformio/examples/stm32f1-blink/.gitignore b/platformio/examples/stm32f1-blink/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/platformio/examples/stm32f1-blink/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/platformio/samples/stm32f1-blink/platformio.ini b/platformio/examples/stm32f1-blink/platformio.ini similarity index 100% rename from platformio/samples/stm32f1-blink/platformio.ini rename to platformio/examples/stm32f1-blink/platformio.ini diff --git a/platformio/samples/stm32f1-blink/src/main.rob b/platformio/examples/stm32f1-blink/src/main.rob similarity index 100% rename from platformio/samples/stm32f1-blink/src/main.rob rename to platformio/examples/stm32f1-blink/src/main.rob diff --git a/platformio/examples/stm32f1-blink/src/newmain.rob b/platformio/examples/stm32f1-blink/src/newmain.rob new file mode 100644 index 0000000..2fa5a8d --- /dev/null +++ b/platformio/examples/stm32f1-blink/src/newmain.rob @@ -0,0 +1,106 @@ + +/* + * Sample Blink Led on port 13 for STM32F1 + */ + +// CLOCK GATES FOR IO +const RCC_BASE = 0x40021000; +register int32 APB2EN at (RCC_BASE + 0x18) { + bool afio; + bool _res1; + bool iopa; + bool iopb; + bool iopc; + bool iopd; + bool iope; + bool iopf; + bool iopg; + bool adc1; + bool adc2; + bool tim1; + bool spi1; + bool tim8; + bool usart1; + bool adc3; + int8 _res2: 3; + bool tim9; + bool tim10; + bool tim11; +} + +// GPIO PORTC base address +const GPIO_PORTC_BASE = 0x40011000; + +// PORTC registers +register int32 GPIOC_CRH at (GPIO_PORTC_BASE + 0x4) { + int8 mode8: 2; + int8 cnf8: 2; + int8 mode9: 2; + int8 cnf9: 2; + int8 mode10: 2; + int8 cnf10: 2; + int8 mode11: 2; + int8 cnf11: 2; + int8 mode12: 2; + int8 cnf12: 2; + int8 mode13: 2; + int8 cnf13: 2; + int8 mode14: 2; + int8 cnf14: 2; + int8 mode15: 2; + int8 cnf15: 2; +} + +register int32 GPIOC_ODR at (GPIO_PORTC_BASE + 0xC) { + bool odr0; + bool odr1; + bool odr2; + bool odr3; + bool odr4; + bool odr5; + bool odr6; + bool odr7; + bool odr8; + bool odr9; + bool odr10; + bool odr11; + bool odr12; + bool odr13; + bool odr14; + bool odr15; +} + +const PIN_MODE_INPUT = 0x0; +const PIN_MODE_OUTPUT10MHz = 0x1; +const PIN_MODE_OUTPUT2MHz = 0x2; +const PIN_MODE_OUTPUT50MHz = 0x3; + +const INPUT_MODE_ANALOG = 0x0; +const INPUT_MODE_FLOATING = 0x1; +const INPUT_MODE_PULLUPDOWN = 0x2; + +const OUTPUT_MODE_PUSHPULL = 0x0; +const OUTPUT_MODE_OPENDRAIN = 0x1; +const OUTPUT_MODE_APUSH_PULL = 0x2; +const OUTPUT_MODE_AOPENDRAIN = 0x3; + +void wait(); + +void main() { + + // Enable port C clock gate. + APB2EN.iopc = true; + + // PORT C, PIN 13 as OUTPUT 50MHz + GPIOC_CRH.mode13 = PIN_MODE_OUTPUT50MHz; + + // PORT C, PIN13 as PUSHPULL + GPIOC_CRH.cnf13 = OUTPUT_MODE_PUSHPULL; + + loop { + GPIOC_ODR.odr13 = false; + wait(); + GPIOC_ODR.odr13 = true; + wait(); + } +} diff --git a/platformio/samples/stm32f1-blink/src/two.rob b/platformio/examples/stm32f1-blink/src/two.rob similarity index 100% rename from platformio/samples/stm32f1-blink/src/two.rob rename to platformio/examples/stm32f1-blink/src/two.rob diff --git a/platformio/install b/platformio/install index fa6c492..b260b97 100755 --- a/platformio/install +++ b/platformio/install @@ -6,6 +6,6 @@ mkdir -p ~/.platformio/packages ln -sf `realpath platform` ~/.platformio/platforms/robcmp ln -sf `realpath toolchain-robcmp` ~/.platformio/packages/toolchain-robcmp code --install-extension vscode-syntax/robcmpsyntax-0.0.1.vsix -echo "Open the samples folder and try to build and upload!" -echo " code samples/avr328p" -echo " code samples/stm32f1" +echo "Open the examples folder and try to build and upload!" +echo " code examples/avr328p-blink" +echo " code examples/stm32f1" diff --git a/platformio/pkg b/platformio/pkg index 6a4b8c2..a59ed82 100755 --- a/platformio/pkg +++ b/platformio/pkg @@ -1,4 +1,4 @@ PATH=~/.platformio/packages/toolchain-atmelavr/bin/:$PATH cd toolchain-robcmp && make clean && make cd .. -tar cfz robcmp-`uname -s`-`uname -m`-`cat toolchain-robcmp/version`.tar.gz platform samples vscode-syntax/robcmpsyntax-0.0.1.vsix toolchain*.tar.gz install +tar cfz robcmp-`uname -s`-`uname -m`-`cat toolchain-robcmp/version`.tar.gz platform examples vscode-syntax/robcmpsyntax-0.0.1.vsix toolchain*`cat toolchain-robcmp/version`.tar.gz install diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 06668ee..deb89f6 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -27,7 +27,6 @@ ldflags.append("-Tstm32f1.ld") elif mcu == "atmega328p": ldflags.append("-Tavr328p.ld") - ldflags.append("-Tdata=0x800100") ldflags.append(join(ldscripts_folder, "avr5.o")) sources += Glob(join(ldscripts_folder, "avr328p.rob")) else: @@ -44,6 +43,13 @@ ldflags.append("--gc-sections") robcmp_args.append("$SOURCE") +if board.startswith("avr"): + print("Will use avr-gdb from robcmp") + avr_gdb = join(platform.get_package_dir("toolchain-robcmp"), "bin", "avr-gdb") + env.Replace( + GDB=avr_gdb + ) + env.Append( BUILDERS=dict( ElfToBin=Builder( @@ -96,7 +102,7 @@ UPLOADERFLAGS=["-C", avrdude_cfg, "-v", "-V", "-c", "arduino", "-p", "m328p", "-U"], UPLOADCMD='$UPLOADER $UPLOADERFLAGS flash:w:${SOURCE}:i -P $UPLOAD_PORT' ) - + else: sys.stderr.write("Upload protocol %s doesn't support mcu %s\n" % (upload_protocol, mcu)) env.Exit(1) @@ -111,7 +117,7 @@ "-c", "program $SOURCE reset 0x08000000 exit"], UPLOADCMD="$UPLOADER $UPLOADERFLAGS" ) - + else: sys.stderr.write("Upload protocol %s doesn't support mcu %s\n" % (upload_protocol, mcu)) env.Exit(1) diff --git a/platformio/platform/platform.py b/platformio/platform/platform.py index f414781..d36aef1 100644 --- a/platformio/platform/platform.py +++ b/platformio/platform/platform.py @@ -1,6 +1,6 @@ # # Robcmp compiler platform for platformio -# Require packages according to upload_protocol and custom_mcu +# Require packages according to upload_protocol and board # import os @@ -9,16 +9,16 @@ class RobcmpPlatform(PlatformBase): def configure_default_packages(self, variables, targets): upload_protocol = variables.get("upload_protocol", "") - custom_mcu = variables.get("custom_mcu") + board = variables.get("board") required_tool = None if upload_protocol == "serial": - if custom_mcu == "avr328p": + if board == "avr328p": required_tool = "tool-avrdude" - elif custom_mcu == "stm32f1": + elif board == "stm32f1": required_tool = "tool-stm32duino" elif upload_protocol == "stlink": - if custom_mcu == "stm32f1": + if board == "stm32f1": required_tool = "tool-openocd" if required_tool: @@ -46,8 +46,9 @@ def _add_default_debug_tools(self, board): debug["tools"]["robcmp"]["server"]["arguments"] = [ "-f", "$PROG_PATH", "-m", debug["target_mcu"], - "-hw", "led" + "-hw", "led", + "-g" ] board.manifest["debug"] = debug - return board \ No newline at end of file + return board diff --git a/platformio/samples/avr328p-blink/src/main.rob b/platformio/samples/avr328p-blink/src/main.rob deleted file mode 100644 index 003b62f..0000000 --- a/platformio/samples/avr328p-blink/src/main.rob +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Robcmp examples: Blink - * Blinks the led on PIN13 - */ - -register int8 portb at 0x25 { - bool pin8; - bool pin9; - bool pin10; - bool pin11; - bool pin12; - bool pin13; -} - -register int8 ddrb at 0x24 { - bool pin8; - bool pin9; - bool pin10; - bool pin11; - bool pin12; - bool pin13; -} - -void wait(int32 q); -void serial_start(int32 clock, int32 baud_rate); -void serial_write(int8 c); - -int16 main() { - arr = {1000000, 500000, 300000, 200000, 100000, 50000}; - - serial_start(16000000, 9600); - - /* pin 13 is controlled by bit 5 of DDRB and PORTB registers - * - bit 5 of DDRB indicates if the pin is input (0) or output (1) - * - bit 5 of PORTB toggles pin HIGH or LOW - */ - - // set pin 13 as output - ddrb.pin13 = true; - - i = 0; - t = 5; - loop { - portb.pin13 = true; - wait(arr[i]); - - portb.pin13 = false; - wait(arr[i]); - - t--; - if (t == 0) { - t = 5; - i++; - if (i == 6) { - i = 0; - } - } - serial_write(65); - serial_write(66); - serial_write(67); - serial_write(10); - } -} diff --git a/platformio/toolchain-robcmp/Makefile b/platformio/toolchain-robcmp/Makefile index b355ded..8697bec 100644 --- a/platformio/toolchain-robcmp/Makefile +++ b/platformio/toolchain-robcmp/Makefile @@ -25,7 +25,24 @@ ifeq ($(LLVM_SIZE),) $(error "Can't find llvm-size!") endif -TOOLS=$(LLVM_OBJCOPY) $(LLVM_LD) $(LLVM_SIZE) ../../robcmp +AVR_GDB=$(shell which avr-gdb) +ifeq ($(AVR_GDB),) + $(error "Can't find avr-gdb!") +endif + +AVR_OBJDUMP=$(shell which avr-objdump) +ifeq ($(AVR_OBJDUMP),) + $(error "Can't find avr-objdump!") +endif + + +TOOLS=$(LLVM_OBJCOPY) \ + $(LLVM_LD) \ + $(LLVM_SIZE) \ + $(AVR_GDB) \ + $(AVR_OBJDUMP) \ + ../../build/robcmp \ + ../../build/robcmp-simavr-debug ifeq ($(OS),Windows_NT) uname_S := Windows @@ -36,6 +53,7 @@ endif ifeq ($(uname_S), Darwin) suffix=darwin_x86_64 SED=gsed + LIBS=$(shell ./libllvmpathosx.sh ${LLVM_LD}) endif ifeq ($(uname_S), Linux) suffix=linux_x86_64 diff --git a/platformio/toolchain-robcmp/libllvmpathosx.sh b/platformio/toolchain-robcmp/libllvmpathosx.sh new file mode 100755 index 0000000..4673c10 --- /dev/null +++ b/platformio/toolchain-robcmp/libllvmpathosx.sh @@ -0,0 +1,5 @@ +#find libLLVM and some of its dependencies in OSX +libLLVM=`DYLD_PRINT_LIBRARIES=1 $1 -v 2>&1|grep libLLVM|sed "s/.*> //"` +libz3=`DYLD_PRINT_LIBRARIES=1 $1 -v 2>&1|grep libz3|sed "s/.*> //"` +libzstd=`DYLD_PRINT_LIBRARIES=1 $1 -v 2>&1|grep libzstd|sed "s/.*> //"` +echo $libLLVM $libz3 $libzstd diff --git a/platformio/toolchain-robcmp/version b/platformio/toolchain-robcmp/version index 49d5957..3b04cfb 100644 --- a/platformio/toolchain-robcmp/version +++ b/platformio/toolchain-robcmp/version @@ -1 +1 @@ -0.1 +0.2 diff --git a/platformio/vscode-syntax/Makefile b/platformio/vscode-syntax/Makefile new file mode 100644 index 0000000..f0211f4 --- /dev/null +++ b/platformio/vscode-syntax/Makefile @@ -0,0 +1,2 @@ +all: + vsce package diff --git a/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix b/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix new file mode 100644 index 0000000000000000000000000000000000000000..50f66d74ad22c2484e7e0d458bdb48a4e8596dde GIT binary patch literal 3281 zcmaJ@2UHVT8;yh#IeAML-0ENL6A1 z6{QM@^j@V(SGu^$pSX+So`3h7bLP#=Iq$xix!=9_S;By{TmS$F1dwp$w2vc*w${)9 z0PjEm01p5FKm`&|SUehsh5F;sffytf?S{e=UZjrWh7>uPva4&rEzV+4;$S2T!srSM ztE@_uE}O=dYM_MwG+uhCY+O<%)Y?yOxrf(qvbufy-JDibcIiWv)7K0zrxcb9n~(tG zv-zjGn3=Eie-p~uIwABa<_2@ptJ8c$h7V!G39Tmyj+%!X&nskJ$`0T+(1j*qga2;8+jq`l3dSrwK^D^7P${SMA4%DQ8A?4?~1g zo3kdl12<}eELTaSul?Z577gg6xxUXpi8N#R7S0-dKib+fpvnnN4%smE?1JDc=!^0t zKvf>>-KDQ;9IH%$C}*H&VReX#&)F_*&l|VdL?tGt$~A^FY(osW!a8tnQi7}uy#3vA z(l(hGI}v(e_iA-^5dlpSTJ~{W@OE25PQu2X$7Fd+`XeIGxUdVkjUTLP0_=qRV9}7^UfO1xf^+W?895Ogz6{lFyB52vzg#O zt-AJrmcO)orrvPmLrSYl9|8b=ql^v)I4q^<3FmBsyis^3XduSR?>daFR*}VUI}_ZJ zRaLGB+I$4SzM?DcfrK{32-vhNGcL2e?#fa>=5J+DYA?>(84TT&Y9)i!URI3U+7(+4 zE?e|KI68;sn#ng=pEIgGB$_U#5ue6he-iz5!m{f)fum!jLVRHMGh4j7SSmS0nSjVF zY%oz+(9YlN${5XcFG*znEF-5H+2IhD4EO`JgAu-WN9Z9&ro}$IL*fSfi@RT&LRj7V zv7I?b(E3#G0_$I&2%@MuB5mG|@>M@dl5+J!)e2rnth*o59R+d0VcpQ~e!fToRqP&k z9QKa24lYcQ7hJ5A=`im9c8} zYGxqEg0DWBwV2n5kG7+S^NF|#mn(l>maeK$+W7jzBBNb+p!5-^PQ@*sF&qR& zYR8mJ!-gk9M#)?P&t8vmjN?76*u#YFnw8rvu3aD$C;M5L#Bk#TDXJbbxs8xBI%lt= zMt^DD%HdO=pqJ&qOY5rpbd|M@VfxSK2VT!`2*-s#PhH};E_(S$_UV`!a`N1){;|Y{ zQq$9!Jc3LO@$iRt#!&eJHFJw^cuU(0%LH>ClsgVTgQtF8?KYm0TaJAjHA|y+=5njp zN~-Z0!ZRo#+Y-hAq8X7a^rrNo9S{KccM2(XeSkvqlLkg`8zU&j6-b%GKrwCrfa2ia z>nDZ)#oYgX_plAL!hL7$(P;j#GC|Y2%G0`{;ogYI(AMZukmobxT zE_ic+ramwgrFz6}%rEH$JI8s<>IE>LBKj!1E-AnFTS0Uye~#a4&Nk*pemfEm_T!=&r6p1+oc{dt;*spX&?)r`o%kRu0U3zG zEBN9rKnWQ0zeWC?iF{iJT!tdoWvLpPpj*KwMKS6KhkO~5+A?~m?g+0XDjw*Z(B{=G z|6qMQ;H_jws$nOOOrwx)_Nt?9_WhVBxJolRw6o;8uZtN`D_ib4+cCE_*&-E$A(KG_ zV~qSPon0hjgQ1!_T@(0$xAAKdD*_1Hv4MrUO*lcRb61sA zPcH;weKS+Po;9&5CIu?%+T9SGfQr&5Otku|F$LvhkZtG1q6bqpIs&Y?ZIw9n8h1te zNu2eHdcv>DxoC7hItki0HrCb0Iq`Er^4*L{tfC`~m94`#mNK*6;H{8x6UMebykE}Y z?R)#oj266(0&V(J`Yydm%R$OM2=CUz7q2VcEHuWs1KDt|IE;8p49eWD?r;puYE8is z!(nS3U;G}31oY}x&nDy#mal3*9_X02K6ykot+KfARpfLbo1})roTy4`zC6U?Op7X6 zW+u=DCjGo3Hr07QLG z&wh@)e9WWL-%wLvceylPt6crINwYP~x7bm8b=22ys_#iZ_C*i_I`*yI?~lwodP<*$ z6Velh49&1I7pvJH6$A#q#`730%ADV*9E98hsm(ol8W%mmY1ZdXS0MLfdwXsYr={a~ z!bJB%gQ6j?rUCQvEv3S#IISQM||yN{x3WYHIg;E%IP zMO+ShK$dTeyjV?pC=S8j=KKv1Wm`wb@3tuq;TSr<(a_cta7L6>JpA$^`1UPu!p-I_ z1*$lh1Qk)u6k%jDP{nbG<^=HHx3Uz4e6Pw->hQz+e%aXm6XTzIgTD{}fXdKy%Bufo zr?3yOpS%YRotnJ+l^5DavG^Y^@n1RoPe>}nzQ0qGV88N0)94OD{>+7g2-F-nXy()$ z*sr|M(O(euQ{muzs^uTFB&y}_S6-+x{lPal7yt(`sOEK$IjVW>S6*l_h0C8m=D)1W V5=KW^4*+1G9BUMdY-Xa~{SVq9Lx2DP literal 0 HcmV?d00001 diff --git a/platformio/vscode-syntax/robcmpsyntax-0.1.0.vsix b/platformio/vscode-syntax/robcmpsyntax-0.1.0.vsix deleted file mode 100644 index c6ec767854eceec78d881c7eb523030a132388eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3020 zcmaKuc|4SB8^?zkTM-FI))*vX7_wC)X)wr)W$a7J(u`R!qh!~hQL?WSa->388$?B9 zi(?l~_HsDo482*>2=C}UN`20IuIG>YexA?g`91f2UBBylKPWRGNC*Jn<_0vGf3VH> zH@B!~2LQUc0RRyI0N@!&_9T!nM1smC5+)GuPQZA1lE}|&CyB3N0$~fA*A;`KMVXZ) z>Ndg~Y8r*Te=>DuMuw-7Mv{7dEpG_RC;*whDxq7u3B)eeFD{&%bXj|+WJZzK85~+} zA`J2XVf{+@WLNvOC#!QG=v&iNWRx=%)Y|mtiBr;J1n2lW7Vpl$ID@Ch*1trlrIOk~ zMp^0I`OlV;=m)LKqXuWEMg;8`uVW-H*Nt<1IfTODk5i{11-3HjWUb~tk{!eC~fz?fiD|6~x964~XSbJa(d4{Lth zqy%ih9dZLrnWTc&g`DOc5{Gb{5Pb;V>rpVZ^DxYlmW`ee?miW0LIsuU`)T>fc2djP z47x8VDz-z%Uhedd{-z&l9!HPO8CRb@^bKjsd|obT-+A>@>%g$0O7g-;&^@?1Zu?) zeh!Afi^D0{Ga+KLt8?(j)^+8M>_%X`i0E1T^o(szWk6Dpc3+rlGx`Pd3Qkh(QC+C) z@#D%VdaaNTe?~9mO{AgM%iv#f;|64VN|v}#>No9E1sfs*KuuXd9sT11N)+wMdv*01 z8tFrkVtZ>)t6}2Q%N$SD%OW)gT~5+;pqO0E#EgB14vN+hd zdq`Sar;gxAugOh47&R@->`Gli*st<3-KqKbXjzL-Gl4t<2h^lGR#VANqjN`&`3TC_ zN`56Oszya3iWJn~iJWqDBx#H_da#0Dy;{p=Q_BFwH&wR?3 z?Z~YwKgGTB2tatw@o*3t*%~Wm-NE2t>}%}L)joR35?N{o=IaYmSyAY$lGUoO7)xWy zFoMeFv1n)4$b3`fHY+!H6WbvgAy9e?_CnV_wx~mW=yXWB^i+ExrUd#lOs`yKhj|r)hm~1vF;tvrAm1* zJ+U_D%)RvX)qB4GZIPSR)X`b*Y+1Yd7V@mwx29Ibxf8qt+`T=a7l;HejCX*)J9)d; zu_PiP$4ZY#feGYH+npIU1w}RG${XIpS=t#2wMjttR6s@xfolz)c%u|IP=hL&pB5&b z@IToL6nO7%fZ==ii;F0zcTlhfY%Jt)upsxOrfD`&_l^nsJN9H=5xA(1>D83kH*pkU zFdwDcTSu{+`DP)b1@8f5y~D-gHUPi^ z_}BPug8~-Y|9<#&_<`-JzU~)%ST6Wl_kd&r*Y^y0cOx(7UNL3OE>jhdpyqGxe}4)4t63j|jD8=CbZV*P>AJ zG-C+R2jevOm=Xy(yJDhpj^9}iL*&B$s)P~@I=@`qJNevCRvY_3>#kT#b=wHrmX{K{ zVIK8#h*+A1T(ir7eJbH%n#{1tu%HvQ3(7H(e=ReS#FThqWOz-tr_FX;zo5D(?4|1+ z4&0th#$wB6lZV5J3@f*`Sa78(_Z4>>S1rEJE%crC-SpzXOofg{f5fN43l$p;PlH?v zH-ss7BBbr?OsZ_G3y^f+{AcCjEZ{g)V?{Vc=0XNf+0sK=#!K%n$W3|&U}=e}QO;Hc z13_J4Q4{E6@q*g?HSI8|^8pSUUo&4?*3+)Vs$M!P{ogbHa|0@{^8dX7NmmGD_drjQ zsz33(3K?(ycRzluM4F8gaR4S1W)TkeSS>eui;Gamj4I}79%u$8X!OnK5YEqzG+uJ- z7~AUhQ^9NZ7wb01CNz-hd*+ho5E0$HPzQLg3)R%ehxAJu?V)cY{&$a??ldJ#7Cp0A zsgzpnj8(ZYVtchcUxowtpu&97;REuH9PKn2p)_k4ZkJV=9djFvCN+}RdJUay&MJcv zITM!<0=h2_98xK|_;F~R&(|)m@sQ5%=EgEe+%v1=`kWQ>G|3YgXInJx?;jhH_`^{n z*>PVXSTvV11)ghVYFyf{VDNq*&!L33#aNvu4)0r2WmQk5Pqi;=N#rMk&K&=T$aJI@_{Ld5hCqpLlac zCjG|zFif(NQr#l{#H+3T=E#MLMY9snkkY(^C0rS536VeHmezaGLJ@tU-uKu64+gfq zHh}iKky)Vdn06_62%2_i=daA;%km9+$Q@rC-`3Wc{{S4 zYQnkgRyKBh;Q#*%+#v@&a(nj8y+8aD{;cuyx%yq>BkQaGaLVoo>>zJ947X3MohXQW z#lqvaMf}?t_Os-+#10#`DY_E{k(nI3CBHLux573B knct?tP83Aia_wHlzp(*j#=)u^0Kmz*Dp||{?b*KjFa2}>2mk;8 From 8c37c64c33d8438195f2870e3159885eae38d97f Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 20 Aug 2023 17:23:22 -0300 Subject: [PATCH 033/117] Fixes load array after merging pull request. --- src/LoadArray.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index 529e773..61660e6 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -54,8 +54,9 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al } Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); - Value* indexList[2] = {zero, indice}; - GetElementPtrInst* ptr = (GetElementPtrInst*)Builder->CreateGEP(rsym->getLLVMType(), alloc, ArrayRef(indexList), "gep"); - LoadInst *ret = Builder->CreateLoad(ptr->getResultElementType(), ptr, ident.getFullName()); + Value *indexList[2] = {zero, indice}; + Value *ptr = Builder->CreateGEP(rsym->getLLVMType(), alloc, ArrayRef(indexList), "gep"); + Type *elemType = buildTypes->llvmType(rsym->getElementDt()); + LoadInst *ret = Builder->CreateLoad(elemType, ptr, ident.getFullName()); return ret; } From aaf15f5334b62e1dc30826a6dabadb624970c8ec Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 20 Aug 2023 19:47:42 -0300 Subject: [PATCH 034/117] Fixes failing tests using type/interface. --- src/BackLLVM.cpp | 17 +++++++++++ src/FunctionCall.cpp | 64 +++++++++++++++++------------------------ src/FunctionImpl.cpp | 30 ++++++++++--------- src/Load.cpp | 14 +++++++-- src/Load.h | 3 ++ src/MemCopy.cpp | 12 ++++---- src/Node.h | 9 ++++++ src/Scalar.cpp | 8 ++++-- src/Variable.cpp | 9 ++++-- test/general/Makefile | 4 +-- test/general/byref.rob | 2 +- test/general/runtest.sh | 2 +- 12 files changed, 107 insertions(+), 67 deletions(-) diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index e82f12a..d3142c3 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -134,6 +135,16 @@ void print_llvm_ir(char opt_level) { // it being invalid. if (debugopt) { mainmodule->print(outs(), nullptr); + + for(auto &f : mainmodule->getFunctionList()) { + if (verifyFunction(f, &llvm::errs())) { + cerr << "Error(s) detected while verifying function " << f.getName().str() << endl; + } + } + + if (verifyModule(*mainmodule), &llvm::errs()) + cerr << "Error(s) detected while verifying the global module." << endl; + return; } @@ -175,4 +186,10 @@ void setTarget(const char *targetarch) { break; } } + + // must set cpu before function generation + if (currentTargetId == st_native) { + static string defaultcpu = sys::getHostCPUName().str(); + supportedTargets[0].cpu = defaultcpu.c_str(); + } } diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index e1983a8..7ef7793 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -40,13 +40,16 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock // call with only one parameter is a cast if (p == 1) { - Cast ca(dt, parameters->getParamElement(0)); + Node *param = parameters->getParamElement(0); + Cast ca(dt, param); ca.setScope(this); - ca.children()[0]->setScope(&ca); + if (!param->getScope()) + param->setScope(&ca); return ca.generate(func, block, allocblock); } else if (p == 0) { // it's a constructor // alloc + Builder->SetInsertPoint(block); Value *var = leftValue->getLLVMValue(func); if (var == NULL) { Builder->SetInsertPoint(allocblock); @@ -55,7 +58,7 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock leftValue->setAlloca(var); leftValue->setDataType(dt); if (debug_info) - RobDbgInfo.declareVar(this, var, allocblock); + RobDbgInfo.declareVar(leftValue, var, allocblock); } vector args; args.push_back(var); @@ -69,12 +72,15 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock return NULL; FunctionBase *initfunc = dynamic_cast(fsymbol); + Builder->SetInsertPoint(block); + if (initfunc->needsParent()) { - args.push_back(initfunc->findMember("#this")->getLLVMValue(NULL)); + Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); + Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + args.push_back(ptr); } - Builder->SetInsertPoint(block); - Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); + CallInst *c = Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); return NULL; } } @@ -93,33 +99,27 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock return NULL; } + if (fsymbol->getNumCodedParams() != parameters->getNumParams()) { + yyerrorcpp(string_format("Function %s has %d argument(s) but was called with %d.", + name.c_str(), fsymbol->getNumCodedParams(), + parameters->getNumParams()), this); + yywarncpp("The function declaration is here.", symbol); + return NULL; + } + dt = fsymbol->getDataType(); - int additionalParams = 0; - Value *parent = NULL; - DataType parentdt = BuildTypes::undefinedType; Value *stem = func->getThisArg(); DataType stemdt = func->getThisArgDt(); - if (stem) - additionalParams = 1; + bool stemIsPointerToPointer = false; Builder->SetInsertPoint(block); if (ident.isComplex()) { Identifier istem = ident.getStem(); Node *n = istem.getSymbol(getScope()); - - if (buildTypes->isInternal(n->getDataType())) { - parent = func->getThisArg(); - parentdt = func->getThisArgDt(); - stem = n->getLLVMValue(func); - stemdt = n->getDataType(); - additionalParams = 2; - } - else { - stem = n->getLLVMValue(func); - stemdt = n->getDataType(); - additionalParams = 1; - } + stem = n->getLLVMValue(func); + stemdt = n->getDataType(); + stemIsPointerToPointer = n->isPointerToPointer(); // TODO: When accessing a.x.func(), need to load a and gep x //Load loadstem(ident.getStem()); @@ -127,14 +127,6 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock //stem = loadstem.generate(func, block, allocblock); } - if (fsymbol->getNumCodedParams() != parameters->getNumParams()) { - yyerrorcpp(string_format("Function %s has %d argument(s) but was called with %d.", - name.c_str(), fsymbol->getNumCodedParams(), - parameters->getNumParams()), this); - yywarncpp("The function declaration is here.", symbol); - return NULL; - } - vector args; for (int i = 0; i < parameters->getNumParams(); i++){ Value *valor = parameters->getParamElement(i)->generate(func, block, allocblock); @@ -152,16 +144,12 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock args.push_back(valor); } + // this parameter if (stem) { - if (buildTypes->isInterface(stemdt)) + if (stemIsPointerToPointer) stem = Builder->CreateLoad(stem->getType()->getPointerTo(), stem, "defer"); args.push_back(stem); } - if (parent) { - if (buildTypes->isInterface(parentdt)) - parent = Builder->CreateLoad(parent->getType()->getPointerTo(), parent, "defer"); - args.push_back(parent); - } ArrayRef argsRef(args); diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 56306fa..32e6757 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -51,11 +51,12 @@ bool FunctionImpl::preGenerate() { attrs.addAttribute("frame-pointer", "all"); attrs.addAttribute("stack-protector-buffer-size", "8"); - /*if (name == "init") // inline constructors + if ((name == "init") || + (node_children.size() == 1)) { + // inline constructors and functions with only one node. + // TODO: Check the resulting binary size. attrs.addAttribute(Attribute::InlineHint); - else - if (node_children.size() == 1) - attrs.addAttribute(Attribute::AlwaysInline);*/ + } if (name == "__vectors") { // FIXME: remove after adding functions attributes to language func->setSection(".vectors"); @@ -78,7 +79,7 @@ bool FunctionImpl::preGenerate() { if (isExternal()) return true; - falloc = BasicBlock::Create(global_context, "entry", func); + falloc = BasicBlock::Create(global_context, "", func); fblock = BasicBlock::Create(global_context, "body", func); RobDbgInfo.emitLocation(this); @@ -91,11 +92,13 @@ bool FunctionImpl::preGenerate() { const string& argname = fp->getName(); Arg.setName(argname); - //Arg.addAttr(Attribute::NoUndef); - Value *variable = &Arg; - if (!buildTypes->isComplex(ptype)) - variable = Builder->CreateAlloca(buildTypes->llvmType(ptype), dataAddrSpace, 0, argname); + Type *talloc = buildTypes->llvmType(ptype); + if (buildTypes->isComplex(ptype)) { + talloc = talloc->getPointerTo(); + fp->setPointerToPointer(true); + } + Value *variable = Builder->CreateAlloca(talloc, dataAddrSpace, 0, argname); if (argname == "#this") { thisArg = variable; @@ -105,8 +108,7 @@ bool FunctionImpl::preGenerate() { fp->setAlloca(variable); - if (!buildTypes->isComplex(ptype)) - Builder->CreateStore(&Arg, variable, false); + Builder->CreateStore(&Arg, variable, false); if (debug_info) { DILocalVariable *d = DBuilder->createParameterVariable(sp, argname, Idx+1, funit, @@ -141,9 +143,11 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo BasicBlock *lb = (BasicBlock*)last_block; Builder->SetInsertPoint(lb); RobDbgInfo.emitLocation(&endfunction); - if (lb->sizeWithoutDebug() == 0 && !lb->hasNPredecessorsOrMore(1)) + if (lb->sizeWithoutDebug() == 0 && !lb->hasNPredecessorsOrMore(1) && + lb != fblock) { lb->eraseFromParent(); - else if (lb->getTerminator() == NULL) { + + } else if (lb->getTerminator() == NULL) { Type *xtype = buildTypes->llvmType(dt); if (!xtype->isVoidTy()) { yyerrorcpp("Missing return statement in function " + name, &endfunction); diff --git a/src/Load.cpp b/src/Load.cpp index 59f4ae4..60cc227 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -86,9 +86,15 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl if (!alloc) return NULL; // Caused by an error on previous statement that defines the symbol - if (buildTypes->isComplex(symbol->getDataType())) + if (buildTypes->isComplex(symbol->getDataType())) { + if (symbol->isPointerToPointer()) { + Type *ty = buildTypes->llvmType(symbol->getDataType())->getPointerTo(); + return Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); + } + if (leftValue) + leftValue->setPointerToPointer(true); return alloc; - else { + } else { Type *ty = buildTypes->llvmType(symbol->getDataType()); return Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), ident.getFullName()); } @@ -98,3 +104,7 @@ bool Load::isConstExpr() { Variable *symbol = dynamic_cast(ident.getSymbol(getScope())); return symbol && symbol->isConstExpr(); } + +void Load::setLeftValue(Variable *symbol) { + leftValue = symbol; +} diff --git a/src/Load.h b/src/Load.h index 259c2fc..eae3cf3 100644 --- a/src/Load.h +++ b/src/Load.h @@ -6,6 +6,8 @@ class Load: public Node { private: Identifier ident; + Variable *leftValue = NULL; + public: Load(const char* i): ident(i) { } Load(Identifier i): ident(i) { } @@ -16,4 +18,5 @@ class Load: public Node { virtual bool isConstExpr() override; + virtual void setLeftValue(Variable *symbol) override; }; diff --git a/src/MemCopy.cpp b/src/MemCopy.cpp index 4ae7aa7..820c80f 100644 --- a/src/MemCopy.cpp +++ b/src/MemCopy.cpp @@ -18,12 +18,13 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo Type *exprvty = exprv->getType(); Type *leftvty; - Builder->SetInsertPoint(allocblock); + Builder->SetInsertPoint(block); Value *dest = leftValue->getLLVMValue(func); if (dest) { leftvty = dest->getType(); } else { leftvty = buildTypes->llvmType(dt); + Builder->SetInsertPoint(allocblock); dest = Builder->CreateAlloca(leftvty, dataAddrSpace, nullptr, leftValue->getName()); leftValue->setAlloca(dest); leftValue->setDataType(dt); @@ -37,15 +38,16 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo return NULL; } - Value *srcalloc = Builder->CreateAlloca(exprvty, dataAddrSpace, nullptr, "src"); + //Builder->SetInsertPoint(allocblock); + //Value *srcalloc = Builder->CreateAlloca(exprvty, dataAddrSpace, nullptr, "src"); - Builder->SetInsertPoint(block); - Value *src = Builder->CreateStore(exprv, srcalloc); + //Builder->SetInsertPoint(block); + //Value *src = Builder->CreateStore(exprv, srcalloc); const DataLayout &dl = mainmodule->getDataLayout(); Value *size = ConstantInt::get(Type::getInt32Ty(global_context), dl.getTypeAllocSize(leftvty)); - Builder->CreateMemCpy(dest, Align(1), srcalloc, Align(1), size); + Builder->CreateMemCpy(dest, Align(1), exprv, Align(1), size); return NULL; } diff --git a/src/Node.h b/src/Node.h index a8137c9..38878d3 100644 --- a/src/Node.h +++ b/src/Node.h @@ -17,6 +17,7 @@ class Node : public SourceLocation { DataType dt = BuildTypes::undefinedType; set qualifiers; Node *scope = nullptr; + bool pointerToPointer = false; public: Node() {} @@ -84,6 +85,14 @@ class Node : public SourceLocation { virtual void setLeftValue(Variable *symbol) {} + bool isPointerToPointer() { + return pointerToPointer; + } + + void setPointerToPointer(bool v) { + pointerToPointer = v; + } + friend class UserType; friend class Program; }; diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 6d9f341..e498c74 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -17,13 +17,13 @@ Scalar::Scalar(const char* ident, Node *e): Variable(ident), expr(e) { Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(allocblock); Node *isymbol = ident.getSymbol(getScope()); Variable *symbol = dynamic_cast(isymbol); if (!symbol) return NULL; + Builder->SetInsertPoint(block); Pointer *reg = NULL; Node *stem = NULL; if (ident.isComplex()) { @@ -47,8 +47,9 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc //stem = loadstem.generate(func, block, allocblock); } - // tell the allocated left value to an eventual - // constructor initializing a user type field + // set the allocated left value to: + // - a constructor initializing a user type field + // - a load for a new variable expr->setLeftValue(symbol); Value *exprv = expr->generate(func, block, allocblock); @@ -56,6 +57,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc return NULL; DataType exprv_dt = expr->getDataType(); + Builder->SetInsertPoint(block); if (!alloc) alloc = symbol->getLLVMValue(func); diff --git a/src/Variable.cpp b/src/Variable.cpp index 12ed0c5..718f200 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -13,11 +13,16 @@ Value *Variable::getLLVMValue(Node *stem) { if (func && func->getThisArg()) { // generating a function of a type: get the gep on #this or #parent parameters Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); - alloc = Builder->CreateStructGEP(thisTy, func->getThisArg(), gepidx, "gepthis"); + Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + alloc = Builder->CreateStructGEP(thisTy, ptr, gepidx, "gepthis"); } else { // accessing a var of a user type: get the gep in the scope (user type) of the scalar Type *udt = buildTypes->llvmType(stem->getDataType()); - alloc = Builder->CreateStructGEP(udt, stem->getLLVMValue(NULL), gepidx, "gepu"); // FIXME + Value *ptr = stem->getLLVMValue(NULL); + if (stem->isPointerToPointer()) { + ptr = Builder->CreateLoad(udt->getPointerTo(), ptr, "deref"); + } + alloc = Builder->CreateStructGEP(udt, ptr, gepidx, "gepu"); // FIXME } } return alloc; diff --git a/test/general/Makefile b/test/general/Makefile index ffa3943..4d6786b 100644 --- a/test/general/Makefile +++ b/test/general/Makefile @@ -1,6 +1,6 @@ ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) -ALL_TT=$(patsubst %.rob,out/%.tt,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) OS=$(shell uname -o) @@ -31,7 +31,7 @@ out/%.o : %.rob ${ROBCMP} Makefile out/%.ll : %.rob ${ROBCMP} Makefile ${ROBCMP} ${OPT} $< > $@ -out/%.tt : %.rob +%.tt : %.rob @-./runtest.sh $< $(patsubst %.rob,out/%,$<) ifeq ($(OS), Msys) diff --git a/test/general/byref.rob b/test/general/byref.rob index 0c9a722..102ca86 100644 --- a/test/general/byref.rob +++ b/test/general/byref.rob @@ -30,7 +30,7 @@ int16 main() { x.y = 17; a.setSubt(x); - if (ss.y == 18) { + if ss.y == 17 { return 0; } return 1; diff --git a/test/general/runtest.sh b/test/general/runtest.sh index 17fc685..a11b6da 100755 --- a/test/general/runtest.sh +++ b/test/general/runtest.sh @@ -3,7 +3,7 @@ GREEN="\033[0;32m" RED="\033[0;31m" NC="\033[0m" -echo -n " $1" +echo -n " ... $1" make -s $2 &> /dev/null if [ "$?" -eq 0 ]; then timeout 10s ./$2 &> /dev/null From 8b199fbc2ab2057f5edd7867f09cb1397c84c04c Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Mon, 28 Aug 2023 20:39:40 -0300 Subject: [PATCH 035/117] Rename special function names using # to : due to incompatibility with linker substitution and rename function calls on interface fields --- src/FunctionCall.cpp | 31 +++++++++++++++++++++++-------- src/FunctionDecl.cpp | 2 +- src/FunctionDecl.h | 10 +++++----- src/FunctionImpl.cpp | 6 +++--- src/FunctionParams.cpp | 2 +- src/Identifier.cpp | 7 +++++++ src/Identifier.h | 2 ++ src/Interface.cpp | 2 +- src/UserType.cpp | 8 ++++---- src/Variable.cpp | 2 +- 10 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 7ef7793..9c5a998 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -63,7 +63,7 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock vector args; args.push_back(var); - // call #init + // call :init Node *type = findSymbol(name); if (!type) return NULL; @@ -109,17 +109,16 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock dt = fsymbol->getDataType(); + Node *stemSymbol = NULL; Value *stem = func->getThisArg(); DataType stemdt = func->getThisArgDt(); - bool stemIsPointerToPointer = false; Builder->SetInsertPoint(block); if (ident.isComplex()) { Identifier istem = ident.getStem(); - Node *n = istem.getSymbol(getScope()); - stem = n->getLLVMValue(func); - stemdt = n->getDataType(); - stemIsPointerToPointer = n->isPointerToPointer(); + stemSymbol = istem.getSymbol(getScope()); + stem = stemSymbol->getLLVMValue(func); + stemdt = stemSymbol->getDataType(); // TODO: When accessing a.x.func(), need to load a and gep x //Load loadstem(ident.getStem()); @@ -145,8 +144,8 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock } // this parameter - if (stem) { - if (stemIsPointerToPointer) + if (stemSymbol) { + if (stemSymbol->isPointerToPointer()) stem = Builder->CreateLoad(stem->getType()->getPointerTo(), stem, "defer"); args.push_back(stem); } @@ -157,6 +156,22 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock Value *vfunc = symbol->getLLVMValue(func); Function *cfunc = dyn_cast(vfunc); + // when calling an interface function, generate a complete name + // to enable injection at link time (symbol name substitution) + if (stemSymbol && buildTypes->isInterface(stemSymbol->getDataType())) { + string inject_name = stemSymbol->getScope()->getName() + ":"; + inject_name.append(stemSymbol->getName() + ":"); + inject_name.append(ident.getLastName()); + Function *intf_cfunc = mainmodule->getFunction(inject_name); + if (!intf_cfunc) { + intf_cfunc = Function::Create(cfunc->getFunctionType(), Function::ExternalLinkage, + codeAddrSpace, inject_name, mainmodule); + intf_cfunc->setDSOLocal(true); + intf_cfunc->setCallingConv(CallingConv::C); + } + cfunc = intf_cfunc; + } + Builder->SetInsertPoint(block); return Builder->CreateCall(cfunc, argsRef); } diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 20a7aa1..b636d07 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -4,7 +4,7 @@ void FunctionBase::addThisArgument(DataType dt) { thisArgDt = dt; - FunctionParam *fp = new FunctionParam("#this", dt); + FunctionParam *fp = new FunctionParam(":this", dt); fp->setScope(this); parameters->append(fp); symbols[fp->getName()] = fp; diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 1528e2e..11107cf 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -12,7 +12,7 @@ class FunctionBase: public NamedNode { bool constructor = false; bool external = false; DataType thisArgDt = BuildTypes::undefinedType; - string userTypeName; + string prefixName; bool validateAndGetArgsTypes(std::vector &args); @@ -68,15 +68,15 @@ class FunctionBase: public NamedNode { return thisArgDt; } - void setUserTypeName(const string& ut) { - userTypeName = ut; + void setPrefixName(const string& prefix) { + prefixName = prefix; } string getFinalName() { - if (userTypeName == "") + if (prefixName == "") return name; else - return userTypeName + "#" + name; + return prefixName + ":" + name; } virtual bool needsParent() { diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 32e6757..5d6b367 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -100,9 +100,9 @@ bool FunctionImpl::preGenerate() { } Value *variable = Builder->CreateAlloca(talloc, dataAddrSpace, 0, argname); - if (argname == "#this") { + if (argname == ":this") { thisArg = variable; - } else if (argname == "#parent") { + } else if (argname == ":parent") { parentArg = variable; } @@ -208,7 +208,7 @@ bool FunctionImpl::validateImplementation(FunctionDecl *decl) { void FunctionImpl::addParentArgument(DataType dt) { parentArgDt = dt; - FunctionParam *fp = new FunctionParam("#parent", dt); + FunctionParam *fp = new FunctionParam(":parent", dt); fp->setScope(this); parameters->append(fp); symbols[fp->getName()] = fp; diff --git a/src/FunctionParams.cpp b/src/FunctionParams.cpp index 0fa6247..0289d7f 100644 --- a/src/FunctionParams.cpp +++ b/src/FunctionParams.cpp @@ -10,7 +10,7 @@ void FunctionParams::append(FunctionParam *e) { unsigned FunctionParams::getNumCodedParams() { unsigned num = 0; for(auto p : parameters) { - if (p->getName()[0] != '#') // don't count parameters #this and #parent + if (p->getName()[0] != ':') // don't count parameters :this and :parent num++; } return num; diff --git a/src/Identifier.cpp b/src/Identifier.cpp index f4b74b9..2f7385e 100644 --- a/src/Identifier.cpp +++ b/src/Identifier.cpp @@ -28,3 +28,10 @@ Identifier Identifier::getStem() { size_t last = ident.find_last_of('.'); return ident.substr(0, last); } + + string const Identifier::getLastName() const { + if (!complex) + return ident; + else + return ident.substr(ident.find_last_of(".")+1); +} diff --git a/src/Identifier.h b/src/Identifier.h index acad8be..2b0e810 100644 --- a/src/Identifier.h +++ b/src/Identifier.h @@ -24,4 +24,6 @@ class Identifier: public SourceLocation { } Identifier getStem(); + + string const getLastName() const; }; diff --git a/src/Interface.cpp b/src/Interface.cpp index 9ef4484..de52828 100644 --- a/src/Interface.cpp +++ b/src/Interface.cpp @@ -41,7 +41,7 @@ Value *Interface::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al for(Node *n : node_children) { FunctionDecl *fd = dynamic_cast(n); if (fd) { - fd->setUserTypeName(getName()); + fd->setPrefixName(getName()); fd->addThisArgument(dt); fd->setExternal(true); fd->generate(func, block, allocblock); diff --git a/src/UserType.cpp b/src/UserType.cpp index 09fe684..323f61b 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -13,7 +13,7 @@ class ParentScalar: public Scalar { public: - ParentScalar(DataType parentDt) : Scalar("parent", new Load("#parent")) { + ParentScalar(DataType parentDt) : Scalar("parent", new Load(":parent")) { expr->setScope(this); dt = parentDt; pointer = pm_pointer; @@ -151,7 +151,7 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all finit->addThisArgument(dt); if (parent) finit->addParentArgument(parent->getDataType()); - finit->setUserTypeName(getName()); + finit->setPrefixName(getName()); finit->setExternal(declaration); finit->generate(func, block, allocblock); @@ -162,7 +162,7 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all */ for(auto & [key, stmt] : getSymbols()) { if (FunctionImpl *f = dynamic_cast(stmt)) { - f->setUserTypeName(getName()); + f->setPrefixName(getName()); f->addThisArgument(dt); for(auto &field : fields) f->addSymbol(dynamic_cast(field)); @@ -192,7 +192,7 @@ unsigned UserType::getFieldStartBit(Node *field) { const string UserType::getName() const { if (parent) - return parent->getName() + "#" + NamedNode::getName(); + return parent->getName() + ":" + NamedNode::getName(); else return NamedNode::getName(); } diff --git a/src/Variable.cpp b/src/Variable.cpp index 718f200..be2cbee 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -11,7 +11,7 @@ Value *Variable::getLLVMValue(Node *stem) { FunctionImpl *func = dynamic_cast(stem); if (func && func->getThisArg()) { - // generating a function of a type: get the gep on #this or #parent parameters + // generating a function of a type: get the gep on :this or :parent parameters Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); alloc = Builder->CreateStructGEP(thisTy, ptr, gepidx, "gepthis"); From 5b76f01839187bed1eb88d98de71435034334e12 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 14 Sep 2023 15:49:17 -0300 Subject: [PATCH 036/117] Support structures to injection --- src/BackLLVM.cpp | 3 +++ src/BackLLVM.h | 3 +++ src/Header.h | 1 + src/Language.l | 5 +++++ src/Language.y | 12 +++++++++++- src/LanguageHeader.y | 2 ++ 6 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index d3142c3..f4f5f80 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -39,6 +39,9 @@ std::unique_ptr buildTypes; unsigned int codeAddrSpace = 1; unsigned int dataAddrSpace = 0; +// Injections +map>> injections; + enum SupportedTargets currentTargetId; extern char *build_outputfilename; diff --git a/src/BackLLVM.h b/src/BackLLVM.h index 4ab910a..2204416 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -25,3 +25,6 @@ extern enum SupportedTargets currentTargetId; extern TargetInfo supportedTargets[__last_target]; void setTarget(const char *targetarch); const TargetInfo& currentTarget(); + +enum BindScope {bs_singleton, bs_transient}; +extern map>> injections; diff --git a/src/Header.h b/src/Header.h index 808cd39..4dd3783 100644 --- a/src/Header.h +++ b/src/Header.h @@ -59,5 +59,6 @@ #include "UserType.h" #include "Enum.h" #include "MemCopy.h" +#include "BackLLVM.h" extern Node* getNodeForIntConst(int64_t i); diff --git a/src/Language.l b/src/Language.l index 829a121..10df15c 100644 --- a/src/Language.l +++ b/src/Language.l @@ -42,6 +42,11 @@ ID {A}({A}|{D})* "implements" { return TOK_IMPL; } "use" { return TOK_USE; } +"bind" { return TOK_BIND; } +"to" { return TOK_TO; } +"singleton" { return TOK_SINGLETON; } +"transient" { return TOK_TRANSIENT; } + "enum" { return TOK_ENUM; } "if" { return TOK_IF; } diff --git a/src/Language.y b/src/Language.y index c78a067..d39962e 100644 --- a/src/Language.y +++ b/src/Language.y @@ -17,6 +17,7 @@ %type simplevar_decl call_or_cast complexvar_set %type term term2 expr factor stmt condblock whileblock logicexpr %type logicterm logicfactor TOK_AND TOK_OR event unary +%type bind %type type_impls %type element @@ -29,7 +30,7 @@ %type paramscall %type TOK_IDENTIFIER TOK_XIDENTIFIER ident_or_xident -%type TOK_INTEGER qualifier +%type TOK_INTEGER qualifier bind_scope %type TOK_FLOAT %type TOK_DOUBLE %type TOK_LDOUBLE @@ -69,6 +70,7 @@ global : use | enum | simplevar_decl ';' | qualifier simplevar_decl ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } + | bind use : TOK_USE TOK_IDENTIFIER ';' { parseUseFile($2, @TOK_USE); @@ -222,6 +224,14 @@ simplevar_decl : TOK_IDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$ simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } +bind : TOK_BIND ident_or_xident[id] TOK_TO ident_or_xident[to] bind_scope[scope] ';' { + //extern map>> injections; + injections[$id].push_back(make_pair(string($to), BindScope($scope))); +} + +bind_scope : TOK_SINGLETON { $$ = bs_singleton; } + | TOK_TRANSIENT { $$ = bs_transient; } + array : '{' elements '}' { $$ = $elements; } matrix : '{' melements '}' { $$ = $melements; } diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index fa30c65..45eb270 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -29,6 +29,8 @@ %token TOK_FFLOAT TOK_FDOUBLE TOK_FCHAR TOK_FLONG TOK_FUNSIGNED TOK_FBOOL %token TOK_TYPE TOK_INTF TOK_IMPL TOK_USE TOK_ENUM +%token TOK_BIND TOK_TO TOK_SINGLETON TOK_TRANSIENT + %token TOK_QUANDO TOK_ESTA %token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT From ba93b8d933ab3e5b24987fb1c4019c1b412695ca Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 14 Sep 2023 17:28:23 -0300 Subject: [PATCH 037/117] Hardware specification merge --- CMakeLists.txt | 13 ++++++- src/Spec.l | 54 ++++++++++++++++++++++++++++ src/Spec.y | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 24 +++++++++++++ 4 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 src/Spec.l create mode 100644 src/Spec.y diff --git a/CMakeLists.txt b/CMakeLists.txt index c0bb193..d10b261 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,8 @@ file(GLOB robcmp_SRC CONFIGURE_DEPENDS ) flex_target(lexer "${CMAKE_CURRENT_SOURCE_DIR}/src/Language.l" "${CMAKE_BINARY_DIR}/Language_l.cpp") +flex_target(lexer_spec "${CMAKE_CURRENT_SOURCE_DIR}/src/Spec.l" "${CMAKE_BINARY_DIR}/Spec_l.cpp") + bison_target(scanner_main "${CMAKE_BINARY_DIR}/Language_gen.y" "${CMAKE_BINARY_DIR}/Language_gen.cpp" @@ -36,6 +38,10 @@ bison_target(scanner_use "${CMAKE_BINARY_DIR}/LanguageUse_gen.y" "${CMAKE_BINARY_DIR}/LanguageUse_gen.cpp" COMPILE_FLAGS "-Wall -Wno-deprecated") +bison_target(scanner_spec + "${CMAKE_CURRENT_SOURCE_DIR}/src/Spec.y" + "${CMAKE_BINARY_DIR}/Spec_y.cpp" + COMPILE_FLAGS "-Wall -Wno-deprecated") # Language_gen.y add_custom_command( @@ -52,9 +58,14 @@ add_custom_command( add_custom_target(parsers DEPENDS ${CMAKE_BINARY_DIR}/Language_gen.y ${CMAKE_BINARY_DIR}/LanguageUse_gen.y) -add_executable(robcmp ${FLEX_lexer_OUTPUTS} ${BISON_scanner_main_OUTPUTS} ${BISON_scanner_use_OUTPUTS} ${robcmp_SRC}) +add_executable(robcmp + ${FLEX_lexer_OUTPUTS} ${FLEX_lexer_spec_OUTPUTS} + ${BISON_scanner_main_OUTPUTS} ${BISON_scanner_use_OUTPUTS} ${BISON_scanner_spec_OUTPUTS} + ${robcmp_SRC}) + add_flex_bison_dependency(lexer scanner_main) add_flex_bison_dependency(lexer scanner_use) +add_flex_bison_dependency(lexer_spec scanner_spec) add_dependencies(robcmp parsers) llvm_map_components_to_libnames(llvm_libs support core irreader passes diff --git a/src/Spec.l b/src/Spec.l new file mode 100644 index 0000000..e71d623 --- /dev/null +++ b/src/Spec.l @@ -0,0 +1,54 @@ +%{ + +#include "FlexDependencies.h" +#include "Spec_y.hpp" + +extern void unescape(char *s); +void specerror(YYLTYPE *loc, yyscan_t yyscanner, const char *s); + +%} + +%option noinput nounput noyywrap +%option yylineno +%option reentrant bison-locations +%option prefix="spec" + +%option yylineno + +D [0-9] +L [a-zA-Z] + +%% + + +[ \t\n\r] { /* espaços */ } + +"port" { return SPEC_PORT; } +"digital" { return SPEC_DIGITAL; } +"pwm" { return SPEC_PWM; } +"name" { return SPEC_NAME; } + +"bind" { return SPEC_BIND; } + +"true" { return SPEC_TRUE; } +"false" { return SPEC_FALSE; } + +"to" { return SPEC_TO; } + +\"[^\"]+\" { yylval->str = strndup(yytext+1, yyleng-2); unescape(yylval->str); return SPEC_STRING; } + +"{" { return '{'; } +"}" { return '}'; } + +"=" { return '='; } +":" { return ':'; } + +{L}({L}|{D})* { return SPEC_PORT_NAME; } + + +{L}({L}|{D})*\.*({L}|{D})* { return SPEC_IDENT; } + +. { specerror(yylloc, NULL, "lexical error, caractere nao pertence ao alfabeto da linguagem:"); } + +%% + diff --git a/src/Spec.y b/src/Spec.y new file mode 100644 index 0000000..2b8c205 --- /dev/null +++ b/src/Spec.y @@ -0,0 +1,97 @@ +%{ + +class Node; +class Stmts; + + +%} + +%locations +%define api.location.type {location_t} +%define api.pure full +%param {yyscan_t scanner} + +%name-prefix="spec" +//%define api.prefix {spec} // not working in Bison 3.8.2 + +%code provides { + #define YY_DECL int speclex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) + YY_DECL; + void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); +} + +%code top { + #ifndef YYLTYPE + #define YYLTYPE location_t + #endif + #include "FlexDependencies.h" +} + +%union { + // char *port; + // char *ident; + char *str; + + + // Node *node; + // Stmts *stmt; +} + + +%token SPEC_PORT SPEC_PORT_NAME SPEC_DIGITAL SPEC_BIND SPEC_IDENT SPEC_TO +%token SPEC_PWM SPEC_NAME SPEC_TRUE SPEC_FALSE SPEC_PORT_IDENT SPEC_STRING + + +%start program + +%% + +program : stmts + ; + +stmts : stmts stmt + | stmt + ; + +stmt : bind + | port_statement + ; + +bind : SPEC_BIND SPEC_IDENT SPEC_TO SPEC_IDENT + ; + +port_statement : SPEC_PORT_NAME '{' port_attributes '}' + ; + +port_attributes : port_attributes port_attribute + | port_attribute + ; + +port_attribute : attribute_digital + | attribute_pwm + | port_bind + ; + +attribute_digital : SPEC_DIGITAL '=' SPEC_TRUE + | SPEC_DIGITAL '=' SPEC_FALSE + ; + +attribute_pwm : SPEC_PWM '=' SPEC_TRUE + | SPEC_PWM '=' SPEC_FALSE + ; + +port_bind : SPEC_BIND '=' SPEC_IDENT { } + ; + + +%% + +extern char *spec_filename; +extern int errorsfound; + +void specerror(YYLTYPE *loc, yyscan_t yyscanner, const char *s) +{ + fprintf(stderr, "%s:%d: error: %s\n", spec_filename, loc->first_line, s); + errorsfound++; +} + diff --git a/src/main.cpp b/src/main.cpp index 2ed0a6e..9622ba0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,6 +10,13 @@ void print_llvm_ir(char opt_level); bool debug_info; extern char *build_outputfilename; +char *spec_filename; +FILE *specin = NULL; +int speclex_init(yyscan_t* scanner); +void specset_in(FILE *_in_str, yyscan_t yyscanner); +int speclex_destroy(yyscan_t yyscanner); +int specparse(yyscan_t scanner); + int main(int argc, char *argv[]) { char optimization = 'z'; @@ -50,12 +57,29 @@ int main(int argc, char *argv[]) { if (i+1 < argc) includeDirs.push_back(argv[++i]); } + else if (strncmp(argv[i], "-s", 2) == 0) { + spec_filename = argv[++i]; + specin = fopen(spec_filename, "r"); + if (specin == NULL) { + fprintf(stderr, "Could not open file %s.\n", spec_filename); + exit(1); + } + } else { buildFileName = argv[i]; } i++; } + if (specin) { + yyscan_t scanner; + speclex_init(&scanner); + specset_in(specin, scanner); + specparse(scanner); + speclex_destroy(scanner); + fclose(specin); + } + // set current target and basic build types setTarget(targetarch); From 5c572c44521d420d5dc2fabacab716d9b6f7b5e0 Mon Sep 17 00:00:00 2001 From: Yago de Matos Date: Tue, 26 Sep 2023 09:46:55 -0300 Subject: [PATCH 038/117] Add injections to global scope --- src/BackLLVM.cpp | 4 +- src/BackLLVM.h | 5 +- src/FunctionCall.cpp | 365 +++++++++++++++++++++++------------------- src/Language.y | 2 +- src/Program.cpp | 34 ++++ src/Spec.l | 5 +- src/Spec.y | 56 +++++-- test/general/bind.rob | 31 ++++ test/general/spec.txt | 5 + 9 files changed, 327 insertions(+), 180 deletions(-) create mode 100644 test/general/bind.rob create mode 100644 test/general/spec.txt diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index f4f5f80..a22ee25 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -39,8 +39,10 @@ std::unique_ptr buildTypes; unsigned int codeAddrSpace = 1; unsigned int dataAddrSpace = 0; + // Injections -map>> injections; +map> injections; +map map_injections; enum SupportedTargets currentTargetId; extern char *build_outputfilename; diff --git a/src/BackLLVM.h b/src/BackLLVM.h index 2204416..bb09d1b 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -26,5 +26,8 @@ extern TargetInfo supportedTargets[__last_target]; void setTarget(const char *targetarch); const TargetInfo& currentTarget(); +class Variable; + enum BindScope {bs_singleton, bs_transient}; -extern map>> injections; +extern map> injections; +extern map map_injections; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 9c5a998..a2686e2 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -8,174 +8,217 @@ #include "Visitor.h" #include "BackLLVM.h" #include "UserType.h" +#include "Program.h" + +extern Program *program; + + DataType FunctionCall::getDataType() { - - if (dt == BuildTypes::undefinedType) { - // is a cast or constructor? - dt = buildTypes->getType(ident.getFullName()); - if (parameters->getNumParams() <= 1 && dt != BuildTypes::undefinedType) { - return dt; - } - - if (!symbol) - symbol = ident.getSymbol(getScope()); - - if (symbol) - dt = symbol->getDataType(); - } - return dt; + + if (dt == BuildTypes::undefinedType) { + // is a cast or constructor? + dt = buildTypes->getType(ident.getFullName()); + if (parameters->getNumParams() <= 1 && dt != BuildTypes::undefinedType) { + return dt; + } + + if (!symbol) + symbol = ident.getSymbol(getScope()); + + if (symbol) + dt = symbol->getDataType(); + } + return dt; } Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - RobDbgInfo.emitLocation(this); - string name = ident.getFullName(); - - // check if it is a cast call - DataType adt = buildTypes->getType(name); - if (adt != BuildTypes::undefinedType) { - dt = adt; - unsigned p = parameters->getNumParams(); - - // call with only one parameter is a cast - if (p == 1) { - Node *param = parameters->getParamElement(0); - Cast ca(dt, param); - ca.setScope(this); - if (!param->getScope()) - param->setScope(&ca); - return ca.generate(func, block, allocblock); - - } else if (p == 0) { // it's a constructor - // alloc - Builder->SetInsertPoint(block); - Value *var = leftValue->getLLVMValue(func); - if (var == NULL) { - Builder->SetInsertPoint(allocblock); - var = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, 0, - leftValue->getName()); - leftValue->setAlloca(var); - leftValue->setDataType(dt); - if (debug_info) - RobDbgInfo.declareVar(leftValue, var, allocblock); - } - vector args; - args.push_back(var); - - // call :init - Node *type = findSymbol(name); - if (!type) - return NULL; - Node *fsymbol = type->findMember("init"); - if (!fsymbol) - return NULL; - FunctionBase *initfunc = dynamic_cast(fsymbol); - - Builder->SetInsertPoint(block); - - if (initfunc->needsParent()) { - Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); - Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); - args.push_back(ptr); - } - - CallInst *c = Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); - return NULL; - } - } - - if (!symbol) - symbol = ident.getSymbol(getScope(), false); - - if (symbol == NULL) { - yyerrorcpp("Function " + name + " not defined.", this); - return NULL; - } - - FunctionBase *fsymbol = dynamic_cast(symbol); - if (fsymbol == NULL) { - yyerrorcpp("Symbol " + name + " is not a function.", this); - return NULL; - } - - if (fsymbol->getNumCodedParams() != parameters->getNumParams()) { - yyerrorcpp(string_format("Function %s has %d argument(s) but was called with %d.", - name.c_str(), fsymbol->getNumCodedParams(), - parameters->getNumParams()), this); - yywarncpp("The function declaration is here.", symbol); - return NULL; - } - - dt = fsymbol->getDataType(); - - Node *stemSymbol = NULL; - Value *stem = func->getThisArg(); - DataType stemdt = func->getThisArgDt(); - - Builder->SetInsertPoint(block); - if (ident.isComplex()) { - Identifier istem = ident.getStem(); - stemSymbol = istem.getSymbol(getScope()); - stem = stemSymbol->getLLVMValue(func); - stemdt = stemSymbol->getDataType(); - - // TODO: When accessing a.x.func(), need to load a and gep x - //Load loadstem(ident.getStem()); - //loadstem.setParent(this->parent); - //stem = loadstem.generate(func, block, allocblock); - } - - vector args; - for (int i = 0; i < parameters->getNumParams(); i++){ - Value *valor = parameters->getParamElement(i)->generate(func, block, allocblock); - if (!valor) - return NULL; - - DataType pdt = fsymbol->getParameters().getParamType(i); - if (buildTypes->isInterface(pdt)) { - valor = Builder->CreateLoad(valor->getType()->getPointerTo(), valor, "defer"); - } else if (!buildTypes->isComplex(pdt)) { - //TODO: we don't support cohercion between user types yet - Type *pty = buildTypes->llvmType(pdt); - valor = Coercion::Convert(valor, pty, block, this); - } - args.push_back(valor); - } - - // this parameter - if (stemSymbol) { - if (stemSymbol->isPointerToPointer()) - stem = Builder->CreateLoad(stem->getType()->getPointerTo(), stem, "defer"); - args.push_back(stem); - } - - ArrayRef argsRef(args); - - Builder->SetInsertPoint(allocblock); - Value *vfunc = symbol->getLLVMValue(func); - Function *cfunc = dyn_cast(vfunc); - - // when calling an interface function, generate a complete name - // to enable injection at link time (symbol name substitution) - if (stemSymbol && buildTypes->isInterface(stemSymbol->getDataType())) { - string inject_name = stemSymbol->getScope()->getName() + ":"; - inject_name.append(stemSymbol->getName() + ":"); - inject_name.append(ident.getLastName()); - Function *intf_cfunc = mainmodule->getFunction(inject_name); - if (!intf_cfunc) { - intf_cfunc = Function::Create(cfunc->getFunctionType(), Function::ExternalLinkage, - codeAddrSpace, inject_name, mainmodule); - intf_cfunc->setDSOLocal(true); - intf_cfunc->setCallingConv(CallingConv::C); - } - cfunc = intf_cfunc; - } - - Builder->SetInsertPoint(block); - return Builder->CreateCall(cfunc, argsRef); + RobDbgInfo.emitLocation(this); + string name = ident.getFullName(); + + + // check if it is a cast call + DataType adt = buildTypes->getType(name); + if (adt != BuildTypes::undefinedType) { + dt = adt; + unsigned p = parameters->getNumParams(); + // call with only one parameter is a cast + if (p == 1) { + Node *param = parameters->getParamElement(0); + Cast ca(dt, param); + ca.setScope(this); + if (!param->getScope()) + param->setScope(&ca); + return ca.generate(func, block, allocblock); + + } else if (p == 0) { // it's a constructor + // alloc + Builder->SetInsertPoint(block); + Value *var = leftValue->getLLVMValue(func); + if (var == NULL) { + Builder->SetInsertPoint(allocblock); + var = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, 0, + leftValue->getName()); + leftValue->setAlloca(var); + leftValue->setDataType(dt); + if (debug_info) + RobDbgInfo.declareVar(leftValue, var, allocblock); + } + vector args; + args.push_back(var); + + // call :init + Node *type = findSymbol(name); + if (!type) + return NULL; + + + Node *fsymbol = type->findMember("init"); + if (!fsymbol) { + //extern map>> injections; + // se presente no injection + // consultar b3, se não criado criar um + // new Scalar("", new FC("b3", new ParamsCall())) + // return new Load("") + + Node *scope = leftValue->getScope(); + UserType *parent= dynamic_cast(scope); + + if (parent == NULL) { + return NULL; + } + + const string toInjection = parent->getName() + "." + leftValue->getName(); + if (injections.count(toInjection) == 0) { + return NULL; + } + + + const string variableName = ":injectionName__" + injections[toInjection].first; + // if (map_injections.count(variableName) == 0) { + // Variable *injectionVariable = new Scalar(variableName, new FunctionCall(injections[toInjection].first, new ParamsCall())); + // map_injections[variableName] = injectionVariable; + + // // TODO: Verificar se a função main já foi gerada + // // injectionVariable->gene + // program->addChild(injectionVariable); + // program->addSymbol(injectionVariable); + // } + + Load ld(variableName); + + ld.setScope(program); + + return ld.generate(func, block, allocblock); + } + + FunctionBase *initfunc = dynamic_cast(fsymbol); + + Builder->SetInsertPoint(block); + + if (initfunc->needsParent()) { + Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); + Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + args.push_back(ptr); + } + + CallInst *c = Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); + return NULL; + } + } + + if (!symbol) + symbol = ident.getSymbol(getScope(), false); + + if (symbol == NULL) { + yyerrorcpp("Function " + name + " not defined.", this); + return NULL; + } + + FunctionBase *fsymbol = dynamic_cast(symbol); + if (fsymbol == NULL) { + yyerrorcpp("Symbol " + name + " is not a function.", this); + return NULL; + } + + if (fsymbol->getNumCodedParams() != parameters->getNumParams()) { + yyerrorcpp(string_format("Function %s has %d argument(s) but was called with %d.", + name.c_str(), fsymbol->getNumCodedParams(), + parameters->getNumParams()), this); + yywarncpp("The function declaration is here.", symbol); + return NULL; + } + + dt = fsymbol->getDataType(); + + Node *stemSymbol = NULL; + Value *stem = func->getThisArg(); + DataType stemdt = func->getThisArgDt(); + + Builder->SetInsertPoint(block); + if (ident.isComplex()) { + Identifier istem = ident.getStem(); + stemSymbol = istem.getSymbol(getScope()); + stem = stemSymbol->getLLVMValue(func); + stemdt = stemSymbol->getDataType(); + + // TODO: When accessing a.x.func(), need to load a and gep x + //Load loadstem(ident.getStem()); + //loadstem.setParent(this->parent); + //stem = loadstem.generate(func, block, allocblock); + } + + vector args; + for (int i = 0; i < parameters->getNumParams(); i++){ + Value *valor = parameters->getParamElement(i)->generate(func, block, allocblock); + if (!valor) + return NULL; + + DataType pdt = fsymbol->getParameters().getParamType(i); + if (buildTypes->isInterface(pdt)) { + valor = Builder->CreateLoad(valor->getType()->getPointerTo(), valor, "defer"); + } else if (!buildTypes->isComplex(pdt)) { + //TODO: we don't support cohercion between user types yet + Type *pty = buildTypes->llvmType(pdt); + valor = Coercion::Convert(valor, pty, block, this); + } + args.push_back(valor); + } + + // this parameter + if (stemSymbol) { + if (stemSymbol->isPointerToPointer()) + stem = Builder->CreateLoad(stem->getType()->getPointerTo(), stem, "defer"); + args.push_back(stem); + } + + ArrayRef argsRef(args); + + Builder->SetInsertPoint(allocblock); + Value *vfunc = symbol->getLLVMValue(func); + Function *cfunc = dyn_cast(vfunc); + + // when calling an interface function, generate a complete name + // to enable injection at link time (symbol name substitution) + if (stemSymbol && buildTypes->isInterface(stemSymbol->getDataType())) { + string inject_name = stemSymbol->getScope()->getName() + ":"; + inject_name.append(stemSymbol->getName() + ":"); + inject_name.append(ident.getLastName()); + Function *intf_cfunc = mainmodule->getFunction(inject_name); + if (!intf_cfunc) { + intf_cfunc = Function::Create(cfunc->getFunctionType(), Function::ExternalLinkage, + codeAddrSpace, inject_name, mainmodule); + intf_cfunc->setDSOLocal(true); + intf_cfunc->setCallingConv(CallingConv::C); + } + cfunc = intf_cfunc; + } + + Builder->SetInsertPoint(block); + return Builder->CreateCall(cfunc, argsRef); } void FunctionCall::accept(Visitor& v) { - v.visit(*this); + v.visit(*this); } diff --git a/src/Language.y b/src/Language.y index d39962e..d315790 100644 --- a/src/Language.y +++ b/src/Language.y @@ -226,7 +226,7 @@ simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); bind : TOK_BIND ident_or_xident[id] TOK_TO ident_or_xident[to] bind_scope[scope] ';' { //extern map>> injections; - injections[$id].push_back(make_pair(string($to), BindScope($scope))); + // injections[$id].push_back(make_pair(string($to), BindScope($scope))); } bind_scope : TOK_SINGLETON { $$ = bs_singleton; } diff --git a/src/Program.cpp b/src/Program.cpp index 5548afb..e2bb95f 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -123,6 +123,40 @@ void Program::generate() { fs.close();*/ // generate the program! + // loop pelo injections + + for (auto injection : injections) { + const string variableName = ":injectionName__" + injection.first; + Variable *injectionVariable = new Scalar(variableName, NULL); + map_injections[variableName] = injectionVariable; + + node_children.insert(node_children.begin(), injectionVariable); + program->addSymbol(injectionVariable); + } + + vector globals; + for (auto injection : injections) { + const string variableName = ":injectionName__" + injection.first; + Variable *injectionVariable = new Scalar(variableName, new FunctionCall(injection.first, new ParamsCall())); + map_injections[variableName] = injectionVariable; + + globals.push_back(injectionVariable); + } + + + FunctionParams *fp = new FunctionParams(); + FunctionImpl *finit = new FunctionImpl((DataType)tvoid, ":injections", fp, + std::move(globals), *this->getLoct(), true); + + finit->generate(NULL, NULL, global_alloc); + + + Node *loadScope = program->findSymbol("main"); + // new FunctionCall(":injections", new ParamsCall()) + + + + for(auto n: children()) n->generate(NULL, NULL, global_alloc); diff --git a/src/Spec.l b/src/Spec.l index e71d623..bb1e32f 100644 --- a/src/Spec.l +++ b/src/Spec.l @@ -42,12 +42,11 @@ L [a-zA-Z] "=" { return '='; } ":" { return ':'; } +";" { return ';'; } -{L}({L}|{D})* { return SPEC_PORT_NAME; } +{L}({L}|{D})*(\.({L}|{D})*)* { yylval->ident = strndup(yytext, yyleng); unescape(yylval->ident); return SPEC_XIDENT; } -{L}({L}|{D})*\.*({L}|{D})* { return SPEC_IDENT; } - . { specerror(yylloc, NULL, "lexical error, caractere nao pertence ao alfabeto da linguagem:"); } %% diff --git a/src/Spec.y b/src/Spec.y index 2b8c205..05d1bf0 100644 --- a/src/Spec.y +++ b/src/Spec.y @@ -1,9 +1,5 @@ %{ -class Node; -class Stmts; - - %} %locations @@ -25,22 +21,50 @@ class Stmts; #define YYLTYPE location_t #endif #include "FlexDependencies.h" + #define SCANNER_OR_VISITOR + #include "Header.h" } %union { // char *port; - // char *ident; + char *ident; char *str; - // Node *node; + Node *node; // Stmts *stmt; -} + // vector *nodes; +} -%token SPEC_PORT SPEC_PORT_NAME SPEC_DIGITAL SPEC_BIND SPEC_IDENT SPEC_TO +/* %union { + char *ident; + char *str; + int64_t nint; + float nfloat; + double ndouble; + long double nldouble; + Node *node; + ArrayElements *aes; + MatrixElements *mes; + FunctionParams *fps; + ParamsCall *pc; + vector *nodes; + vector *strings; + ArrayElement *ae; + MatrixElement *me; + FunctionParam *fp; +} */ + +%token SPEC_PORT SPEC_PORT_NAME SPEC_DIGITAL SPEC_BIND SPEC_IDENT SPEC_TO SPEC_XIDENT %token SPEC_PWM SPEC_NAME SPEC_TRUE SPEC_FALSE SPEC_PORT_IDENT SPEC_STRING +/* %type globals */ +/* %type global bind */ +%type bind +%type SPEC_IDENT SPEC_XIDENT ident + + %start program @@ -54,13 +78,19 @@ stmts : stmts stmt ; stmt : bind - | port_statement + /* | port_statement */ ; -bind : SPEC_BIND SPEC_IDENT SPEC_TO SPEC_IDENT - ; -port_statement : SPEC_PORT_NAME '{' port_attributes '}' +bind : SPEC_BIND ident[id] SPEC_TO ident[to] ';' { + injections.insert({$to, make_pair(string($id), BindScope(bs_singleton))}); +} + +ident : SPEC_IDENT + | SPEC_XIDENT + ; + +/* port_statement : SPEC_PORT_NAME '{' port_attributes '}' ; port_attributes : port_attributes port_attribute @@ -81,7 +111,7 @@ attribute_pwm : SPEC_PWM '=' SPEC_TRUE ; port_bind : SPEC_BIND '=' SPEC_IDENT { } - ; + ; */ %% diff --git a/test/general/bind.rob b/test/general/bind.rob new file mode 100644 index 0000000..5cf290e --- /dev/null +++ b/test/general/bind.rob @@ -0,0 +1,31 @@ +interface port { + int8 get(); +} + +type b3 implements port { + int8 get() { + return 10; + } +} + +type display { + a = 10; + reset = port(); + + int8 get_reset() { + return reset.get(); + } + +} + +int16 main() { + //xxx = b3(); + d = display(); + + r = d.get_reset(); + if r == 11 { + return 0; + } else { + return 1; + } +} \ No newline at end of file diff --git a/test/general/spec.txt b/test/general/spec.txt new file mode 100644 index 0000000..d4fd20e --- /dev/null +++ b/test/general/spec.txt @@ -0,0 +1,5 @@ + + +bind b3 to display.reset; + + From 779654e6d3ea48489eb7fd52f4797bead4e6c645 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 28 Sep 2023 18:19:49 -0300 Subject: [PATCH 039/117] First functional injection without linker \o/ --- src/FunctionCall.cpp | 5 +++ src/Node.cpp | 7 +++- src/Node.h | 2 +- src/NullConst.h | 21 +++++++++++ src/Program.cpp | 88 +++++++++++++++++++++++++++---------------- src/Program.h | 1 + src/UserType.cpp | 6 ++- test/general/bind.rob | 3 +- 8 files changed, 95 insertions(+), 38 deletions(-) create mode 100644 src/NullConst.h diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index a2686e2..62d7816 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -110,6 +110,11 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock ld.setScope(program); + // change FunctionCall datatype to the datatype of the injected var + dt = ld.getDataType(); + Node *lsymbol = findSymbol(leftValue->getName()); + lsymbol->setDataType(dt); + return ld.generate(func, block, allocblock); } diff --git a/src/Node.cpp b/src/Node.cpp index 02d9a2a..2ee46a5 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -51,8 +51,11 @@ Node* Node::findSymbol(const string& name, bool recursive) { return NULL; } -void Node::addChild(Node *n) { - node_children.push_back(n); +void Node::addChild(Node *n, bool prepend) { + if (prepend) + node_children.insert(node_children.begin(), n); + else + node_children.push_back(n); } void Node::addSymbol(NamedNode *nm) { diff --git a/src/Node.h b/src/Node.h index 38878d3..40a9a01 100644 --- a/src/Node.h +++ b/src/Node.h @@ -55,7 +55,7 @@ class Node : public SourceLocation { virtual Node* findMember(const string& name); - void addChild(Node *n); + void addChild(Node *n, bool prepend = false); map const& getSymbols(); diff --git a/src/NullConst.h b/src/NullConst.h new file mode 100644 index 0000000..78282ed --- /dev/null +++ b/src/NullConst.h @@ -0,0 +1,21 @@ + +#pragma once + +#include "BuildTypes.h" +#include "HeaderGlobals.h" +#include "Node.h" + +class NullConst: public Node { +public: + NullConst(DataType dt) { + this->dt = dt; + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + return ConstantPointerNull::get(PointerType::get(buildTypes->llvmType(dt), 0)); + } + + virtual bool isConstExpr() override { + return true; + } +}; diff --git a/src/Program.cpp b/src/Program.cpp index e2bb95f..a1fc667 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -1,6 +1,10 @@ #include "Program.h" +#include "FunctionImpl.h" +#include "HeaderGlobals.h" #include "SymbolizeTree.h" #include "BackLLVM.h" +#include "NullConst.h" +#include Program::Program() { mainmodule = new Module(this->getFile(), global_context); @@ -111,6 +115,32 @@ Value *Program::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo return NULL; } +void Program::generateInjectionSetup() { + // create a function called :injections, to setup global injection vars with + // their singleton instances + FunctionParams *fp = new FunctionParams(); + FunctionImpl *finject = new FunctionImpl((DataType)tvoid, ":injections", fp, + vector(), *this->getLoct(), true); + + vector globals; + for (auto &[key, itype] : injections) { + const string variableName = ":injectionName__" + itype.first; + FunctionCall *fc = new FunctionCall(itype.first, new ParamsCall()); + fc->setScope(finject); + Variable *injectionVariable = new Scalar(variableName, fc); + + globals.push_back(injectionVariable); + } + + for(auto &g : globals) { + finject->addChild(g); + g->setScope(finject); + } + finject->setScope(program); + program->addSymbol(finject); + finject->generate(NULL, NULL, global_alloc); +} + void Program::generate() { // instrumentation passes @@ -123,43 +153,37 @@ void Program::generate() { fs.close();*/ // generate the program! - // loop pelo injections - for (auto injection : injections) { - const string variableName = ":injectionName__" + injection.first; - Variable *injectionVariable = new Scalar(variableName, NULL); - map_injections[variableName] = injectionVariable; + for(auto n: children()) { + if (FunctionImpl *func = dynamic_cast(n)) { + if (func->getName() == "main" || func->getName() == "__main") { + generateInjectionSetup(); + FunctionCall *fc = new FunctionCall(":injections", new ParamsCall()); + fc->setScope(func); + func->addChild(fc, true); + } + } - node_children.insert(node_children.begin(), injectionVariable); - program->addSymbol(injectionVariable); - } - - vector globals; - for (auto injection : injections) { - const string variableName = ":injectionName__" + injection.first; - Variable *injectionVariable = new Scalar(variableName, new FunctionCall(injection.first, new ParamsCall())); - map_injections[variableName] = injectionVariable; + n->generate(NULL, NULL, global_alloc); - globals.push_back(injectionVariable); + // if n is a UserType, there is a injection for it? + if (UserType *ut = dynamic_cast(n)) { + for (auto &[key, itype] : injections) { + if (itype.first == ut->getName()) { + const string variableName = ":injectionName__" + itype.first; + DataType var_dt = buildTypes->getType(itype.first); + Variable *injectionVariable = new Scalar(variableName, new NullConst(var_dt)); + injectionVariable->setScope(program); + map_injections[variableName] = injectionVariable; + + program->addSymbol(injectionVariable); + injectionVariable->generate(NULL, NULL, global_alloc); + break; //TODO: When implementing transient injection, change here. + } + } + } } - - FunctionParams *fp = new FunctionParams(); - FunctionImpl *finit = new FunctionImpl((DataType)tvoid, ":injections", fp, - std::move(globals), *this->getLoct(), true); - - finit->generate(NULL, NULL, global_alloc); - - - Node *loadScope = program->findSymbol("main"); - // new FunctionCall(":injections", new ParamsCall()) - - - - - for(auto n: children()) - n->generate(NULL, NULL, global_alloc); - if (debug_info) DBuilder->finalize(); } diff --git a/src/Program.h b/src/Program.h index 2a056cc..f7cf239 100644 --- a/src/Program.h +++ b/src/Program.h @@ -11,6 +11,7 @@ class Program : public Node { Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); void generate(); + void generateInjectionSetup(); }; extern Program* program; diff --git a/src/UserType.cpp b/src/UserType.cpp index 323f61b..ac37ae1 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -1,11 +1,13 @@ #include "UserType.h" +#include "HeaderGlobals.h" #include "Interface.h" #include "FunctionImpl.h" #include "FunctionParams.h" #include "FunctionCall.h" #include "ParamsCall.h" #include "Program.h" +#include "Variable.h" #include "Visitor.h" #include "Enum.h" #include "Load.h" @@ -72,7 +74,9 @@ bool UserType::createDataType() { } if (v) { - if (v->getPointerMode() == pm_unknown) + if (buildTypes->isInterface(v->getDataType())) + v->setPointer(pm_pointer); + else if (v->getPointerMode() == pm_unknown) v->setPointer(pm_nopointer); Type *llvmType = v->getLLVMType(); diff --git a/test/general/bind.rob b/test/general/bind.rob index 5cf290e..8fa75be 100644 --- a/test/general/bind.rob +++ b/test/general/bind.rob @@ -19,11 +19,10 @@ type display { } int16 main() { - //xxx = b3(); d = display(); r = d.get_reset(); - if r == 11 { + if r == 10 { return 0; } else { return 1; From f4af14d913168f07fb6920e84a4087d04a151055 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 9 May 2024 23:46:03 -0300 Subject: [PATCH 040/117] Fix test with .spec file and other small fixes. --- .gitignore | 3 +++ platformio/install | 5 +++-- platformio/toolchain-robcmp/Makefile | 2 +- src/Spec.y | 5 +++-- src/main.cpp | 2 +- test/general/Makefile | 8 ++++++-- test/general/bind.rob | 2 +- test/general/{spec.txt => bind.spec} | 0 8 files changed, 18 insertions(+), 9 deletions(-) rename test/general/{spec.txt => bind.spec} (100%) diff --git a/.gitignore b/.gitignore index 40178b0..1fc403e 100644 --- a/.gitignore +++ b/.gitignore @@ -63,4 +63,7 @@ avr-ld refdatasheets build test/general/out +test/general/temp.spec test/avr328p/out +platformio/toolchain-robcmp/bin +platformio/toolchain-robcmp/lib diff --git a/platformio/install b/platformio/install index b260b97..b513448 100755 --- a/platformio/install +++ b/platformio/install @@ -3,8 +3,9 @@ cd toolchain-robcmp && tar xfz ../toolchain-robcmp-*.tar.gz cd .. mkdir -p ~/.platformio/platforms mkdir -p ~/.platformio/packages -ln -sf `realpath platform` ~/.platformio/platforms/robcmp -ln -sf `realpath toolchain-robcmp` ~/.platformio/packages/toolchain-robcmp +mkdir -p ~/.platformio/platforms/robcmp +cp -r platform/* ~/.platformio/platforms/robcmp +cp -r toolchain-robcmp ~/.platformio/packages/ code --install-extension vscode-syntax/robcmpsyntax-0.0.1.vsix echo "Open the examples folder and try to build and upload!" echo " code examples/avr328p-blink" diff --git a/platformio/toolchain-robcmp/Makefile b/platformio/toolchain-robcmp/Makefile index 8697bec..b162636 100644 --- a/platformio/toolchain-robcmp/Makefile +++ b/platformio/toolchain-robcmp/Makefile @@ -51,7 +51,7 @@ else endif ifeq ($(uname_S), Darwin) - suffix=darwin_x86_64 + suffix=darwin_$(shell uname -m) SED=gsed LIBS=$(shell ./libllvmpathosx.sh ${LLVM_LD}) endif diff --git a/src/Spec.y b/src/Spec.y index 05d1bf0..8fce795 100644 --- a/src/Spec.y +++ b/src/Spec.y @@ -70,8 +70,9 @@ %% -program : stmts - ; +program : %empty + | stmts + ; stmts : stmts stmt | stmt diff --git a/src/main.cpp b/src/main.cpp index 9622ba0..0d7567b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,7 +30,7 @@ int main(int argc, char *argv[]) { if (t > 1) fprintf(stderr, ","); fprintf(stderr, "%s", supportedTargets[t].name); } - fprintf(stderr, "} -I {include_dir} -g -O{1,2,3,s,z} -o output_file input_file\n"); + fprintf(stderr, "} -I {include_dir} -g -O{1,2,3,s,z} -o output_file -s spec_file input_file\n"); return 1; } diff --git a/test/general/Makefile b/test/general/Makefile index 4d6786b..9007a86 100644 --- a/test/general/Makefile +++ b/test/general/Makefile @@ -26,10 +26,14 @@ clean: .SECONDARY: out/%.o : %.rob ${ROBCMP} Makefile - ${ROBCMP} ${OPT} -o $@ $< + @touch temp.spec && truncate -s 0 temp.spec + @[ -f $(patsubst %.rob,%.spec,$<) ] && cp $(patsubst %.rob,%.spec,$<) temp.spec || true + ${ROBCMP} ${OPT} -s temp.spec -o $@ $< out/%.ll : %.rob ${ROBCMP} Makefile - ${ROBCMP} ${OPT} $< > $@ + @touch temp.spec && truncate -s 0 temp.spec + @[ -f $(patsubst %.rob,%.spec,$<) ] && cp $(patsubst %.rob,%.spec,$<) temp.spec || true + ${ROBCMP} ${OPT} -s temp.spec $< > $@ %.tt : %.rob @-./runtest.sh $< $(patsubst %.rob,out/%,$<) diff --git a/test/general/bind.rob b/test/general/bind.rob index 8fa75be..e0d377d 100644 --- a/test/general/bind.rob +++ b/test/general/bind.rob @@ -27,4 +27,4 @@ int16 main() { } else { return 1; } -} \ No newline at end of file +} diff --git a/test/general/spec.txt b/test/general/bind.spec similarity index 100% rename from test/general/spec.txt rename to test/general/bind.spec From c1f5818eae9d5062d3da78827006f098fb3ae283 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Tue, 21 May 2024 21:08:45 -0300 Subject: [PATCH 041/117] Script to build avr-gdb: adding support M1 Apple --- platformio/avr-gdb-build/build | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100755 platformio/avr-gdb-build/build diff --git a/platformio/avr-gdb-build/build b/platformio/avr-gdb-build/build new file mode 100755 index 0000000..2ded647 --- /dev/null +++ b/platformio/avr-gdb-build/build @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +VERSION=14.2 + +wget -c https://ftp.mirrorservice.org/sites/sourceware.org/pub/gdb/releases/gdb-${VERSION}.tar.xz + +rm -Rf gdb-${VERSION} +tar xf gdb-${VERSION}.tar.xz + +cd gdb-${VERSION} +mkdir build +cd build + +CC=/usr/local/bin/gcc-14 +CXX=/usr/local/bin/g++-14 +GMP=/usr/local/opt/gmp +MPFR=/usr/local/opt/mpfr +CFLAGS="-I/usr/local/include" +CPPFLAGS="-I/usr/local/include" +export CFLAGS +export CPPFLAGS +export CC +export CXX +../configure --target=avr --with-texinfo=no --with-python=no --with-gmp=$GMP --with-mpfr=$MPFR +make -j8 +cp gdb/gdb ../../avr-gdb +echo "Build successfully... run ./avr-gdb to check functionality." From a357ed29b55288c815f6fe780341cd9d7b2317ef Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 23 May 2024 18:47:40 -0300 Subject: [PATCH 042/117] Implements the support for arrays in function calls and other small fixes --- .gitignore | 2 ++ src/Array.cpp | 14 +++++++---- src/Array.h | 13 ++++++++++- src/BinaryOp.cpp | 5 ++-- src/BuildTypes.cpp | 39 +++++++++++++++++++++++++++++-- src/BuildTypes.h | 13 ++++++++++- src/Coercion.cpp | 32 +++++++++++++++++++++++-- src/FlexDependencies.h | 2 +- src/FunctionCall.cpp | 45 ++++++++++++++++++++++++++++-------- src/FunctionDecl.cpp | 9 ++++---- src/FunctionDecl.h | 21 +++++++++++++++++ src/FunctionImpl.cpp | 18 ++++++++------- src/FunctionParams.cpp | 11 +++++++-- src/FunctionParams.h | 24 ++++--------------- src/Header.h | 3 ++- src/Identifier.cpp | 3 +++ src/Language.y | 6 ++++- src/LanguageHeader.y | 2 +- src/LanguageUse.y | 6 ++++- src/Load.cpp | 10 ++++---- src/Load.h | 4 ++++ src/LoadArray.cpp | 8 +++++++ src/Matrix.cpp | 2 +- src/Node.cpp | 8 +++++-- src/Node.h | 3 ++- src/ParamsCall.cpp | 4 ++++ src/ParamsCall.h | 1 + src/Program.cpp | 4 ++-- src/Scalar.cpp | 5 ++-- src/UpdateArray.cpp | 23 ++++++++++++------ src/Variable.h | 4 ++++ src/main.cpp | 16 +++++++++++++ test/general/byref-array.rob | 26 +++++++++++++++++++++ test/general/sort.rob | 18 +++++++-------- 34 files changed, 313 insertions(+), 91 deletions(-) create mode 100644 test/general/byref-array.rob diff --git a/.gitignore b/.gitignore index 1fc403e..890b52d 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ # Debug files *.dSYM/ +.cache/ # Generated robcmp @@ -67,3 +68,4 @@ test/general/temp.spec test/avr328p/out platformio/toolchain-robcmp/bin platformio/toolchain-robcmp/lib +platformio/avr-gdb-build diff --git a/src/Array.cpp b/src/Array.cpp index 753a118..f077ae9 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -3,8 +3,8 @@ #include "Coercion.h" #include "BackLLVM.h" #include "Visitor.h" -#include "Int16.h" #include "FunctionImpl.h" +#include "NamedConst.h" Array::Array(const char *n, ArrayElements *aes) : LinearDataStructure(n), elements(aes) { NamedConst *nc = new NamedConst("size", getNodeForIntConst(aes->getArraySize())); @@ -16,12 +16,14 @@ void Array::createDataType() { if (arrayType != NULL) return; - //Create an Array of Type Int8, and Size = size. + //Create a constant with the array size size = elements->getArraySize(); Value *array_size = ConstantInt::get(Type::getInt8Ty(global_context), size); //Get Type of elements in Array of Elements, and define as I. element_dt = elements->getArrayType(); + dt = buildTypes->getArrayType(buildTypes->name(element_dt), + *this->getLoct(), true); Type* I = buildTypes->llvmType(element_dt); //Declare array type. @@ -89,9 +91,13 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb if (getGEPIndex() != -1) alloc = getLLVMValue(func); - else + else { alloc = Builder->CreateAlloca(arrayType, dataAddrSpace, 0, name); - + if (debug_info) { + RobDbgInfo.emitLocation(this); + RobDbgInfo.declareVar(this, alloc, allocblock); + } + } RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); diff --git a/src/Array.h b/src/Array.h index 833bab4..8d04a49 100644 --- a/src/Array.h +++ b/src/Array.h @@ -4,7 +4,6 @@ #include "Node.h" #include "Variable.h" #include "ArrayElements.h" -#include "NamedConst.h" class ArrayElements; @@ -19,6 +18,18 @@ class LinearDataStructure: public Variable { } }; +class ParamArray: public LinearDataStructure { +public: + ParamArray(const char *n, string element_dt_name, location_t loc): LinearDataStructure(n) { + this->element_dt = buildTypes->getType(element_dt_name, true); + this->dt = buildTypes->getArrayType(element_dt_name, loc, true); + } + + virtual Node *getElementIndex(Node *p1, Node *p2) override { + return p1; + } +}; + class Array: public LinearDataStructure { private: unsigned int size; diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index 544b070..c6cfe55 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -2,7 +2,6 @@ #include "Language_gen_y.hpp" #include "BinaryOp.h" -#include "Int8.h" #include "Coercion.h" BinaryOp::BinaryOp(Node *l, int op, Node *r) { @@ -56,6 +55,7 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, c = dyn_cast(v); } if (c) { + RobDbgInfo.emitLocation(this); int64_t v = c->getUniqueInteger().getZExtValue(); if (Ty1->getIntegerBitWidth() < v) { if (v >= 8 && v <= 15) @@ -79,6 +79,7 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, llvmop = opint; } else { + RobDbgInfo.emitLocation(this); if (Ty1->isIntegerTy()) lhs = Builder->CreateSIToFP(lhs, Ty2, "castitof"); else if (Ty2->isIntegerTy()) @@ -108,6 +109,7 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, } } + RobDbgInfo.emitLocation(this); return Builder->CreateBinOp(llvmop, lhs, rhs, "binop"); } @@ -150,7 +152,6 @@ DataType BinaryOp::getDataType() { } Value *BinaryOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - RobDbgInfo.emitLocation(this); switch (op) { case '+' : return binary_operator(Instruction::Add, Instruction::FAdd, func, block, allocblock); case '-' : return binary_operator(Instruction::Sub, Instruction::FSub, func, block, allocblock); diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index c3dc131..81e9625 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -1,6 +1,8 @@ #include "BuildTypes.h" +#include "HeaderGlobals.h" #include "Node.h" +#include "Scanner.h" #include "Variable.h" #include "BackLLVM.h" @@ -39,11 +41,44 @@ BuildTypes::BuildTypes(DataType targetPointerType) { if (t > 0) // no void bitWidth = dl.getTypeAllocSizeInBits(info.llvmType); info.diType = DBuilder->createBasicType(info.name, bitWidth, info.dwarfEnc); - info.diPointerType = DBuilder->createPointerType(info.diType, 8); + info.diPointerType = DBuilder->createPointerType(info.diType, pts); } } } +DataType BuildTypes::getArrayType(const string& elementName, SourceLocation n, bool createUndefined) { + string arrayTyName = elementName + "[]"; + auto ut = namedTypes.find(arrayTyName); + if (ut == namedTypes.end()) { + if (createUndefined) { + auto elementTyIter = namedTypes.find(elementName); + auto elementInfo = tinfo[elementTyIter->second]; + if (elementTyIter == namedTypes.end() || elementInfo.llvmType == NULL) { + yyerrorcpp(string_format("Type %s is not defined.", + elementName.c_str()), &n, true); + } else { + DataType dt = addDataType(DataTypeInfo(arrayTyName)); + DataTypeInfo &info = tinfo[dt]; + info.llvmType = ArrayType::get(elementInfo.llvmType, 0); // we couldn't know the array size at compile time + info.isDefined = true; + info.isComplex = false; + info.isArray = true; + info.bitWidth = elementInfo.bitWidth; + info.dwarfEnc = dwarf::DW_ATE_address; + if (debug_info) { + info.diType = DBuilder->createArrayType(0, 0, elementInfo.diType, {}); + unsigned ptbw = tinfo[currentTarget().pointerType].bitWidth; + info.diPointerType = DBuilder->createPointerType(elementInfo.diType, ptbw); + } + return dt; + } + } + } else if (tinfo[ut->second].isDefined || createUndefined) { + return ut->second; + } + return undefinedType; +} + DataType BuildTypes::getType(const string& name, bool createUndefined) { auto ut = namedTypes.find(name); if (ut == namedTypes.end()) { @@ -118,7 +153,7 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi RobDbgInfo.currFile(), userType->getLineNo(), bitWidth, 1, 0, DINode::DIFlags::FlagZero, nullptr, dielems); unsigned ptbw = tinfo[currentTarget().pointerType].bitWidth; - info.diPointerType = DBuilder->createPointerType(info.diType, 8); + info.diPointerType = DBuilder->createPointerType(info.diType, ptbw); } return id; } diff --git a/src/BuildTypes.h b/src/BuildTypes.h index a0f8609..f59932c 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -3,6 +3,7 @@ #include #include "HeaderGlobals.h" +#include "SourceLocation.h" typedef int DataType; @@ -27,6 +28,7 @@ struct DataTypeInfo { bool isComplex; bool isInterface; bool isInternal; + bool isArray; DataTypeInfo() {} @@ -41,12 +43,13 @@ struct DataTypeInfo { this->isComplex = false; this->isInternal = false; this->isInterface = false; + this->isArray = false; } DataTypeInfo(const char* name, unsigned bitWidth, Type *llvmType, unsigned dwarfEnc): name(name), bitWidth(bitWidth), llvmType(llvmType), dwarfEnc(dwarfEnc), diType(NULL), diPointerType(NULL), sl(NULL), isDefined(true), isComplex(false), isInternal(false), - isInterface(false) {}; + isInterface(false), isArray(false) {}; }; class BuildTypes { @@ -72,6 +75,9 @@ class BuildTypes { DataType getType(const string& name, bool createUndefined = false); + DataType getArrayType(const string& elementName, SourceLocation n, + bool createUndefined = false); + const char *name(DataType tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].name.c_str(); @@ -139,6 +145,11 @@ class BuildTypes { assert(tid != -1 && "Undefined type"); return tinfo[tid].isInterface; } + + bool isArray(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isArray; + } }; // TODO: Replace all places with buildType::name diff --git a/src/Coercion.cpp b/src/Coercion.cpp index 85d6955..b10b1d5 100644 --- a/src/Coercion.cpp +++ b/src/Coercion.cpp @@ -82,11 +82,39 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati r = Builder->CreateSExt(v, destty, "sext"); } } - else if (!destty->isPointerTy()) { + else { yyerrorcpp("No coercion between " + getTypeName(ty) + " and " + getTypeName(destty) + " implemented.", loc); } + } else { + // check composite types + bool distinct = ty->getNumContainedTypes() != destty->getNumContainedTypes(); + if (!distinct && ty->getNumContainedTypes() > 0) { + for(int i = 0; i < ty->getNumContainedTypes(); i++) { + auto ity = ty->getContainedType(i); + auto dity = destty->getContainedType(i); + if (ity != dity) { + distinct = true; + } else { + if (ity->isIntegerTy() && dity->isIntegerTy()) { + unsigned wity = ity->getIntegerBitWidth(); + unsigned wdity = dity->getIntegerBitWidth(); + if (wity != wdity) + distinct = true; + } else if (ity->isFloatingPointTy() && dity->isFloatingPointTy()) { + unsigned wity = GetFloatingPointBitwidth(ity); + unsigned wdity = GetFloatingPointBitwidth(dity); + if (wity != wdity) + distinct = true; + } + } + if (distinct) + break; + } + if (distinct) + yyerrorcpp("No coercion between " + getTypeName(ty) + " and " + + getTypeName(destty) + " implemented.", loc); + } } return r; - } diff --git a/src/FlexDependencies.h b/src/FlexDependencies.h index e2ada18..b19b255 100644 --- a/src/FlexDependencies.h +++ b/src/FlexDependencies.h @@ -16,7 +16,7 @@ class ParamsCall; class Structure; class ArrayElement; class MatrixElement; -class FunctionParam; +class Variable; class Field; #include "SourceLocation.h" diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 62d7816..189fee1 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -1,4 +1,5 @@ #include "FunctionCall.h" +#include "BuildTypes.h" #include "Cast.h" #include "FunctionDecl.h" #include "FunctionImpl.h" @@ -37,8 +38,7 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock RobDbgInfo.emitLocation(this); string name = ident.getFullName(); - - // check if it is a cast call + // check if it is a cast call: the function name is a primitive type, e.g., int8(x) DataType adt = buildTypes->getType(name); if (adt != BuildTypes::undefinedType) { dt = adt; @@ -176,19 +176,46 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock vector args; for (int i = 0; i < parameters->getNumParams(); i++){ - Value *valor = parameters->getParamElement(i)->generate(func, block, allocblock); + Node *param = parameters->getParamElement(i); + DataType call_dt = param->getDataType(); + DataType def_dt = fsymbol->getParameters().getParamType(i); + + Value *valor = param->generate(func, block, allocblock); if (!valor) return NULL; - - DataType pdt = fsymbol->getParameters().getParamType(i); - if (buildTypes->isInterface(pdt)) { + + if (buildTypes->isInterface(call_dt)) { valor = Builder->CreateLoad(valor->getType()->getPointerTo(), valor, "defer"); - } else if (!buildTypes->isComplex(pdt)) { - //TODO: we don't support cohercion between user types yet - Type *pty = buildTypes->llvmType(pdt); + } else if (buildTypes->isComplex(call_dt)) { + //we don't support cohercion between user types yet + if (call_dt != def_dt) { + yyerrorcpp(string_format("Argument %s expects '%s' but '%s' was provided.", + fsymbol->getParameters().getParamName(i).c_str(), + buildTypes->name(def_dt), + buildTypes->name(call_dt)), this); + yywarncpp("The function declaration is here.", fsymbol); + } + } else if (buildTypes->isArray(call_dt)) { + // we pass the address of the first element + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); + Value *indexList[2] = {zero, zero}; + Value *ptr = Builder->CreateGEP(param->getLLVMType(), valor, ArrayRef(indexList), "gep"); + valor = ptr; + } else { + Type *pty = buildTypes->llvmType(def_dt); valor = Coercion::Convert(valor, pty, block, this); } args.push_back(valor); + + // add a size parameter after each array + if (buildTypes->isArray(call_dt)) { + string psizename = param->getName() + ".size"; + Load ld(psizename); + ld.setScope(func); + valor = ld.generate(func, block, allocblock); + valor = Coercion::Convert(valor, buildTypes->llvmType(tint32), block, this); + args.push_back(valor); + } } // this parameter diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index b636d07..ef7447f 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -4,28 +4,27 @@ void FunctionBase::addThisArgument(DataType dt) { thisArgDt = dt; - FunctionParam *fp = new FunctionParam(":this", dt); + Variable *fp = new Variable(":this", dt); fp->setScope(this); parameters->append(fp); symbols[fp->getName()] = fp; } - bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { bool valid = true; Type *xtype = buildTypes->llvmType(dt); if (!xtype) { - yyerrorcpp(string_format("Type %s not defined.", buildTypes->name(dt)), this); + yyerrorcpp(string_format("Type %s is not defined.", buildTypes->name(dt)), this); valid = false; } for (int i = 0; i < parameters->getParameters().size(); i++) { DataType dt = parameters->getParamType(i); Type *atype = buildTypes->llvmType(dt); - if (buildTypes->isComplex(dt)) { + if (buildTypes->isComplex(dt) || buildTypes->isArray(dt)) { atype = atype->getPointerTo(); } if (!atype) { - yyerrorcpp(string_format("Type %s for argument %s not defined.", + yyerrorcpp(string_format("Type %s for argument %s is not defined.", buildTypes->name(dt), parameters->getParamName(i).c_str()), this); valid = false; } else { diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 11107cf..99373d6 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -1,5 +1,6 @@ #pragma once +#include "BuildTypes.h" #include "Node.h" #include "FunctionParams.h" #include "Variable.h" @@ -20,6 +21,7 @@ class FunctionBase: public NamedNode { FunctionBase(DataType dt, string name, FunctionParams *fp) : NamedNode(name) { this->dt = dt; this->parameters = fp; + addPseudoParameters(); } FunctionBase(DataType dt, string name, FunctionParams *fp, vector &&stmts, @@ -28,6 +30,25 @@ class FunctionBase: public NamedNode { this->dt = dt; this->parameters = fp; this->constructor = constructor; + addPseudoParameters(); + } + + void addPseudoParameters() { + // add a size parameter after each array + std::vector const& vparams = this->parameters->getParameters(); + for (int i = 0; i < vparams.size(); ++i) { + Variable *p = vparams[i]; + if (buildTypes->isArray(p->getDataType())) { + string psizename = p->getName() + ".size"; + + //TODO: There is something better than fix this to Int32? Fix here and in FunctionCall::generate + Variable *sizep = new Variable(psizename.c_str(), tint32); + this->parameters->insert(i+1, sizep); + + // add a pseudo symbol to resolve to pname.size + p->addSymbol("size", sizep); + } + } } FunctionParams& getParameters() { diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 5d6b367..febf098 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -87,14 +87,12 @@ bool FunctionImpl::preGenerate() { unsigned Idx = 0; for (auto &Arg : func->args()) { - FunctionParam *fp = parameters->getParameters()[Idx]; + Variable *fp = parameters->getParameters()[Idx]; DataType ptype = fp->getDataType(); const string& argname = fp->getName(); - Arg.setName(argname); - Type *talloc = buildTypes->llvmType(ptype); - if (buildTypes->isComplex(ptype)) { + if (buildTypes->isComplex(ptype) || buildTypes->isArray(ptype)) { talloc = talloc->getPointerTo(); fp->setPointerToPointer(true); } @@ -111,8 +109,12 @@ bool FunctionImpl::preGenerate() { Builder->CreateStore(&Arg, variable, false); if (debug_info) { + DIType *dit = buildTypes->diType(ptype); + if (buildTypes->isComplex(ptype) || buildTypes->isArray(ptype)) + dit = buildTypes->diPointerType(ptype); + DILocalVariable *d = DBuilder->createParameterVariable(sp, argname, Idx+1, funit, - this->getLineNo(), buildTypes->diType(ptype), true); + this->getLineNo(), dit, true); DBuilder->insertDeclare(variable, d, RobDbgInfo.getFixedOffsetExpression(), DILocation::get(sp->getContext(), this->getLineNo(), 0, sp), falloc); @@ -167,7 +169,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo DISubroutineType *FunctionImpl::getFunctionDIType() { SmallVector Tys; Tys.push_back(buildTypes->diType(dt)); // return type - for(FunctionParam *p : parameters->getParameters()) { + for(Variable *p : parameters->getParameters()) { Tys.push_back(buildTypes->diType(p->getDataType())); } return DBuilder->createSubroutineType(DBuilder->getOrCreateTypeArray(Tys)); @@ -186,7 +188,7 @@ bool FunctionImpl::validateImplementation(FunctionDecl *decl) { } int compareno = std::min(pnum_impl, pnum_decl); for(int i = 0; i < compareno; i++) { - FunctionParam *p = decl_parameters.getParameters()[i]; + Variable *p = decl_parameters.getParameters()[i]; if (p->getDataType() != parameters->getParamType(i)) { yyerrorcpp(string_format("Argument %s has distinct type in declaration '%s' and definition '%s'.", parameters->getParamName(i).c_str(), buildTypes->name(p->getDataType()), @@ -208,7 +210,7 @@ bool FunctionImpl::validateImplementation(FunctionDecl *decl) { void FunctionImpl::addParentArgument(DataType dt) { parentArgDt = dt; - FunctionParam *fp = new FunctionParam(":parent", dt); + Variable *fp = new Variable(":parent", dt); fp->setScope(this); parameters->append(fp); symbols[fp->getName()] = fp; diff --git a/src/FunctionParams.cpp b/src/FunctionParams.cpp index 0289d7f..189c319 100644 --- a/src/FunctionParams.cpp +++ b/src/FunctionParams.cpp @@ -3,14 +3,21 @@ FunctionParams::FunctionParams() {}; -void FunctionParams::append(FunctionParam *e) { +void FunctionParams::append(Variable *e) { parameters.push_back(e); }; + +void FunctionParams::insert(int at, Variable *fp) { + parameters.insert(parameters.begin() + at, fp); +} unsigned FunctionParams::getNumCodedParams() { unsigned num = 0; for(auto p : parameters) { - if (p->getName()[0] != ':') // don't count parameters :this and :parent + // don't count parameters :this, :parent, and other pseudo + // parameters like _any_.size, _any_.cols + if (p->getName().find(':') == string::npos && + p->getName().find('.') == string::npos) num++; } return num; diff --git a/src/FunctionParams.h b/src/FunctionParams.h index 2e77e0b..3057a41 100644 --- a/src/FunctionParams.h +++ b/src/FunctionParams.h @@ -3,36 +3,20 @@ #include "Node.h" #include "Variable.h" -class FunctionParam: public Variable { -public: - FunctionParam(const char *name, DataType dt): Variable(name) { - this->dt = dt; - } - - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - return NULL; - } - - void setAlloca(Value *alloc) { - this->alloc = alloc; - } - - friend class FunctionImpl; -}; - class FunctionParams { private: - std::vector parameters; + std::vector parameters; public: FunctionParams(); - void append(FunctionParam *fp); + void append(Variable *fp); + void insert(int at, Variable *fp); unsigned getNumCodedParams(); DataType getParamType (int position); const string getParamName (int position); - std::vector const& getParameters() { + std::vector const& getParameters() { return parameters; } }; diff --git a/src/Header.h b/src/Header.h index 4dd3783..32a603d 100644 --- a/src/Header.h +++ b/src/Header.h @@ -25,7 +25,7 @@ #include "FunctionCall.h" #include "FunctionDecl.h" #include "FunctionImpl.h" -#include "FunctionParams.h" +#include "Variable.h" #include "If.h" #include "Int1.h" #include "Int8.h" @@ -60,5 +60,6 @@ #include "Enum.h" #include "MemCopy.h" #include "BackLLVM.h" +#include "NamedConst.h" extern Node* getNodeForIntConst(int64_t i); diff --git a/src/Identifier.cpp b/src/Identifier.cpp index 2f7385e..d8fa7c4 100644 --- a/src/Identifier.cpp +++ b/src/Identifier.cpp @@ -3,6 +3,9 @@ Node* Identifier::getSymbol(Node *scope, bool validate) { + if (scope == NULL) + assert("scope can't be null!"); + Node *result = scope; stringstream ss(ident); string ci; diff --git a/src/Language.y b/src/Language.y index d315790..f32bd3a 100644 --- a/src/Language.y +++ b/src/Language.y @@ -143,7 +143,11 @@ function_params: %empty { } function_param : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] { - $$ = new FunctionParam($id, buildTypes->getType($type, true)); + $$ = new Variable($id, buildTypes->getType($type, true)); +} + +function_param : TOK_IDENTIFIER[type] '[' ']' TOK_IDENTIFIER[id] { + $$ = new ParamArray($id, $type, @type); } register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT expr ';' { diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index 45eb270..0a2b37f 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -50,7 +50,7 @@ vector *strings; ArrayElement *ae; MatrixElement *me; - FunctionParam *fp; + Variable *fp; } %start programa diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 11ca2d3..1b1fb63 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -129,7 +129,11 @@ function_params: %empty { } function_param : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] { - $$ = new FunctionParam($id, buildTypes->getType($type, true)); + $$ = new Variable($id, buildTypes->getType($type, true)); +} + +function_param : TOK_IDENTIFIER[type] '[' ']' TOK_IDENTIFIER[id] { + $$ = new ParamArray($id, $type, @type); } register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT const_expr ';' { diff --git a/src/Load.cpp b/src/Load.cpp index 60cc227..e440958 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -1,7 +1,6 @@ #include "Load.h" -#include "HeaderExternals.h" -#include "Scalar.h" +#include "BuildTypes.h" #include "FunctionImpl.h" #include "Variable.h" #include "Pointer.h" @@ -86,16 +85,17 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl if (!alloc) return NULL; // Caused by an error on previous statement that defines the symbol - if (buildTypes->isComplex(symbol->getDataType())) { + DataType sdt = symbol->getDataType(); + if (buildTypes->isComplex(sdt) || buildTypes->isArray(sdt)) { if (symbol->isPointerToPointer()) { - Type *ty = buildTypes->llvmType(symbol->getDataType())->getPointerTo(); + Type *ty = buildTypes->llvmType(sdt)->getPointerTo(); return Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); } if (leftValue) leftValue->setPointerToPointer(true); return alloc; } else { - Type *ty = buildTypes->llvmType(symbol->getDataType()); + Type *ty = buildTypes->llvmType(sdt); return Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), ident.getFullName()); } } diff --git a/src/Load.h b/src/Load.h index eae3cf3..b55be93 100644 --- a/src/Load.h +++ b/src/Load.h @@ -19,4 +19,8 @@ class Load: public Node { virtual bool isConstExpr() override; virtual void setLeftValue(Variable *symbol) override; + + virtual const string getName() const override { + return ident.getFullName(); + } }; diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index 61660e6..5c0edf8 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -46,6 +46,9 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al alloc = rsym->getLLVMValue(func); } + if (!alloc) + return NULL; + Node *indn = getElementIndex(rsym); Value *indice = indn->generate(func, block, allocblock); if (!indice || !indice->getType()->isIntegerTy()){ @@ -53,6 +56,11 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al return NULL; } + if (rsym->isPointerToPointer()) { + Type *ty = buildTypes->llvmType(rsym->getDataType())->getPointerTo(); + alloc = Builder->CreateLoad(ty, alloc, rsym->hasQualifier(qvolatile), "deref"); + } + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); Value *indexList[2] = {zero, indice}; Value *ptr = Builder->CreateGEP(rsym->getLLVMType(), alloc, ArrayRef(indexList), "gep"); diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 47f1178..218ab30 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -3,9 +3,9 @@ #include "Array.h" #include "BinaryOp.h" #include "Visitor.h" -#include "Int16.h" #include "BackLLVM.h" #include "FunctionImpl.h" +#include "NamedConst.h" Matrix::Matrix(const char *n, MatrixElements *me) : LinearDataStructure(n), melements(me) { NamedConst *rows = new NamedConst("rows", getNodeForIntConst(me->getRowCount())); diff --git a/src/Node.cpp b/src/Node.cpp index 2ee46a5..d54556e 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -59,10 +59,14 @@ void Node::addChild(Node *n, bool prepend) { } void Node::addSymbol(NamedNode *nm) { + addSymbol(nm->getName(), nm); +} + +void Node::addSymbol(const string& label, NamedNode *nm) { // if the variable is already defined here or in a parent // scope, don't add it again. - if (!findSymbol(nm->getName(), true)) { - symbols[nm->getName()] = nm; + if (!findSymbol(label, true)) { + symbols[label] = nm; } } diff --git a/src/Node.h b/src/Node.h index 40a9a01..a73c5f8 100644 --- a/src/Node.h +++ b/src/Node.h @@ -59,8 +59,9 @@ class Node : public SourceLocation { map const& getSymbols(); + virtual void addSymbol(const string& label, NamedNode *nm); virtual void addSymbol(NamedNode *nm); - + void setDataType(DataType dt) { this->dt = dt; } diff --git a/src/ParamsCall.cpp b/src/ParamsCall.cpp index 2ff8154..d4254aa 100644 --- a/src/ParamsCall.cpp +++ b/src/ParamsCall.cpp @@ -6,6 +6,10 @@ ParamsCall::ParamsCall() {}; void ParamsCall::append(Node *n) { parameters.push_back(n); }; + +void ParamsCall::insert(int at, Node *pc) { + parameters.insert(parameters.begin() + at, pc); +} unsigned ParamsCall::getNumParams() const { return parameters.size(); diff --git a/src/ParamsCall.h b/src/ParamsCall.h index 4d0efd1..fb3c39b 100644 --- a/src/ParamsCall.h +++ b/src/ParamsCall.h @@ -9,6 +9,7 @@ class ParamsCall { public: ParamsCall(); void append(Node *pc); + void insert(int at, Node *pc); unsigned getNumParams() const; Node *getParamElement (int position) const; diff --git a/src/Program.cpp b/src/Program.cpp index a1fc667..2c768d0 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -14,7 +14,7 @@ Program::Program() { mainmodule->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION); mainmodule->addModuleFlag(Module::Warning, "Dwarf Version", 4); DBuilder = make_unique(*mainmodule); - RobDbgInfo.cunit = DBuilder->createCompileUnit(dwarf::DW_LANG_C, + RobDbgInfo.cunit = DBuilder->createCompileUnit(dwarf::DW_LANG_C11, DBuilder->createFile(this->getFile(), std::filesystem::current_path().string()), "Robcmp", false, "", 0); @@ -156,7 +156,7 @@ void Program::generate() { for(auto n: children()) { if (FunctionImpl *func = dynamic_cast(n)) { - if (func->getName() == "main" || func->getName() == "__main") { + if (injections.size() > 0 && (func->getName() == "main" || func->getName() == "__main")) { generateInjectionSetup(); FunctionCall *fc = new FunctionCall(":injections", new ParamsCall()); fc->setScope(func); diff --git a/src/Scalar.cpp b/src/Scalar.cpp index e498c74..57d5f49 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -16,8 +16,6 @@ Scalar::Scalar(const char* ident, Node *e): Variable(ident), expr(e) { Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - RobDbgInfo.emitLocation(this); - Node *isymbol = ident.getSymbol(getScope()); Variable *symbol = dynamic_cast(isymbol); if (!symbol) @@ -89,6 +87,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc } } } else { + RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(allocblock); AllocaInst *temp = Builder->CreateAlloca(exprv->getType(), dataAddrSpace, 0, name); temp->setAlignment(Align(1)); @@ -130,6 +129,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc if (pm == pm_pointer) currty = currty->getPointerTo(); + RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); Value *nvalue = NULL; @@ -168,6 +168,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc nvalue = Coercion::Convert(exprv, currty, block, symbol); } + RobDbgInfo.emitLocation(this); return Builder->CreateStore(nvalue, alloc, symbol->hasQualifier(qvolatile)); } } diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index 4c2ae3f..e58c85d 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -3,6 +3,7 @@ #include "Coercion.h" #include "Array.h" #include "FunctionImpl.h" +#include "HeaderGlobals.h" UpdateArray::UpdateArray(const char *i, Node *pos, Node *expr): ident(i), position(pos), expr(expr) { addChild(pos); @@ -25,8 +26,8 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * ty = aux->getValueType(); ArrayType *arrayTy = NULL; - if (ty->isArrayTy()) { - arrayTy = (ArrayType*)ty; + if (buildTypes->isArray(rsym->getDataType())) { + arrayTy = (ArrayType*)buildTypes->llvmType(rsym->getDataType()); } else { yyerrorcpp("Symbol " + ident.getFullName() + " is not an array.", this); @@ -40,13 +41,21 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * return NULL; } - Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); - - Value* indexList[2] = {zero, indice}; - GetElementPtrInst* ptr = GetElementPtrInst::Create(arrayTy, sym, ArrayRef(indexList), "", block); Value *val = expr->generate(func, block, allocblock); val = Coercion::Convert(val, arrayTy->getArrayElementType(), block, this); - StoreInst *store = new StoreInst(val, ptr, false, block); + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + if (rsym->isPointerToPointer()) { + Type *ty = buildTypes->llvmType(rsym->getDataType())->getPointerTo(); + sym = Builder->CreateLoad(ty, sym, rsym->hasQualifier(qvolatile), "deref"); + } + + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); + Value *indexList[2] = {zero, indice}; + Value *ptr = Builder->CreateGEP(arrayTy, sym, ArrayRef(indexList), "gep"); + StoreInst *store = Builder->CreateStore(val, ptr, false); return store; } diff --git a/src/Variable.h b/src/Variable.h index bad7d5f..f51ba38 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -15,6 +15,10 @@ class Variable: public NamedNode { public: Variable(const string &name): NamedNode(name), ident(name) {} + + Variable(const string &name, DataType dt): NamedNode(name), ident(name) { + this->dt = dt; + } virtual Value* getLLVMValue(Node *stem) override; diff --git a/src/main.cpp b/src/main.cpp index 0d7567b..0424efc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,7 +17,23 @@ void specset_in(FILE *_in_str, yyscan_t yyscanner); int speclex_destroy(yyscan_t yyscanner); int specparse(yyscan_t scanner); +#include +#include +void SIGSEGV_handler(int sig) { + void *array[10]; + size_t size; + + // get void*'s for all entries on the stack + size = backtrace(array, 10); + + // print out all the frames to stderr + fprintf(stderr, "Error: signal %d:\n", sig); + backtrace_symbols_fd(array, size, STDERR_FILENO); + exit(1); +} + int main(int argc, char *argv[]) { + signal(SIGSEGV, SIGSEGV_handler); char optimization = 'z'; const char *targetarch = ""; diff --git a/test/general/byref-array.rob b/test/general/byref-array.rob new file mode 100644 index 0000000..dcc8c67 --- /dev/null +++ b/test/general/byref-array.rob @@ -0,0 +1,26 @@ + +int32 sum_array(int16[] a); + +int8 main() { + x = {int16(0), 1, 2, 3, 4, 5, 6, 7, 8, 9}; + if sum_array(x) == 45 + 1 + 10 { + return 0; + } else { + return 1; + } +} + +int32 pass_array_pointer(int16[] b) { + result = b[1] + b.size; + return result; +} + +int32 sum_array(int16[] a) { + i = 0; + result = int32(0); + while i < a.size { + result += a[i]; + i++; + } + return result + pass_array_pointer(a); +} diff --git a/test/general/sort.rob b/test/general/sort.rob index d26d18d..aeb561e 100644 --- a/test/general/sort.rob +++ b/test/general/sort.rob @@ -2,16 +2,11 @@ * sorts the vector a and check the result */ -a = { 34, -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; -r = { -9, -5, -3, 0, 6, 6, 11, 12, 12, 17, 22, 22, 34, 44, 56, 100 }; - -void sort(int8 n) { - t = 0; - s = 0; - temp = 0; - while t < n - 1 { +void sort(int16[] a) { + t = int16(0); + while t < a.size - 1 { s = t + 1; - while s < n { + while s < a.size { if a[t] > a[s] { temp = a[t]; a[t] = a[s]; @@ -24,7 +19,10 @@ void sort(int8 n) { } int16 main() { - sort(a.size); + a = {int16(34), -5, 6, 0, 12, 100, 56, 22, 44, -3, -9, 12, 17, 22, 6, 11 }; + r = {int16(-9), -5, -3, 0, 6, 6, 11, 12, 12, 17, 22, 22, 34, 44, 56, 100 }; + + sort(a); i = 0; while i < a.size { if a[i] != r[i] { From 91cf03bb2b38ccde0234725886164cbbdc9c2aa9 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Fri, 24 May 2024 23:32:56 -0300 Subject: [PATCH 043/117] Improves boolean support in the language; fix returning of type instances --- src/BinaryOp.cpp | 8 ++++++++ src/CmpOp.cpp | 1 + src/Language.l | 5 +++-- src/Language.y | 21 ++++++++++++--------- src/Return.cpp | 6 ++++++ test/general/bitstruct.rob | 2 +- test/general/bool.rob | 20 ++++++++++++++++++++ test/general/itoa.rob | 19 +++++++++---------- test/general/return_a_type.rob | 20 ++++++++++++++++++++ 9 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 test/general/bool.rob create mode 100644 test/general/return_a_type.rob diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index c6cfe55..68bad89 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -18,6 +18,14 @@ Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, Value *lhs = lhsn->generate(func, block, allocblock); Value *rhs = rhsn->generate(func, block, allocblock); + Type *lhsty = lhs->getType(); + Type *rhsty = rhs->getType(); + if (!lhsty->isIntegerTy() || !(lhsty->getIntegerBitWidth() == 1)) + yyerrorcpp("The left side of the logical expression is not boolean.", this); + + if (!rhsty->isIntegerTy() || !(rhsty->getIntegerBitWidth() == 1)) + yyerrorcpp("The right side of the logical expression is not boolean.", this); + Builder->SetInsertPoint(block); return Builder->CreateBinOp(op, lhs, rhs, "logicop"); } diff --git a/src/CmpOp.cpp b/src/CmpOp.cpp index 9ea80ad..1889ecb 100644 --- a/src/CmpOp.cpp +++ b/src/CmpOp.cpp @@ -6,6 +6,7 @@ CmpOp::CmpOp (Node *l, int op, Node *r) : lexpn(l), rexpn(r) { this->op = op; + this->dt = tbool; addChild(lexpn); addChild(rexpn); } diff --git a/src/Language.l b/src/Language.l index 10df15c..33859bb 100644 --- a/src/Language.l +++ b/src/Language.l @@ -61,6 +61,9 @@ ID {A}({A}|{D})* "and" { return TOK_AND; } "or" { return TOK_OR; } +"<<" { return TOK_LSHIFT; } +">>" { return TOK_RSHIFT; } + "!" { return '!'; } "<" { return '<'; } ">" { return '>'; } @@ -85,8 +88,6 @@ ID {A}({A}|{D})* "&" { return '&'; } "^" { return '^'; } "~" { return '~'; } -"<<" { return TOK_LSHIFT; } -">>" { return TOK_RSHIFT; } ":" { return ':'; } "." { return '.'; } diff --git a/src/Language.y b/src/Language.y index f32bd3a..aaf5ec1 100644 --- a/src/Language.y +++ b/src/Language.y @@ -16,7 +16,7 @@ %type enum enum_item interface_impl %type simplevar_decl call_or_cast complexvar_set %type term term2 expr factor stmt condblock whileblock logicexpr -%type logicterm logicfactor TOK_AND TOK_OR event unary +%type logicterm logicfactor TOK_AND TOK_OR event unary logicunary %type bind %type type_impls @@ -224,9 +224,9 @@ type_stmt : simplevar_decl ';' | interface_impl | enum -simplevar_decl : TOK_IDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } -simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } -simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' logicexpr { $$ = new Scalar($id, $logicexpr); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } bind : TOK_BIND ident_or_xident[id] TOK_TO ident_or_xident[to] bind_scope[scope] ';' { //extern map>> injections; @@ -297,11 +297,10 @@ stmt : ident_or_xident '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Lo | whileblock | interface_impl -complexvar_set : TOK_XIDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } -complexvar_set : TOK_XIDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } -complexvar_set : TOK_XIDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } +complexvar_set : TOK_XIDENTIFIER[id] '=' logicexpr { $$ = new Scalar($id, $logicexpr); $$->setLocation(@id); } +complexvar_set : TOK_XIDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } +complexvar_set : TOK_XIDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } -returnblock : TOK_RETURN expr { $$ = new Return($2); } returnblock : TOK_RETURN logicexpr { $$ = new Return($2); } returnblock : TOK_RETURN { $$ = new Return(); } @@ -367,8 +366,12 @@ logicfactor : '(' logicexpr ')' { $$ = $2; } | expr '>''=' expr { $$ = new CmpOp($1, GE_OP, $4); } | expr '<' expr { $$ = new CmpOp($1, LT_OP, $3); } | expr '>' expr { $$ = new CmpOp($1, GT_OP, $3); } + | expr %expect 1 + | logicunary ; +logicunary : '!' logicfactor { $$ = new BinaryOp(new Int1(1), '-', $2); } + /* * Arithmetic */ @@ -392,7 +395,7 @@ term2 : term2 '&' factor { $$ = new BinaryOp($1, '&', $3); } | factor { $$ = $1; } ; -factor : '(' expr ')' { $$ = $2; } +factor : '(' expr ')' { $$ = $2; } | ident_or_xident { $$ = new Load($1); } | TOK_TRUE { $$ = new Int1(1); } | TOK_FALSE { $$ = new Int1(0); } diff --git a/src/Return.cpp b/src/Return.cpp index 9078536..abd21af 100644 --- a/src/Return.cpp +++ b/src/Return.cpp @@ -10,6 +10,12 @@ Value *Return::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc if (node) { ret = node->generate(func, block, allocblock); if (ret) { + DataType sdt = node->getDataType(); + if (buildTypes->isComplex(sdt)) { + // defer the pointer before returning + Type *ty = buildTypes->llvmType(sdt); + ret = Builder->CreateLoad(ty, ret, false, "deref"); + } Type *retty = func->getLLVMFunction()->getReturnType(); ret = Coercion::Convert(ret, retty, block, this); } diff --git a/test/general/bitstruct.rob b/test/general/bitstruct.rob index b994424..254c96e 100644 --- a/test/general/bitstruct.rob +++ b/test/general/bitstruct.rob @@ -26,7 +26,7 @@ int16 main() { set_struct_kfield(x); - if x.c == true and x.k == false and x.j == true { + if x.c and !x.k and x.j { return 0; } else { return 1; diff --git a/test/general/bool.rob b/test/general/bool.rob new file mode 100644 index 0000000..92c27f0 --- /dev/null +++ b/test/general/bool.rob @@ -0,0 +1,20 @@ + +int16 main() { + a = 1 > 7; + b = 2 <= 3; + c = true; + d = false; + e = a or b; + f = a and c; + g = a or b and c; + + if !(2+1 == 3) or !(2+2 == 4) or d { + return 1; + } + + if a or !b or !c or d or !e or f or !g { + return 1; + } + + return 0; +} diff --git a/test/general/itoa.rob b/test/general/itoa.rob index 98c5e0d..c7b09c3 100644 --- a/test/general/itoa.rob +++ b/test/general/itoa.rob @@ -1,9 +1,7 @@ -chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; +const chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; -result = {0:18}; - -void itoa(int16 value, int8 base) { +void itoa(int16 value, int8 base, char[] result) { if base < 2 or base > 16 { result[0] = 0; return; @@ -78,7 +76,7 @@ base16 = { {'7', 'f', 'f', 'f', 0 , 0} }; -bool check10(int8 id) { +bool check10(int8 id, char[] result) { ret = true; i = 0; while result[i] != 0 and ret == true { @@ -90,7 +88,7 @@ bool check10(int8 id) { return ret; } -bool check16(int8 id) { +bool check16(int8 id, char[] result) { ret = true; i = 0; while result[i] != 0 and ret == true { @@ -103,14 +101,15 @@ bool check16(int8 id) { } int16 main() { + result = {0:18}; ret = true; i = 0; while i < numbers.size and ret == true { - itoa(numbers[i], 10); - ret = check10(i); + itoa(numbers[i], 10, result); + ret = check10(i, result); if ret == true { - itoa(numbers[i], 16); - ret = check16(i); + itoa(numbers[i], 16, result); + ret = check16(i, result); } i++; } diff --git a/test/general/return_a_type.rob b/test/general/return_a_type.rob new file mode 100644 index 0000000..5c9d406 --- /dev/null +++ b/test/general/return_a_type.rob @@ -0,0 +1,20 @@ + +type ta { + x = 0; + y = 0; +} + +ta get_ta(int8 x, int8 y) { + result = ta(); + result.x = x; + result.y = y; + return result; +} + +int8 main() { + result = get_ta(15, 20); + if result.x == 15 and result.y == 20 { + return 0; + } + return 1; +} \ No newline at end of file From 974e6a130f8a2cfb3c4fdf4241442d45843df104 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 25 May 2024 19:37:45 -0300 Subject: [PATCH 044/117] Extend array support in the language and some fixes. --- src/Array.h | 11 +++-- src/BuildTypes.cpp | 7 +++ src/BuildTypes.h | 2 + src/DebugInfo.cpp | 3 ++ src/Load.cpp | 3 +- src/LoadArray.cpp | 34 +++++++++++-- src/MemCopy.cpp | 51 ++++++++++++++----- src/MemCopy.h | 4 ++ src/Node.h | 1 + src/Scalar.cpp | 4 +- src/UpdateArray.cpp | 95 +++++++++++++++++++++--------------- test/general/byref-array.rob | 45 +++++++++++++++-- 12 files changed, 192 insertions(+), 68 deletions(-) diff --git a/src/Array.h b/src/Array.h index 8d04a49..6f38685 100644 --- a/src/Array.h +++ b/src/Array.h @@ -11,7 +11,7 @@ class LinearDataStructure: public Variable { protected: DataType element_dt = BuildTypes::undefinedType; public: - LinearDataStructure(const char *n): Variable(n) {} + LinearDataStructure(const string &n): Variable(n) {} virtual Node *getElementIndex(Node *p1, Node *p2) = 0; virtual DataType getElementDt() { return element_dt; @@ -20,11 +20,16 @@ class LinearDataStructure: public Variable { class ParamArray: public LinearDataStructure { public: - ParamArray(const char *n, string element_dt_name, location_t loc): LinearDataStructure(n) { + ParamArray(const string& n, string element_dt_name, location_t loc): LinearDataStructure(n) { this->element_dt = buildTypes->getType(element_dt_name, true); this->dt = buildTypes->getArrayType(element_dt_name, loc, true); } - + + ParamArray(const string &n, DataType dt): LinearDataStructure(n) { + this->dt = dt; + this->element_dt = buildTypes->getArrayElementType(dt); + } + virtual Node *getElementIndex(Node *p1, Node *p2) override { return p1; } diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 81e9625..c155c44 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -79,6 +79,13 @@ DataType BuildTypes::getArrayType(const string& elementName, SourceLocation n, b return undefinedType; } +DataType BuildTypes::getArrayElementType(DataType arrayDt) { + assert(isArray(arrayDt) && "arrayDt must be an array."); + string elementName = name(arrayDt); + elementName = elementName.substr(0, elementName.length()-2); + return getType(elementName); +} + DataType BuildTypes::getType(const string& name, bool createUndefined) { auto ut = namedTypes.find(name); if (ut == namedTypes.end()) { diff --git a/src/BuildTypes.h b/src/BuildTypes.h index f59932c..b972017 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -78,6 +78,8 @@ class BuildTypes { DataType getArrayType(const string& elementName, SourceLocation n, bool createUndefined = false); + DataType getArrayElementType(DataType arrayDt); + const char *name(DataType tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].name.c_str(); diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index f4820e4..1ad4cf8 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -59,6 +59,9 @@ DIExpression *DebugInfo::getFixedOffsetExpression() { void DebugInfo::declareVar(Node *n, Value *alloc, BasicBlock *allocblock) { DataType dt = n->getDataType(); llvm::DIType *dty = buildTypes->diType(dt); + if (n->isPointerToPointer()) + dty = buildTypes->diPointerType(dt); + if (n->hasQualifier(qvolatile)) { dty = DBuilder->createQualifiedType(dwarf::DW_TAG_volatile_type, dty); } diff --git a/src/Load.cpp b/src/Load.cpp index e440958..7f122a5 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -31,6 +31,7 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl } dt = isymbol->getDataType(); + symbols = symbol->getSymbols(); if (block == NULL && (allocblock == NULL || allocblock == global_alloc)) { // trying to load a variable to initialize a global one. @@ -89,7 +90,7 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl if (buildTypes->isComplex(sdt) || buildTypes->isArray(sdt)) { if (symbol->isPointerToPointer()) { Type *ty = buildTypes->llvmType(sdt)->getPointerTo(); - return Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); + alloc = Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); } if (leftValue) leftValue->setPointerToPointer(true); diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index 5c0edf8..6c22491 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -1,6 +1,7 @@ #include "LoadArray.h" #include "Array.h" +#include "BuildTypes.h" #include "FunctionImpl.h" LoadArray::LoadArray(const char *i, Node *pos): ident(i), position(pos) { @@ -9,18 +10,35 @@ LoadArray::LoadArray(const char *i, Node *pos): ident(i), position(pos) { DataType LoadArray::getDataType() { if (dt == BuildTypes::undefinedType) { - if (!rsym) + Node *symbol = ident.getSymbol(getScope()); + + // temporary fallback while matrix is not modified/fixed + if (!symbol || !buildTypes->isArray(symbol->getDataType())) { rsym = dynamic_cast(ident.getSymbol(getScope())); - if (rsym) dt = rsym->getElementDt(); + } else + dt = buildTypes->getArrayElementType(symbol->getDataType()); } return dt; } Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - if (!rsym) - rsym = dynamic_cast(ident.getSymbol(getScope())); + bool localrsym = false; + + if (!rsym) { + Node *symbol = ident.getSymbol(getScope()); + rsym = dynamic_cast(symbol); + if (!rsym) { + // when the array has been assigned to another var + if (buildTypes->isArray(symbol->getDataType())) { + localrsym = true; + rsym = new ParamArray(ident.getFullName(), symbol->getDataType()); + rsym->setAlloca(symbol->getLLVMValue(NULL)); + rsym->setPointerToPointer(symbol->isPointerToPointer()); + } + } + } if (rsym == NULL) { yyerrorcpp("Variable " + ident.getFullName() + " not defined or not an array/matrix.", this); return NULL; @@ -46,8 +64,10 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al alloc = rsym->getLLVMValue(func); } - if (!alloc) + if (!alloc) { + yyerrorcpp("Missing the array reference to gep.", this); return NULL; + } Node *indn = getElementIndex(rsym); Value *indice = indn->generate(func, block, allocblock); @@ -66,5 +86,9 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al Value *ptr = Builder->CreateGEP(rsym->getLLVMType(), alloc, ArrayRef(indexList), "gep"); Type *elemType = buildTypes->llvmType(rsym->getElementDt()); LoadInst *ret = Builder->CreateLoad(elemType, ptr, ident.getFullName()); + + if (localrsym) + delete rsym; + return ret; } diff --git a/src/MemCopy.cpp b/src/MemCopy.cpp index 820c80f..caabf05 100644 --- a/src/MemCopy.cpp +++ b/src/MemCopy.cpp @@ -13,21 +13,54 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); + // Get src value Value *exprv = expr->generate(func, block, allocblock); - dt = expr->getDataType(); Type *exprvty = exprv->getType(); + dt = expr->getDataType(); + + // Compute the size of src + const DataLayout &dl = mainmodule->getDataLayout(); + Value *size; + Value *nelem = NULL; + + if (buildTypes->isArray(dt)) { + // Load the array size and compute the bytes to copy + DataType eldt = buildTypes->getArrayElementType(dt); + TypeSize eltsize = dl.getTypeAllocSize(buildTypes->llvmType(eldt)); + ConstantInt *elbytes = ConstantInt::get(Type::getInt32Ty(global_context), eltsize); + Load ld("size"); + ld.setScope(expr); + nelem = ld.generate(func, allocblock, allocblock); + Builder->SetInsertPoint(allocblock); + size = Builder->CreateBinOp(Instruction::Mul, elbytes, nelem, "arrsize"); + } else { + TypeSize ts = dl.getTypeAllocSize(buildTypes->llvmType(dt)); + size = ConstantInt::get(Type::getInt32Ty(global_context), ts); + } + // Prepare dest memory Type *leftvty; - Builder->SetInsertPoint(block); Value *dest = leftValue->getLLVMValue(func); if (dest) { leftvty = dest->getType(); + //FIXME: must check the alloc size for array and matrix } else { - leftvty = buildTypes->llvmType(dt); Builder->SetInsertPoint(allocblock); - dest = Builder->CreateAlloca(leftvty, dataAddrSpace, nullptr, leftValue->getName()); + if (buildTypes->isArray(dt)) { + DataType eldt = buildTypes->getArrayElementType(dt); + dest = Builder->CreateAlloca(buildTypes->llvmType(eldt), dataAddrSpace, nelem, leftValue->getName()); + leftvty = buildTypes->llvmType(dt)->getPointerTo(); + } else { + leftvty = buildTypes->llvmType(dt); + dest = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, nelem, leftValue->getName()); + } + leftValue->setAlloca(dest); leftValue->setDataType(dt); + + //FIXME: only work for constant symbols + leftValue->symbols = expr->getSymbols(); + if (debug_info) RobDbgInfo.declareVar(this, dest, allocblock); } @@ -38,15 +71,7 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo return NULL; } - //Builder->SetInsertPoint(allocblock); - //Value *srcalloc = Builder->CreateAlloca(exprvty, dataAddrSpace, nullptr, "src"); - - //Builder->SetInsertPoint(block); - //Value *src = Builder->CreateStore(exprv, srcalloc); - - const DataLayout &dl = mainmodule->getDataLayout(); - Value *size = ConstantInt::get(Type::getInt32Ty(global_context), dl.getTypeAllocSize(leftvty)); - + Builder->SetInsertPoint(block); Builder->CreateMemCpy(dest, Align(1), exprv, Align(1), size); return NULL; diff --git a/src/MemCopy.h b/src/MemCopy.h index 1003d1b..b30d6f2 100644 --- a/src/MemCopy.h +++ b/src/MemCopy.h @@ -18,4 +18,8 @@ class MemCopy: public Node { virtual void setLeftValue(Variable *symbol) override; virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual const string getName() const override { + return leftValue->getName(); + } }; diff --git a/src/Node.h b/src/Node.h index a73c5f8..61fc916 100644 --- a/src/Node.h +++ b/src/Node.h @@ -96,6 +96,7 @@ class Node : public SourceLocation { friend class UserType; friend class Program; + friend class MemCopy; }; class NamedNode: public Node { diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 57d5f49..b8648c7 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -94,7 +94,9 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc alloc = temp; Builder->SetInsertPoint(block); ret = Builder->CreateStore(exprv, alloc, symbol->hasQualifier(qvolatile)); - + + symbols = expr->getSymbols(); + if (debug_info) RobDbgInfo.declareVar(this, alloc, allocblock); } diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index e58c85d..f0ae4a3 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -11,52 +11,67 @@ UpdateArray::UpdateArray(const char *i, Node *pos, Node *expr): ident(i), positi } Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - Node *rsym = ident.getSymbol(getScope()); - if (rsym == NULL) { - return NULL; - } - LinearDataStructure *arr = dynamic_cast(rsym); - Value *sym = rsym->getLLVMValue(func); - - // sym type can be GlobalVariable or AllocInst - Type *ty = NULL; - if (auto *aux = dyn_cast(sym)) - ty = aux->getAllocatedType(); - else if (auto *aux = dyn_cast(sym)) - ty = aux->getValueType(); - - ArrayType *arrayTy = NULL; - if (buildTypes->isArray(rsym->getDataType())) { - arrayTy = (ArrayType*)buildTypes->llvmType(rsym->getDataType()); - } - else { - yyerrorcpp("Symbol " + ident.getFullName() + " is not an array.", this); - return NULL; - } - Node *indn = getElementIndex(arr); - Value *indice = indn->generate(func, block, allocblock); - if (!indice || !indice->getType()->isIntegerTy()){ - yyerrorcpp("Index to update " + ident.getFullName() + " elements must be of type integer.", this); - return NULL; + bool localarr = false; + Node *symbol = ident.getSymbol(getScope()); + LinearDataStructure *arr = dynamic_cast(symbol); + if (!arr) { + // when the array has been assigned to another var + if (buildTypes->isArray(symbol->getDataType())) { + localarr = true; + arr = new ParamArray(ident.getFullName(), symbol->getDataType()); + arr->setAlloca(symbol->getLLVMValue(NULL)); + arr->setPointerToPointer(symbol->isPointerToPointer()); } + } - Value *val = expr->generate(func, block, allocblock); - val = Coercion::Convert(val, arrayTy->getArrayElementType(), block, this); + if (symbol == NULL) + return NULL; - RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(block); + Value *sym = symbol->getLLVMValue(func); - if (rsym->isPointerToPointer()) { - Type *ty = buildTypes->llvmType(rsym->getDataType())->getPointerTo(); - sym = Builder->CreateLoad(ty, sym, rsym->hasQualifier(qvolatile), "deref"); - } + // sym type can be GlobalVariable or AllocInst + Type *ty = NULL; + if (auto *aux = dyn_cast(sym)) + ty = aux->getAllocatedType(); + else if (auto *aux = dyn_cast(sym)) + ty = aux->getValueType(); + + ArrayType *arrayTy = NULL; + if (buildTypes->isArray(symbol->getDataType())) { + arrayTy = (ArrayType*)buildTypes->llvmType(symbol->getDataType()); + } + else { + yyerrorcpp("Symbol " + ident.getFullName() + " is not an array.", this); + return NULL; + } + + Node *indn = getElementIndex(arr); + Value *indice = indn->generate(func, block, allocblock); + if (!indice || !indice->getType()->isIntegerTy()){ + yyerrorcpp("Index to update " + ident.getFullName() + " elements must be of type integer.", this); + return NULL; + } + + Value *val = expr->generate(func, block, allocblock); + val = Coercion::Convert(val, arrayTy->getArrayElementType(), block, this); + + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + if (symbol->isPointerToPointer()) { + Type *ty = buildTypes->llvmType(symbol->getDataType())->getPointerTo(); + sym = Builder->CreateLoad(ty, sym, symbol->hasQualifier(qvolatile), "deref"); + } - Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); - Value *indexList[2] = {zero, indice}; - Value *ptr = Builder->CreateGEP(arrayTy, sym, ArrayRef(indexList), "gep"); - StoreInst *store = Builder->CreateStore(val, ptr, false); + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); + Value *indexList[2] = {zero, indice}; + Value *ptr = Builder->CreateGEP(arrayTy, sym, ArrayRef(indexList), "gep"); + StoreInst *store = Builder->CreateStore(val, ptr, false); - return store; + if (localarr) + delete arr; + + return store; } diff --git a/test/general/byref-array.rob b/test/general/byref-array.rob index dcc8c67..ce122f5 100644 --- a/test/general/byref-array.rob +++ b/test/general/byref-array.rob @@ -3,15 +3,50 @@ int32 sum_array(int16[] a); int8 main() { x = {int16(0), 1, 2, 3, 4, 5, 6, 7, 8, 9}; - if sum_array(x) == 45 + 1 + 10 { - return 0; - } else { - return 1; + + // y is a reference to x + y = x; + i = 0; + while i < y.size { + if y[i] != x[i] { + return 1; + } + i++; + } + + // w is a reference to y (same as x) + w = y; + i = 0; + while i < w.size { + if w[i] != x[i] { + return 1; + } + i++; } + + // z is a copy of y + z = copy(y); + i = 0; + while i < z.size { + z[i] = z[i] + 1; + if z[i] != x[i] + 1 { + return i; + } + i++; + } + + zt = sum_array(w); + if zt != 45 + 18 + 10 { + return zt; + } + + return 0; } int32 pass_array_pointer(int16[] b) { - result = b[1] + b.size; + c = b; + d = copy(b); + result = c[9] + d[9] + b.size; return result; } From df848efcddb7deb046ec5d8ae569d80aaf117630 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 26 May 2024 19:48:32 -0300 Subject: [PATCH 045/117] Refactoring array operations: simplify and remove duplicated code. --- Makefile => Makefile.old | 0 src/Array.cpp | 41 +++++++++++++++++++----- src/Array.h | 29 ++++++++++------- src/BuildTypes.cpp | 2 -- src/BuildTypes.h | 2 +- src/LoadArray.cpp | 67 ++++++++++++++++++---------------------- src/LoadArray.h | 29 ++++++++++++----- src/LoadMatrix.h | 25 ++++++++++++--- src/Matrix.cpp | 46 ++++++++------------------- src/Matrix.h | 19 +++++++++--- src/UpdateArray.cpp | 39 ++++++----------------- src/UpdateArray.h | 13 ++------ src/UpdateMatrix.h | 10 +++--- src/Visitor.h | 6 ++-- 14 files changed, 170 insertions(+), 158 deletions(-) rename Makefile => Makefile.old (100%) diff --git a/Makefile b/Makefile.old similarity index 100% rename from Makefile rename to Makefile.old diff --git a/src/Array.cpp b/src/Array.cpp index f077ae9..e2d42f9 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -5,11 +5,17 @@ #include "Visitor.h" #include "FunctionImpl.h" #include "NamedConst.h" +#include "BinaryOp.h" -Array::Array(const char *n, ArrayElements *aes) : LinearDataStructure(n), elements(aes) { +Array::Array(const string& n, ArrayElements *aes) : Variable(n), elements(aes) { NamedConst *nc = new NamedConst("size", getNodeForIntConst(aes->getArraySize())); addChild(nc); - dt = tarray; +} + +DataType Array::getDataType() { + if (arrayType == NULL) + createDataType(); + return dt; } void Array::createDataType() { @@ -79,7 +85,7 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb alloc = gv; if (debug_info) { - auto di_ptr = DBuilder->createPointerType(buildTypes->diType(getElementDt()), + auto di_ptr = DBuilder->createPointerType(buildTypes->diType(element_dt), buildTypes->bitWidth(currentTarget().pointerType)); auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", funit, this->getLineNo(), di_ptr, false); @@ -124,14 +130,33 @@ Type* Array::getLLVMType() { return arrayType; } -Node *Array::getElementIndex(Node *p1, Node *p2) { - if (p1->isConstExpr()) { +Node *Array::getElementIndex(Node *p1, Node *p2, const string& name, int p1size, int p2size, + Node *columnNumber) { + + // if constant, validate indexes + if (p1->isConstExpr() && p1size != -1) { Value *p1v = p1->generate(NULL, NULL, NULL); Constant *c = dyn_cast(p1v); int64_t v = c->getUniqueInteger().getZExtValue(); - if (v >= size) { - yyerrorcpp(string_format("Array %s index (%d) out of bounds.", name.c_str(), v), p1); + if (v >= p1size) { + yyerrorcpp(string_format("Index (%d) for %s is out of bounds.", + v, name.c_str()), p1); + } + } + + if (p2 && p2->isConstExpr() && p2size != -1) { + Value *p1v = p2->generate(NULL, NULL, NULL); + Constant *c = dyn_cast(p1v); + int64_t v = c->getUniqueInteger().getZExtValue(); + if (v >= p2size) { + yyerrorcpp(string_format("Index (%d) for %s is out of bounds.", + v, name.c_str()), p2); } } - return p1; + + if (!p2) // is an array + return p1; + + // Generate index of element for matrix + return new BinaryOp(new BinaryOp(p1, '*', columnNumber), '+', p2); } diff --git a/src/Array.h b/src/Array.h index 6f38685..a797a0e 100644 --- a/src/Array.h +++ b/src/Array.h @@ -7,7 +7,7 @@ class ArrayElements; -class LinearDataStructure: public Variable { +/*class LinearDataStructure: public Variable { protected: DataType element_dt = BuildTypes::undefinedType; public: @@ -16,38 +16,38 @@ class LinearDataStructure: public Variable { virtual DataType getElementDt() { return element_dt; } -}; +};*/ -class ParamArray: public LinearDataStructure { +class ParamArray: public Variable { +protected: + DataType element_dt = BuildTypes::undefinedType; public: - ParamArray(const string& n, string element_dt_name, location_t loc): LinearDataStructure(n) { + ParamArray(const string& n, string element_dt_name, location_t loc): Variable(n) { this->element_dt = buildTypes->getType(element_dt_name, true); this->dt = buildTypes->getArrayType(element_dt_name, loc, true); } - ParamArray(const string &n, DataType dt): LinearDataStructure(n) { + ParamArray(const string &n, DataType dt): Variable(n) { this->dt = dt; this->element_dt = buildTypes->getArrayElementType(dt); } - - virtual Node *getElementIndex(Node *p1, Node *p2) override { - return p1; - } }; -class Array: public LinearDataStructure { +class Array: public Variable { private: unsigned int size; + DataType element_dt = BuildTypes::undefinedType; ArrayElements *elements; ArrayType *arrayType = NULL; void createDataType(); public: - Array(const char *n, ArrayElements *aes); + Array(const string& n, ArrayElements *aes); virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual Node *getElementIndex(Node *p1, Node *p2) override; + static Node *getElementIndex(Node *p1, Node *p2, const string& name, + int p1size = -1, int p2size = -1, Node *columnNumber = NULL); std::vector getElements() { return elements->getElements(); @@ -57,4 +57,9 @@ class Array: public LinearDataStructure { virtual Type *getLLVMType() override; + DataType getDataType() override; + + int getSize() const { + return size; + } }; diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index c155c44..aadbb43 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -29,8 +29,6 @@ BuildTypes::BuildTypes(DataType targetPointerType) { tinfo[tldouble] = {"long double", 128, Type::getFP128Ty(global_context), dwarf::DW_ATE_float}; unsigned pts = tinfo[targetPointerType].bitWidth; - Type *pty = tinfo[targetPointerType].llvmType; - tinfo[tarray] = {"array", pts, pty, dwarf::DW_ATE_address}; const DataLayout &dl = mainmodule->getDataLayout(); for(int t = 0; t < __bdt_last; t++) { diff --git a/src/BuildTypes.h b/src/BuildTypes.h index b972017..192aaaf 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -9,7 +9,7 @@ typedef int DataType; enum BasicDataType {tvoid, tbool, tchar, tint2, tint3, tint4, tint5, tint6, tint7, tint8, tint16, tint32, tint64, tint8u, tint16u, tint32u, tint64u, - tfloat, tdouble, tldouble, tarray, + tfloat, tdouble, tldouble, /* new types here! */ __bdt_last}; diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index 6c22491..35c0661 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -1,22 +1,17 @@ -#include "LoadArray.h" #include "Array.h" +#include "LoadArray.h" #include "BuildTypes.h" #include "FunctionImpl.h" -LoadArray::LoadArray(const char *i, Node *pos): ident(i), position(pos) { +LoadArray::LoadArray(const string &i, Node *pos): BaseArrayOper(i, pos, NULL) { addChild(pos); } DataType LoadArray::getDataType() { if (dt == BuildTypes::undefinedType) { Node *symbol = ident.getSymbol(getScope()); - - // temporary fallback while matrix is not modified/fixed - if (!symbol || !buildTypes->isArray(symbol->getDataType())) { - rsym = dynamic_cast(ident.getSymbol(getScope())); - dt = rsym->getElementDt(); - } else + if (symbol && buildTypes->isArray(symbol->getDataType())) dt = buildTypes->getArrayElementType(symbol->getDataType()); } return dt; @@ -24,23 +19,12 @@ DataType LoadArray::getDataType() { Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - bool localrsym = false; + Node *symbol = ident.getSymbol(getScope()); + if (!symbol) + return NULL; - if (!rsym) { - Node *symbol = ident.getSymbol(getScope()); - rsym = dynamic_cast(symbol); - if (!rsym) { - // when the array has been assigned to another var - if (buildTypes->isArray(symbol->getDataType())) { - localrsym = true; - rsym = new ParamArray(ident.getFullName(), symbol->getDataType()); - rsym->setAlloca(symbol->getLLVMValue(NULL)); - rsym->setPointerToPointer(symbol->isPointerToPointer()); - } - } - } - if (rsym == NULL) { - yyerrorcpp("Variable " + ident.getFullName() + " not defined or not an array/matrix.", this); + if (!buildTypes->isArray(symbol->getDataType())) { + yyerrorcpp("Variable " + ident.getFullName() + " is not an array or matrix.", this); return NULL; } @@ -51,44 +35,53 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al if (ident.isComplex()) { Identifier istem = ident.getStem(); Node *stem = istem.getSymbol(getScope()); - alloc = rsym->getLLVMValue(stem); + alloc = symbol->getLLVMValue(stem); if (stem->hasQualifier(qvolatile)) - rsym->setQualifier(qvolatile); + symbol->setQualifier(qvolatile); // TODO: When accessing a.x.func(), need to load a and gep x //Load loadstem(ident.getStem()); //loadstem.setParent(this->parent); //stem = loadstem.generate(func, block, allocblock); } else { - alloc = rsym->getLLVMValue(func); + alloc = symbol->getLLVMValue(func); } if (!alloc) { + // this is a compiler error yyerrorcpp("Missing the array reference to gep.", this); return NULL; } - Node *indn = getElementIndex(rsym); + Node *indn = getElementIndex(symbol); Value *indice = indn->generate(func, block, allocblock); - if (!indice || !indice->getType()->isIntegerTy()){ + if (!indice || !indice->getType()->isIntegerTy()) { //TODO: replace by isIntegerDataType yyerrorcpp("Index to access " + ident.getFullName() + " elements must be of type integer.", this); return NULL; } - if (rsym->isPointerToPointer()) { - Type *ty = buildTypes->llvmType(rsym->getDataType())->getPointerTo(); - alloc = Builder->CreateLoad(ty, alloc, rsym->hasQualifier(qvolatile), "deref"); + if (symbol->isPointerToPointer()) { + Type *ty = buildTypes->llvmType(symbol->getDataType())->getPointerTo(); + alloc = Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); } Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); Value *indexList[2] = {zero, indice}; - Value *ptr = Builder->CreateGEP(rsym->getLLVMType(), alloc, ArrayRef(indexList), "gep"); - Type *elemType = buildTypes->llvmType(rsym->getElementDt()); + Value *ptr = Builder->CreateGEP(symbol->getLLVMType(), alloc, ArrayRef(indexList), "gep"); + DataType elementDt = buildTypes->getArrayElementType(symbol->getDataType()); + Type *elemType = buildTypes->llvmType(elementDt); LoadInst *ret = Builder->CreateLoad(elemType, ptr, ident.getFullName()); - if (localrsym) - delete rsym; - return ret; } + +Node* BaseArrayOper::getElementIndex(const Node *symbol) { + + // Get element + int rows = -1; + if (const Array *arr = dynamic_cast(symbol)) + rows = arr->getSize(); + + return Array::getElementIndex(position, NULL, ident.getFullName(), rows); +} diff --git a/src/LoadArray.h b/src/LoadArray.h index 63ef826..bfba866 100644 --- a/src/LoadArray.h +++ b/src/LoadArray.h @@ -2,22 +2,37 @@ #pragma once #include "Node.h" -#include "Array.h" #include "Identifier.h" -class LoadArray: public Node { +class BaseArrayOper: public Node { protected: Identifier ident; Node *position; - LinearDataStructure *rsym = NULL; + Node *position2; public: - LoadArray(const char *i, Node *pos); + BaseArrayOper(const string& i, Node *pos, Node *pos2): ident(i), position(pos), + position2(pos2) {} + + virtual Node* getElementIndex(const Node *symbol); - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + Node *getPosition() { + return position; + } + + Node *getPosition2() { + return position2; + } - virtual Node *getElementIndex(LinearDataStructure *arr) { - return arr->getElementIndex(position, NULL); + const string getIdent() { + return ident.getFullName(); } +}; + +class LoadArray: public BaseArrayOper { +public: + LoadArray(const string& i, Node *pos); + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; virtual DataType getDataType() override; }; diff --git a/src/LoadMatrix.h b/src/LoadMatrix.h index 3c83911..3d2f435 100644 --- a/src/LoadMatrix.h +++ b/src/LoadMatrix.h @@ -1,20 +1,35 @@ #pragma once #include "Node.h" +#include "Matrix.h" #include "Array.h" #include "LoadArray.h" class LoadMatrix: public LoadArray { -private: - Node *position2; public: - LoadMatrix(const char *i, Node *p1, Node *p2): LoadArray(i, p1) { + LoadMatrix(const string &i, Node *p1, Node *p2): LoadArray(i, p1) { this->position2 = p2; addChild(p2); } - virtual Node *getElementIndex(LinearDataStructure *arr) override { - return arr->getElementIndex(position, position2); + virtual Node* getElementIndex(const Node *symbol) override { + return getElementIndexMatrix(this, symbol); } + static Node* getElementIndexMatrix(BaseArrayOper *matrix, const Node *symbol) { + // Get element + int rows = -1; + int cols = -1; + Node *mcols = NULL; + if (const Matrix *mx = dynamic_cast(symbol)) { + rows = mx->getRows(); + cols = mx->getCols(); + mcols = getNodeForIntConst(cols); + } else if (const ParamMatrix *pmx = dynamic_cast(symbol)) { + mcols = pmx->getCols(); + } + + return Array::getElementIndex(matrix->getPosition(), matrix->getPosition2(), + matrix->getIdent(), rows, cols, mcols); + } }; diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 218ab30..882b29d 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -1,44 +1,16 @@ #include "Matrix.h" #include "Coercion.h" #include "Array.h" -#include "BinaryOp.h" #include "Visitor.h" #include "BackLLVM.h" #include "FunctionImpl.h" #include "NamedConst.h" -Matrix::Matrix(const char *n, MatrixElements *me) : LinearDataStructure(n), melements(me) { +Matrix::Matrix(const char *n, MatrixElements *me) : Variable(n), melements(me) { NamedConst *rows = new NamedConst("rows", getNodeForIntConst(me->getRowCount())); NamedConst *cols = new NamedConst("cols", getNodeForIntConst(me->getColumnCount())); addChild(rows); addChild(cols); - dt = tarray; //FIXME -} - -Node* Matrix::getElementIndex(Node *p1, Node *p2) { - - // if constants, validate indexes - if (p1->isConstExpr()) { - Value *p1v = p1->generate(NULL, NULL, NULL); - Constant *c = dyn_cast(p1v); - int64_t v = c->getUniqueInteger().getZExtValue(); - if (v >= rows) { - yyerrorcpp(string_format("Matrix %s row index (%d) out of bounds.", name.c_str(), v), p1); - } - } - - if (p2->isConstExpr()) { - Value *p1v = p2->generate(NULL, NULL, NULL); - Constant *c = dyn_cast(p1v); - int64_t v = c->getUniqueInteger().getZExtValue(); - if (v >= cols) { - yyerrorcpp(string_format("Matrix %s col index (%d) out of bounds.", name.c_str(), v), p2); - } - } - - //Generate index of element - Node *mcols = getNodeForIntConst(melements->getColumnCount()); - return new BinaryOp(new BinaryOp(p1, '*', mcols), '+', p2); } Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { @@ -81,8 +53,7 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc auto sp = RobDbgInfo.currScope(); auto funit = RobDbgInfo.currFile(); - //Allocate matrix as a vector. - //Allocate array. + //Allocate matrix as an array. if (allocblock == global_alloc) { // when alloc is global vector constantValues; constantValues.reserve(elementValues.size()); @@ -97,7 +68,7 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc alloc = gv; if (debug_info) { - auto di_ptr = DBuilder->createPointerType(buildTypes->diType(getElementDt()), + auto di_ptr = DBuilder->createPointerType(buildTypes->diType(element_dt), buildTypes->bitWidth(currentTarget().pointerType)); auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", funit, this->getLineNo(), di_ptr, false); @@ -133,15 +104,24 @@ void Matrix::accept(Visitor& v) { v.visit(*this); } + +DataType Matrix::getDataType() { + if (matrixType == NULL) + createDataType(); + return dt; +} + void Matrix::createDataType() { if (matrixType != NULL) return; //Get Type of elements in Vector of Elements, and define as I. element_dt = melements->getMatrixType(); + dt = buildTypes->getArrayType(buildTypes->name(element_dt), + *this->getLoct(), true); Type* I = buildTypes->llvmType(element_dt); - // The matrix size + // The matrix type and size rows = melements->getRowCount(); cols = melements->getColumnCount(); matrixType = ArrayType::get(I, rows * cols); diff --git a/src/Matrix.h b/src/Matrix.h index c88e480..621f1bf 100644 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -2,12 +2,13 @@ #pragma once #include "MatrixElements.h" -#include "Array.h" +#include "Variable.h" -class Matrix: public LinearDataStructure { +class Matrix: public Variable { private: MatrixElements *melements; ArrayType *matrixType = NULL; + DataType element_dt; void createDataType(); unsigned int rows = 0; unsigned int cols = 0; @@ -15,9 +16,7 @@ class Matrix: public LinearDataStructure { public: Matrix(const char *n, MatrixElements *me); - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - - virtual Node *getElementIndex(Node *p1, Node *p2) override; + virtual Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; std::vector const& getElements() { return melements->getElements(); @@ -26,4 +25,14 @@ class Matrix: public LinearDataStructure { void accept(Visitor& v) override; virtual Type *getLLVMType() override; + + DataType getDataType() override; + + int getRows() const { + return rows; + } + + int getCols() const { + return cols; + } }; diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index f0ae4a3..da715c8 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -1,32 +1,25 @@ #include "UpdateArray.h" #include "Coercion.h" -#include "Array.h" #include "FunctionImpl.h" #include "HeaderGlobals.h" -UpdateArray::UpdateArray(const char *i, Node *pos, Node *expr): ident(i), position(pos), expr(expr) { +UpdateArray::UpdateArray(const string &i, Node *pos, Node *expr): + BaseArrayOper(i, pos, NULL), expr(expr) { addChild(pos); addChild(expr); } Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - - bool localarr = false; + Node *symbol = ident.getSymbol(getScope()); - LinearDataStructure *arr = dynamic_cast(symbol); - if (!arr) { - // when the array has been assigned to another var - if (buildTypes->isArray(symbol->getDataType())) { - localarr = true; - arr = new ParamArray(ident.getFullName(), symbol->getDataType()); - arr->setAlloca(symbol->getLLVMValue(NULL)); - arr->setPointerToPointer(symbol->isPointerToPointer()); - } - } + if (!symbol) + return NULL; - if (symbol == NULL) + if (!buildTypes->isArray(symbol->getDataType())) { + yyerrorcpp("Symbol " + ident.getFullName() + " is not an array or matrix.", this); return NULL; + } Value *sym = symbol->getLLVMValue(func); @@ -37,16 +30,7 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * else if (auto *aux = dyn_cast(sym)) ty = aux->getValueType(); - ArrayType *arrayTy = NULL; - if (buildTypes->isArray(symbol->getDataType())) { - arrayTy = (ArrayType*)buildTypes->llvmType(symbol->getDataType()); - } - else { - yyerrorcpp("Symbol " + ident.getFullName() + " is not an array.", this); - return NULL; - } - - Node *indn = getElementIndex(arr); + Node *indn = getElementIndex(symbol); Value *indice = indn->generate(func, block, allocblock); if (!indice || !indice->getType()->isIntegerTy()){ yyerrorcpp("Index to update " + ident.getFullName() + " elements must be of type integer.", this); @@ -54,6 +38,7 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * } Value *val = expr->generate(func, block, allocblock); + ArrayType *arrayTy = (ArrayType*)buildTypes->llvmType(symbol->getDataType()); val = Coercion::Convert(val, arrayTy->getArrayElementType(), block, this); RobDbgInfo.emitLocation(this); @@ -68,10 +53,6 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * Value *indexList[2] = {zero, indice}; Value *ptr = Builder->CreateGEP(arrayTy, sym, ArrayRef(indexList), "gep"); StoreInst *store = Builder->CreateStore(val, ptr, false); - - if (localarr) - delete arr; return store; } - diff --git a/src/UpdateArray.h b/src/UpdateArray.h index f2ea285..f7e2237 100644 --- a/src/UpdateArray.h +++ b/src/UpdateArray.h @@ -2,20 +2,13 @@ #pragma once #include "Node.h" -#include "Array.h" -#include "Identifier.h" +#include "LoadArray.h" -class UpdateArray: public Node { +class UpdateArray: public BaseArrayOper { protected: - Identifier ident; - Node *position; Node *expr; public: - UpdateArray(const char *i, Node *pos, Node *expr); + UpdateArray(const string &i, Node *pos, Node *expr); virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - - virtual Node *getElementIndex(LinearDataStructure *arr) { - return arr->getElementIndex(position, NULL); - } }; diff --git a/src/UpdateMatrix.h b/src/UpdateMatrix.h index 3ece2a0..bbd665b 100644 --- a/src/UpdateMatrix.h +++ b/src/UpdateMatrix.h @@ -2,16 +2,16 @@ #pragma once #include "Node.h" +#include "UpdateArray.h" +#include "LoadMatrix.h" class UpdateMatrix: public UpdateArray { -private: - Node *position2; public: - UpdateMatrix(const char *i, Node *p1, Node *p2, Node *expr) : UpdateArray(i, p1, expr) { + UpdateMatrix(const string &i, Node *p1, Node *p2, Node *expr) : UpdateArray(i, p1, expr) { this->position2 = p2; } - virtual Node *getElementIndex(LinearDataStructure *arr) override { - return arr->getElementIndex(position, position2); + virtual Node* getElementIndex(const Node *symbol) override { + return LoadMatrix::getElementIndexMatrix(this, symbol); } }; diff --git a/src/Visitor.h b/src/Visitor.h index f8bd8f1..df84907 100644 --- a/src/Visitor.h +++ b/src/Visitor.h @@ -33,7 +33,6 @@ class Loop; class UserType; class Variable; class NamedConst; -class LinearDataStructure; #define VISITOR_DECLAREP(T, P) \ virtual void visit(T& n) { visit((P&)n); } \ @@ -84,9 +83,8 @@ class Visitor { VISITOR_DECLAREP(FunctionDecl, FunctionBase) VISITOR_DECLAREP(UserType, NamedNode) VISITOR_DECLAREP(FunctionImpl, FunctionBase) - VISITOR_DECLAREP(LinearDataStructure, Variable) - VISITOR_DECLAREP(Array, LinearDataStructure) - VISITOR_DECLAREP(Matrix, LinearDataStructure) + VISITOR_DECLAREP(Array, Variable) + VISITOR_DECLAREP(Matrix, Variable) }; From 3fe4782501b43e64c024f1875653483177e7ab41 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Mon, 27 May 2024 23:15:30 -0300 Subject: [PATCH 046/117] Implements the support for matrices in function calls and other small fixes --- src/Array.cpp | 2 +- src/Array.h | 2 +- src/ArrayElements.cpp | 75 ++++++++++++++++++++--------------- src/ArrayElements.h | 4 +- src/BuildTypes.cpp | 15 ++++--- src/BuildTypes.h | 25 +++++++++--- src/Char.cpp | 7 ++++ src/Char.h | 24 +++++++++++ src/FunctionCall.cpp | 40 ++++++++++++++----- src/FunctionDecl.cpp | 2 +- src/FunctionDecl.h | 39 +++++++++++++----- src/FunctionImpl.cpp | 4 +- src/Header.h | 1 + src/Language.l | 2 +- src/Language.y | 11 +++-- src/LanguageHeader.y | 1 + src/LanguageUse.y | 8 +++- src/Load.cpp | 2 +- src/LoadArray.cpp | 4 +- src/LoadMatrix.h | 4 +- src/Matrix.cpp | 9 ++++- src/Matrix.h | 19 +++++++++ src/MatrixElements.cpp | 36 ++--------------- src/MatrixElements.h | 4 +- src/UpdateArray.cpp | 2 +- test/general/byref-matrix.rob | 28 +++++++++++++ test/general/itoa.rob | 30 +++++--------- 27 files changed, 263 insertions(+), 137 deletions(-) create mode 100644 src/Char.cpp create mode 100644 src/Char.h create mode 100644 test/general/byref-matrix.rob diff --git a/src/Array.cpp b/src/Array.cpp index e2d42f9..bcd4e18 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -29,7 +29,7 @@ void Array::createDataType() { //Get Type of elements in Array of Elements, and define as I. element_dt = elements->getArrayType(); dt = buildTypes->getArrayType(buildTypes->name(element_dt), - *this->getLoct(), true); + *this->getLoct(), 1, true); Type* I = buildTypes->llvmType(element_dt); //Declare array type. diff --git a/src/Array.h b/src/Array.h index a797a0e..0d9adfb 100644 --- a/src/Array.h +++ b/src/Array.h @@ -24,7 +24,7 @@ class ParamArray: public Variable { public: ParamArray(const string& n, string element_dt_name, location_t loc): Variable(n) { this->element_dt = buildTypes->getType(element_dt_name, true); - this->dt = buildTypes->getArrayType(element_dt_name, loc, true); + this->dt = buildTypes->getArrayType(element_dt_name, loc, 1, true); } ParamArray(const string &n, DataType dt): Variable(n) { diff --git a/src/ArrayElements.cpp b/src/ArrayElements.cpp index e465605..52c1914 100644 --- a/src/ArrayElements.cpp +++ b/src/ArrayElements.cpp @@ -1,12 +1,12 @@ #include "ArrayElements.h" -ArrayElements::ArrayElements() {}; +ArrayElements::ArrayElements(location_t loc): location(loc) {}; void ArrayElements::append(ArrayElement *e) { elements.push_back(e); }; - + unsigned ArrayElements::getArraySize() { unsigned r = 0; for(auto& i : elements) @@ -18,40 +18,51 @@ unsigned ArrayElements::getStructSize() { return elements.size(); } -DataType ArrayElements::getArrayType() { - unsigned intsize = 0; - unsigned floatsize = 0; - for(auto& i : elements) { - DataType dt = i->value->getDataType(); - if (buildTypes->isIntegerDataType(dt) && intsize < buildTypes->bitWidth(dt)) - intsize = buildTypes->bitWidth(dt); - - if (floatsize < 32 && dt == tfloat) - floatsize = 32; - else if (floatsize < 64 && dt == tdouble) - floatsize = 64; - else if (floatsize < 128 && dt == tldouble) - floatsize = 128; - } - if (intsize == 0 && floatsize == 0) { - yyerrorcpp("FIXME: vector of non-consts/non-numbers.", NULL); - return tvoid; +DataType ArrayElements::getArrayConstType(const set& types, SourceLocation *location) { + + if (types.size() == 1) { + // only one type + return *types.begin(); + } else if (types.size() == 2) { + // convert tchar and tint8 to tchar + if (types.find(tchar) != types.end() && + types.find(tint8) != types.end()) + return tchar; } - if (floatsize == 0) { - switch (intsize) { - case 1: return tbool; - case 8: return tint8; - case 16: return tint16; - case 32: return tint32; - default: return tint64; + + // int or float types: detect the largest + DataType intdt, floatdt; + unsigned largest_int = 0; + unsigned largest_float = 0; + for(auto dt : types) { + unsigned bitw = buildTypes->bitWidth(dt); + if (buildTypes->isIntegerDataType(dt) && largest_int < bitw) { + largest_int = bitw; + intdt = dt; } - } else { - switch (floatsize) { - case 32: return tfloat; - case 64: return tdouble; - default: return tldouble; + if (buildTypes->isFloatDataType(dt) && largest_float < bitw) { + largest_float = bitw; + floatdt = dt; } } + + if (largest_float > 0) + return floatdt; // convert all to largest float + else if (largest_int > 0) + return intdt; // convert all to largest int + else { + yyerrorcpp("Can't identify the array type based on its values.", location); + return BuildTypes::undefinedType; + } +} + +DataType ArrayElements::getArrayType() { + // find distinct types + set types; + for(auto& i : elements) { + types.emplace(i->value->getDataType()); + } + return getArrayConstType(types, &location); } Node *ArrayElements::getStructElement(int position) { diff --git a/src/ArrayElements.h b/src/ArrayElements.h index 0694a97..37f4a3c 100644 --- a/src/ArrayElements.h +++ b/src/ArrayElements.h @@ -13,8 +13,9 @@ class ArrayElement { class ArrayElements { private: std::vector elements; + SourceLocation location; public: - ArrayElements(); + ArrayElements(location_t loc); void append(ArrayElement *e); unsigned getArraySize(); @@ -22,6 +23,7 @@ class ArrayElements { unsigned getElementCount (int position); Node *getStructElement (int position); DataType getArrayType(); + static DataType getArrayConstType(const set& types, SourceLocation *location); std::vector const& getElements() { return elements; diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index aadbb43..34c51d7 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -44,8 +44,13 @@ BuildTypes::BuildTypes(DataType targetPointerType) { } } -DataType BuildTypes::getArrayType(const string& elementName, SourceLocation n, bool createUndefined) { - string arrayTyName = elementName + "[]"; +DataType BuildTypes::getArrayType(const string& elementName, SourceLocation n, + unsigned char dimensions, bool createUndefined) { + + string arrayTyName = elementName; + for(int i = 0; i < dimensions; i++) + arrayTyName += "[]"; + auto ut = namedTypes.find(arrayTyName); if (ut == namedTypes.end()) { if (createUndefined) { @@ -60,7 +65,7 @@ DataType BuildTypes::getArrayType(const string& elementName, SourceLocation n, b info.llvmType = ArrayType::get(elementInfo.llvmType, 0); // we couldn't know the array size at compile time info.isDefined = true; info.isComplex = false; - info.isArray = true; + info.arrayDimensions = dimensions; info.bitWidth = elementInfo.bitWidth; info.dwarfEnc = dwarf::DW_ATE_address; if (debug_info) { @@ -78,9 +83,9 @@ DataType BuildTypes::getArrayType(const string& elementName, SourceLocation n, b } DataType BuildTypes::getArrayElementType(DataType arrayDt) { - assert(isArray(arrayDt) && "arrayDt must be an array."); + assert(isArrayOrMatrix(arrayDt) && "arrayDt must be an array or matrix."); string elementName = name(arrayDt); - elementName = elementName.substr(0, elementName.length()-2); + elementName = elementName.substr(0, elementName.length() - 2*dimensions(arrayDt)); return getType(elementName); } diff --git a/src/BuildTypes.h b/src/BuildTypes.h index 192aaaf..dd6e1d5 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -28,7 +28,7 @@ struct DataTypeInfo { bool isComplex; bool isInterface; bool isInternal; - bool isArray; + unsigned char arrayDimensions; DataTypeInfo() {} @@ -43,13 +43,13 @@ struct DataTypeInfo { this->isComplex = false; this->isInternal = false; this->isInterface = false; - this->isArray = false; + this->arrayDimensions = 0; } DataTypeInfo(const char* name, unsigned bitWidth, Type *llvmType, unsigned dwarfEnc): name(name), bitWidth(bitWidth), llvmType(llvmType), dwarfEnc(dwarfEnc), diType(NULL), diPointerType(NULL), sl(NULL), isDefined(true), isComplex(false), isInternal(false), - isInterface(false), isArray(false) {}; + isInterface(false), arrayDimensions(0) {}; }; class BuildTypes { @@ -76,7 +76,7 @@ class BuildTypes { DataType getType(const string& name, bool createUndefined = false); DataType getArrayType(const string& elementName, SourceLocation n, - bool createUndefined = false); + unsigned char dimensions, bool createUndefined = false); DataType getArrayElementType(DataType arrayDt); @@ -150,7 +150,22 @@ class BuildTypes { bool isArray(DataType tid) { assert(tid != -1 && "Undefined type"); - return tinfo[tid].isArray; + return tinfo[tid].arrayDimensions == 1; + } + + bool isMatrix(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].arrayDimensions == 2; + } + + bool isArrayOrMatrix(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].arrayDimensions > 0; + } + + unsigned char dimensions(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].arrayDimensions; } }; diff --git a/src/Char.cpp b/src/Char.cpp new file mode 100644 index 0000000..8d71eec --- /dev/null +++ b/src/Char.cpp @@ -0,0 +1,7 @@ + +#include "Char.h" + +Value *Char::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) +{ + return ConstantInt::get(Type::getInt8Ty(global_context), value); +} diff --git a/src/Char.h b/src/Char.h new file mode 100644 index 0000000..4220dd5 --- /dev/null +++ b/src/Char.h @@ -0,0 +1,24 @@ + +#pragma once + +#include "Node.h" + +class Char: public Node { +private: + char value; + +public: + Char(char v): value(v) {} + + char getValue() const { return value; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tchar; + } +}; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 189fee1..5034840 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -175,10 +175,10 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock } vector args; - for (int i = 0; i < parameters->getNumParams(); i++){ + for (int i = 0, j = 0; i < parameters->getNumParams(); i++, j++) { Node *param = parameters->getParamElement(i); DataType call_dt = param->getDataType(); - DataType def_dt = fsymbol->getParameters().getParamType(i); + DataType def_dt = fsymbol->getParameters().getParamType(j); Value *valor = param->generate(func, block, allocblock); if (!valor) @@ -195,7 +195,14 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock buildTypes->name(call_dt)), this); yywarncpp("The function declaration is here.", fsymbol); } - } else if (buildTypes->isArray(call_dt)) { + } else if (buildTypes->isArrayOrMatrix(call_dt)) { + if (call_dt != def_dt) { + yyerrorcpp(string_format("Argument %s expects '%s' but '%s' was provided.", + fsymbol->getParameters().getParamName(i).c_str(), + buildTypes->name(def_dt), + buildTypes->name(call_dt)), this); + } + // we pass the address of the first element Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); Value *indexList[2] = {zero, zero}; @@ -207,14 +214,25 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock } args.push_back(valor); - // add a size parameter after each array - if (buildTypes->isArray(call_dt)) { - string psizename = param->getName() + ".size"; - Load ld(psizename); - ld.setScope(func); - valor = ld.generate(func, block, allocblock); - valor = Coercion::Convert(valor, buildTypes->llvmType(tint32), block, this); - args.push_back(valor); + // add a size parameter after each array, or .rows and .cols for matrixes + if (buildTypes->isArrayOrMatrix(call_dt)) { + vector params; + if (buildTypes->isArray(call_dt)) + params.push_back(".size"); + else if (buildTypes->isMatrix(call_dt)) { + params.push_back(".rows"); + params.push_back(".cols"); + } + + for(const string& p: params) { + string pname = param->getName() + p; + Load ld(pname); + ld.setScope(func); + valor = ld.generate(func, block, allocblock); + valor = Coercion::Convert(valor, buildTypes->llvmType(tint32), block, this); + args.push_back(valor); + j++; + } } } diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index ef7447f..9eaf9ee 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -20,7 +20,7 @@ bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { for (int i = 0; i < parameters->getParameters().size(); i++) { DataType dt = parameters->getParamType(i); Type *atype = buildTypes->llvmType(dt); - if (buildTypes->isComplex(dt) || buildTypes->isArray(dt)) { + if (buildTypes->isComplex(dt) || buildTypes->isArrayOrMatrix(dt)) { atype = atype->getPointerTo(); } if (!atype) { diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 99373d6..36c42a8 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -4,6 +4,7 @@ #include "Node.h" #include "FunctionParams.h" #include "Variable.h" +#include "Matrix.h" class FunctionBase: public NamedNode { protected: @@ -34,19 +35,37 @@ class FunctionBase: public NamedNode { } void addPseudoParameters() { - // add a size parameter after each array + // add a size parameter after each array, or .rows and .cols for matrixes std::vector const& vparams = this->parameters->getParameters(); for (int i = 0; i < vparams.size(); ++i) { Variable *p = vparams[i]; - if (buildTypes->isArray(p->getDataType())) { - string psizename = p->getName() + ".size"; - - //TODO: There is something better than fix this to Int32? Fix here and in FunctionCall::generate - Variable *sizep = new Variable(psizename.c_str(), tint32); - this->parameters->insert(i+1, sizep); - - // add a pseudo symbol to resolve to pname.size - p->addSymbol("size", sizep); + + DataType pdt = p->getDataType(); + if (buildTypes->isArrayOrMatrix(pdt)) { + vector pseudos; + if (buildTypes->isArray(pdt)) + pseudos.push_back("size"); + else if (buildTypes->isMatrix(pdt)) { + // let it inverted here, because of the insert below (i+1) + pseudos.push_back("cols"); + pseudos.push_back("rows"); + } + + for(const string& s: pseudos) { + //TODO: There is something better than fix this to Int32? Fix here and in FunctionCall::generate + string spname = p->getName() + "." + s; + Variable *sp = new Variable(spname, tint32); + this->parameters->insert(i+1, sp); + + // add a pseudo symbol to resolve to pname.s + p->addSymbol(s, sp); + } + + // ParamMatrix need to know the number of cols to compute element indexes + if (buildTypes->isMatrix(pdt)) { + if (ParamMatrix *pm = dynamic_cast(p)) + pm->setCols(vparams[i+2]); + } } } } diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index febf098..0026ec2 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -92,7 +92,7 @@ bool FunctionImpl::preGenerate() { const string& argname = fp->getName(); Type *talloc = buildTypes->llvmType(ptype); - if (buildTypes->isComplex(ptype) || buildTypes->isArray(ptype)) { + if (buildTypes->isComplex(ptype) || buildTypes->isArrayOrMatrix(ptype)) { talloc = talloc->getPointerTo(); fp->setPointerToPointer(true); } @@ -110,7 +110,7 @@ bool FunctionImpl::preGenerate() { if (debug_info) { DIType *dit = buildTypes->diType(ptype); - if (buildTypes->isComplex(ptype) || buildTypes->isArray(ptype)) + if (buildTypes->isComplex(ptype) || buildTypes->isArrayOrMatrix(ptype)) dit = buildTypes->diPointerType(ptype); DILocalVariable *d = DBuilder->createParameterVariable(sp, argname, Idx+1, funit, diff --git a/src/Header.h b/src/Header.h index 32a603d..e332111 100644 --- a/src/Header.h +++ b/src/Header.h @@ -28,6 +28,7 @@ #include "Variable.h" #include "If.h" #include "Int1.h" +#include "Char.h" #include "Int8.h" #include "Int16.h" #include "Int32.h" diff --git a/src/Language.l b/src/Language.l index 33859bb..0cb9a19 100644 --- a/src/Language.l +++ b/src/Language.l @@ -139,7 +139,7 @@ ID {A}({A}|{D})* unescape(aux); yylval->nint = aux[0]; free(aux); - return TOK_INTEGER; } + return TOK_CHAR; } /* deixar por último. Caractere não reconhecido pelo alfabeto. */ . { yyerror(yylloc, NULL, COLOR_RED "lexical error:" COLOR_RED " caractere nao pertence ao alfabeto da linguagem:"); } diff --git a/src/Language.y b/src/Language.y index aaf5ec1..1b1ab69 100644 --- a/src/Language.y +++ b/src/Language.y @@ -30,7 +30,7 @@ %type paramscall %type TOK_IDENTIFIER TOK_XIDENTIFIER ident_or_xident -%type TOK_INTEGER qualifier bind_scope +%type TOK_INTEGER TOK_CHAR qualifier bind_scope %type TOK_FLOAT %type TOK_DOUBLE %type TOK_LDOUBLE @@ -150,6 +150,10 @@ function_param : TOK_IDENTIFIER[type] '[' ']' TOK_IDENTIFIER[id] { $$ = new ParamArray($id, $type, @type); } +function_param : TOK_IDENTIFIER[type] '[' ']' '[' ']' TOK_IDENTIFIER[id] { + $$ = new ParamMatrix($id, $type, @type); +} + register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT expr ';' { $$ = new Pointer($name, buildTypes->getType($type, true), $5); $$->setQualifier(qvolatile); @@ -245,7 +249,7 @@ melements : melements ',' melement { } melements : melement { - MatrixElements *mes = new MatrixElements(); + MatrixElements *mes = new MatrixElements(@melements); mes->append($1); $$ = mes; } @@ -257,7 +261,7 @@ relements : '{' elements '}' { $$ = $2; } elements : elements ',' element { $1->append($3); $$ = $1; } - | element { ArrayElements *aes = new ArrayElements(); + | element { ArrayElements *aes = new ArrayElements(@element); aes->append($1); $$ = aes; } @@ -399,6 +403,7 @@ factor : '(' expr ')' { $$ = $2; } | ident_or_xident { $$ = new Load($1); } | TOK_TRUE { $$ = new Int1(1); } | TOK_FALSE { $$ = new Int1(0); } + | TOK_CHAR { $$ = new Char($1); } | TOK_INTEGER { $$ = getNodeForIntConst($1); } | TOK_FLOAT { $$ = new Float($1); } | TOK_DOUBLE { $$ = new Double($1); } diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index 0a2b37f..df92b1c 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -24,6 +24,7 @@ %token TOK_LOOP TOK_WHILE %token TOK_AND TOK_OR %token TOK_IDENTIFIER TOK_XIDENTIFIER +%token TOK_CHAR %token TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE %token TOK_FINT8 TOK_FINT16 TOK_FINT32 TOK_FINT64 %token TOK_FFLOAT TOK_FDOUBLE TOK_FCHAR TOK_FLONG TOK_FUNSIGNED TOK_FBOOL diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 1b1fb63..dccde84 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -136,6 +136,10 @@ function_param : TOK_IDENTIFIER[type] '[' ']' TOK_IDENTIFIER[id] { $$ = new ParamArray($id, $type, @type); } +function_param : TOK_IDENTIFIER[type] '[' ']' '[' ']' TOK_IDENTIFIER[id] { + $$ = new ParamMatrix($id, $type, @type); +} + register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT const_expr ';' { $$ = new Pointer($name, buildTypes->getType($type, true), $5); $$->setQualifier(qvolatile); @@ -225,7 +229,7 @@ melements : melements ',' melement { } melements : melement { - MatrixElements *mes = new MatrixElements(); + MatrixElements *mes = new MatrixElements(@melements); mes->append($1); $$ = mes; } @@ -237,7 +241,7 @@ relements : '{' elements '}' { $$ = $2; } elements : elements ',' element { $1->append($3); $$ = $1; } - | element { ArrayElements *aes = new ArrayElements(); + | element { ArrayElements *aes = new ArrayElements(@element); aes->append($1); $$ = aes; } diff --git a/src/Load.cpp b/src/Load.cpp index 7f122a5..c64ea6b 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -87,7 +87,7 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl return NULL; // Caused by an error on previous statement that defines the symbol DataType sdt = symbol->getDataType(); - if (buildTypes->isComplex(sdt) || buildTypes->isArray(sdt)) { + if (buildTypes->isComplex(sdt) || buildTypes->isArrayOrMatrix(sdt)) { if (symbol->isPointerToPointer()) { Type *ty = buildTypes->llvmType(sdt)->getPointerTo(); alloc = Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index 35c0661..dd58fdb 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -11,7 +11,7 @@ LoadArray::LoadArray(const string &i, Node *pos): BaseArrayOper(i, pos, NULL) { DataType LoadArray::getDataType() { if (dt == BuildTypes::undefinedType) { Node *symbol = ident.getSymbol(getScope()); - if (symbol && buildTypes->isArray(symbol->getDataType())) + if (symbol && buildTypes->isArrayOrMatrix(symbol->getDataType())) dt = buildTypes->getArrayElementType(symbol->getDataType()); } return dt; @@ -23,7 +23,7 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al if (!symbol) return NULL; - if (!buildTypes->isArray(symbol->getDataType())) { + if (!buildTypes->isArrayOrMatrix(symbol->getDataType())) { yyerrorcpp("Variable " + ident.getFullName() + " is not an array or matrix.", this); return NULL; } diff --git a/src/LoadMatrix.h b/src/LoadMatrix.h index 3d2f435..31b6757 100644 --- a/src/LoadMatrix.h +++ b/src/LoadMatrix.h @@ -4,6 +4,7 @@ #include "Matrix.h" #include "Array.h" #include "LoadArray.h" +#include "Load.h" class LoadMatrix: public LoadArray { public: @@ -26,7 +27,8 @@ class LoadMatrix: public LoadArray { cols = mx->getCols(); mcols = getNodeForIntConst(cols); } else if (const ParamMatrix *pmx = dynamic_cast(symbol)) { - mcols = pmx->getCols(); + mcols = new Load(pmx->getCols()->getName()); + mcols->setScope(pmx->getCols()->getScope()); } return Array::getElementIndex(matrix->getPosition(), matrix->getPosition2(), diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 882b29d..0db0d77 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -80,8 +80,13 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc if (getGEPIndex() != -1) alloc = getLLVMValue(func); - else + else { alloc = Builder->CreateAlloca(matrixType, dataAddrSpace, 0, name); + if (debug_info) { + RobDbgInfo.emitLocation(this); + RobDbgInfo.declareVar(this, alloc, allocblock); + } + } RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); @@ -118,7 +123,7 @@ void Matrix::createDataType() { //Get Type of elements in Vector of Elements, and define as I. element_dt = melements->getMatrixType(); dt = buildTypes->getArrayType(buildTypes->name(element_dt), - *this->getLoct(), true); + *this->getLoct(), 2, true); Type* I = buildTypes->llvmType(element_dt); // The matrix type and size diff --git a/src/Matrix.h b/src/Matrix.h index 621f1bf..3fae8e5 100644 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -4,6 +4,25 @@ #include "MatrixElements.h" #include "Variable.h" +class ParamMatrix: public Variable { +private: + Node *mcols = NULL; + DataType element_dt; +public: + ParamMatrix(const string& n, string element_dt_name, location_t loc): Variable(n) { + this->element_dt = buildTypes->getType(element_dt_name, true); + this->dt = buildTypes->getArrayType(element_dt_name, loc, 2, true); + } + + void setCols(Node *cols) { + mcols = cols; + } + + Node *getCols() const { + return mcols; + } +}; + class Matrix: public Variable { private: MatrixElements *melements; diff --git a/src/MatrixElements.cpp b/src/MatrixElements.cpp index 607797a..0707023 100644 --- a/src/MatrixElements.cpp +++ b/src/MatrixElements.cpp @@ -1,7 +1,7 @@ #include "MatrixElements.h" -MatrixElements::MatrixElements() {}; +MatrixElements::MatrixElements(location_t loc): location(loc) {}; void MatrixElements::append(MatrixElement *m) { elements.push_back(m); @@ -28,41 +28,13 @@ unsigned MatrixElements::getColumnCount() { } DataType MatrixElements::getMatrixType() { - unsigned intsize = 0; - unsigned floatsize = 0; + set types; for(auto& j : elements) { for (auto& i : j->array->getElements()) { - DataType dt = i->value->getDataType(); - if (buildTypes->isIntegerDataType(dt) && intsize < buildTypes->bitWidth(dt)) - intsize = buildTypes->bitWidth(dt); - - if (floatsize < 32 && dt == tfloat) - floatsize = 32; - else if (floatsize < 64 && dt == tdouble) - floatsize = 64; - else if (floatsize < 128 && dt == tldouble) - floatsize = 128; - } - } - if (intsize == 0 && floatsize == 0) { - yyerrorcpp("FIXME: vector of non-consts/non-numbers.", NULL); - return tvoid; - } - if (floatsize == 0) { - switch (intsize) { - case 1: return tbool; - case 8: return tint8; - case 16: return tint16; - case 32: return tint32; - default: return tint64; - } - } else { - switch (floatsize) { - case 32: return tfloat; - case 64: return tdouble; - default: return tldouble; + types.emplace(i->value->getDataType()); } } + return ArrayElements::getArrayConstType(types, &location); } unsigned MatrixElements::getElementCount(int position) { diff --git a/src/MatrixElements.h b/src/MatrixElements.h index ae2ce89..fcb64df 100644 --- a/src/MatrixElements.h +++ b/src/MatrixElements.h @@ -1,7 +1,6 @@ #pragma once -#include "Node.h" #include "ArrayElements.h" class MatrixElement { @@ -14,8 +13,9 @@ class MatrixElement { class MatrixElements { private: std::vector elements; + SourceLocation location; public: - MatrixElements(); + MatrixElements(location_t loc); void append(MatrixElement *m); unsigned getColumnCount(); diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index da715c8..d3fc5d6 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -16,7 +16,7 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * if (!symbol) return NULL; - if (!buildTypes->isArray(symbol->getDataType())) { + if (!buildTypes->isArrayOrMatrix(symbol->getDataType())) { yyerrorcpp("Symbol " + ident.getFullName() + " is not an array or matrix.", this); return NULL; } diff --git a/test/general/byref-matrix.rob b/test/general/byref-matrix.rob new file mode 100644 index 0000000..15c2c4b --- /dev/null +++ b/test/general/byref-matrix.rob @@ -0,0 +1,28 @@ + +int32 sum_matrix(int16[][] a); + +int32 main() { + // 3x3 matrix of one's + x = {{int16(1):3}:3}; + + zt = sum_matrix(x); + if zt != 9 { + return zt; + } + + return 0; +} + +int32 sum_matrix(int16[][] a) { + i = 0; + result = int32(0); + while i < a.rows { + j = 0; + while j < a.cols { + result += a[i][j]; + j++; + } + i++; + } + return result; +} diff --git a/test/general/itoa.rob b/test/general/itoa.rob index c7b09c3..4ef9c4e 100644 --- a/test/general/itoa.rob +++ b/test/general/itoa.rob @@ -76,23 +76,11 @@ base16 = { {'7', 'f', 'f', 'f', 0 , 0} }; -bool check10(int8 id, char[] result) { +bool check(int8 id, char[][] expected, char[] result) { ret = true; i = 0; - while result[i] != 0 and ret == true { - if result[i] != base10[id][i] { - ret = false; - } - i++; - } - return ret; -} - -bool check16(int8 id, char[] result) { - ret = true; - i = 0; - while result[i] != 0 and ret == true { - if result[i] != base16[id][i] { + while result[i] != 0 and ret { + if result[i] != expected[id][i] { ret = false; } i++; @@ -101,19 +89,19 @@ bool check16(int8 id, char[] result) { } int16 main() { - result = {0:18}; + result = {'\0':18}; ret = true; i = 0; - while i < numbers.size and ret == true { + while i < numbers.size and ret { itoa(numbers[i], 10, result); - ret = check10(i, result); - if ret == true { + ret = check(i, base10, result); + if ret { itoa(numbers[i], 16, result); - ret = check16(i, result); + ret = check(i, base16, result); } i++; } - if ret == true { + if ret { return 0; } else { return 1; From 866614833366cfd0fecd0e0de2e271518f6e3c1f Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 29 May 2024 10:30:30 -0300 Subject: [PATCH 047/117] Implements matrix copy and minor fixes --- src/FunctionDecl.h | 2 +- src/Identifier.cpp | 2 +- src/Load.cpp | 8 +++-- src/Load.h | 2 ++ src/LoadArray.cpp | 2 +- src/LoadArray.h | 2 +- src/LoadMatrix.h | 12 +++++--- src/Matrix.h | 9 ------ src/MemCopy.cpp | 16 +++++++++- src/UpdateMatrix.h | 3 +- test/general/byref-matrix.rob | 58 +++++++++++++++++++++++++++++++++-- test/general/runtest.sh | 2 +- 12 files changed, 91 insertions(+), 27 deletions(-) diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 36c42a8..60a0155 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -64,7 +64,7 @@ class FunctionBase: public NamedNode { // ParamMatrix need to know the number of cols to compute element indexes if (buildTypes->isMatrix(pdt)) { if (ParamMatrix *pm = dynamic_cast(p)) - pm->setCols(vparams[i+2]); + pm->addSymbol("cols", vparams[i+2]); } } } diff --git a/src/Identifier.cpp b/src/Identifier.cpp index d8fa7c4..236e4a7 100644 --- a/src/Identifier.cpp +++ b/src/Identifier.cpp @@ -4,7 +4,7 @@ Node* Identifier::getSymbol(Node *scope, bool validate) { if (scope == NULL) - assert("scope can't be null!"); + assert(scope && "scope can't be null!"); Node *result = scope; stringstream ss(ident); diff --git a/src/Load.cpp b/src/Load.cpp index c64ea6b..e4f6613 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -17,9 +17,11 @@ DataType Load::getDataType() { Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - Node *isymbol = ident.getSymbol(getScope(), false); - if (!isymbol) - isymbol = ident.getSymbol(func, false); + if (!isymbol) { + isymbol = ident.getSymbol(getScope(), false); + if (!isymbol) + isymbol = ident.getSymbol(func, false); + } if (isymbol && isymbol->isConstExpr()) return isymbol->getLLVMValue(func); diff --git a/src/Load.h b/src/Load.h index b55be93..a887718 100644 --- a/src/Load.h +++ b/src/Load.h @@ -7,10 +7,12 @@ class Load: public Node { private: Identifier ident; Variable *leftValue = NULL; + Node *isymbol = NULL; public: Load(const char* i): ident(i) { } Load(Identifier i): ident(i) { } + Load(Node *n): isymbol(n), ident(n->getName()) { } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index dd58fdb..597cb73 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -76,7 +76,7 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al return ret; } -Node* BaseArrayOper::getElementIndex(const Node *symbol) { +Node* BaseArrayOper::getElementIndex(Node *symbol) { // Get element int rows = -1; diff --git a/src/LoadArray.h b/src/LoadArray.h index bfba866..aef3660 100644 --- a/src/LoadArray.h +++ b/src/LoadArray.h @@ -13,7 +13,7 @@ class BaseArrayOper: public Node { BaseArrayOper(const string& i, Node *pos, Node *pos2): ident(i), position(pos), position2(pos2) {} - virtual Node* getElementIndex(const Node *symbol); + virtual Node* getElementIndex(Node *symbol); Node *getPosition() { return position; diff --git a/src/LoadMatrix.h b/src/LoadMatrix.h index 31b6757..97037ea 100644 --- a/src/LoadMatrix.h +++ b/src/LoadMatrix.h @@ -13,11 +13,11 @@ class LoadMatrix: public LoadArray { addChild(p2); } - virtual Node* getElementIndex(const Node *symbol) override { + virtual Node* getElementIndex(Node *symbol) override { return getElementIndexMatrix(this, symbol); } - static Node* getElementIndexMatrix(BaseArrayOper *matrix, const Node *symbol) { + static Node* getElementIndexMatrix(BaseArrayOper *matrix, Node *symbol) { // Get element int rows = -1; int cols = -1; @@ -26,11 +26,13 @@ class LoadMatrix: public LoadArray { rows = mx->getRows(); cols = mx->getCols(); mcols = getNodeForIntConst(cols); - } else if (const ParamMatrix *pmx = dynamic_cast(symbol)) { - mcols = new Load(pmx->getCols()->getName()); - mcols->setScope(pmx->getCols()->getScope()); + } else if (Node *s = symbol->findSymbol("cols", false)) { + mcols = new Load(s); + mcols->setScope(symbol); } + assert(mcols && "Missing the number of columns to compute the matrix element index."); + return Array::getElementIndex(matrix->getPosition(), matrix->getPosition2(), matrix->getIdent(), rows, cols, mcols); } diff --git a/src/Matrix.h b/src/Matrix.h index 3fae8e5..743c118 100644 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -6,21 +6,12 @@ class ParamMatrix: public Variable { private: - Node *mcols = NULL; DataType element_dt; public: ParamMatrix(const string& n, string element_dt_name, location_t loc): Variable(n) { this->element_dt = buildTypes->getType(element_dt_name, true); this->dt = buildTypes->getArrayType(element_dt_name, loc, 2, true); } - - void setCols(Node *cols) { - mcols = cols; - } - - Node *getCols() const { - return mcols; - } }; class Matrix: public Variable { diff --git a/src/MemCopy.cpp b/src/MemCopy.cpp index caabf05..5824f5e 100644 --- a/src/MemCopy.cpp +++ b/src/MemCopy.cpp @@ -33,6 +33,20 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo nelem = ld.generate(func, allocblock, allocblock); Builder->SetInsertPoint(allocblock); size = Builder->CreateBinOp(Instruction::Mul, elbytes, nelem, "arrsize"); + } else if (buildTypes->isMatrix(dt)) { + // Load the matrix size and compute the bytes to copy + DataType eldt = buildTypes->getArrayElementType(dt); + TypeSize eltsize = dl.getTypeAllocSize(buildTypes->llvmType(eldt)); + ConstantInt *elbytes = ConstantInt::get(Type::getInt32Ty(global_context), eltsize); + Load ldrows("rows"); + ldrows.setScope(expr); + Load ldcols("cols"); + ldcols.setScope(expr); + Builder->SetInsertPoint(allocblock); + Value *nrows = ldrows.generate(func, allocblock, allocblock); + Value *ncols = ldcols.generate(func, allocblock, allocblock); + nelem = Builder->CreateBinOp(Instruction::Mul, nrows, ncols, "matrixelem"); + size = Builder->CreateBinOp(Instruction::Mul, elbytes, nelem, "matrixsize"); } else { TypeSize ts = dl.getTypeAllocSize(buildTypes->llvmType(dt)); size = ConstantInt::get(Type::getInt32Ty(global_context), ts); @@ -46,7 +60,7 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo //FIXME: must check the alloc size for array and matrix } else { Builder->SetInsertPoint(allocblock); - if (buildTypes->isArray(dt)) { + if (buildTypes->isArrayOrMatrix(dt)) { DataType eldt = buildTypes->getArrayElementType(dt); dest = Builder->CreateAlloca(buildTypes->llvmType(eldt), dataAddrSpace, nelem, leftValue->getName()); leftvty = buildTypes->llvmType(dt)->getPointerTo(); diff --git a/src/UpdateMatrix.h b/src/UpdateMatrix.h index bbd665b..f0d05f4 100644 --- a/src/UpdateMatrix.h +++ b/src/UpdateMatrix.h @@ -9,9 +9,10 @@ class UpdateMatrix: public UpdateArray { public: UpdateMatrix(const string &i, Node *p1, Node *p2, Node *expr) : UpdateArray(i, p1, expr) { this->position2 = p2; + addChild(p2); } - virtual Node* getElementIndex(const Node *symbol) override { + virtual Node* getElementIndex(Node *symbol) override { return LoadMatrix::getElementIndexMatrix(this, symbol); } }; diff --git a/test/general/byref-matrix.rob b/test/general/byref-matrix.rob index 15c2c4b..52894a9 100644 --- a/test/general/byref-matrix.rob +++ b/test/general/byref-matrix.rob @@ -5,14 +5,66 @@ int32 main() { // 3x3 matrix of one's x = {{int16(1):3}:3}; - zt = sum_matrix(x); - if zt != 9 { + // y is a reference to x + y = x; + + i = 0; + while i < y.rows { + j = 0; + while j < y.cols { + if y[i][j] != x[i][j] { + return 1; + } + j++; + } + i++; + } + + + // w is a reference to y (same as x) + w = y; + i = 0; + while i < w.rows { + j = 0; + while j < w.cols { + if w[i][j] != x[i][j] { + return 1; + } + j++; + } + i++; + } + + // z is a copy of y + z = copy(y); + i = 0; + while i < z.rows { + j = 0; + while j < z.cols { + z[i][j] = z[i][j] + 1; + if z[i][j] != x[i][j] + 1 { + return 1; + } + j++; + } + i++; + } + + zt = sum_matrix(w); + if zt != 9 + 2 + 6 { return zt; } return 0; } +int32 pass_matrix_pointer(int16[][] b) { + c = b; + d = copy(b); + result = c[1][2] + d[2][2] + b.cols + b.rows; + return result; +} + int32 sum_matrix(int16[][] a) { i = 0; result = int32(0); @@ -24,5 +76,5 @@ int32 sum_matrix(int16[][] a) { } i++; } - return result; + return result + pass_matrix_pointer(a); } diff --git a/test/general/runtest.sh b/test/general/runtest.sh index a11b6da..7028b7e 100755 --- a/test/general/runtest.sh +++ b/test/general/runtest.sh @@ -4,7 +4,7 @@ RED="\033[0;31m" NC="\033[0m" echo -n " ... $1" -make -s $2 &> /dev/null +make -s $2 if [ "$?" -eq 0 ]; then timeout 10s ./$2 &> /dev/null #./$2 &> /dev/null From aadb80a44ec6e0aeb7056225907c47b77442ae9d Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 29 May 2024 11:42:21 -0300 Subject: [PATCH 048/117] Adjusts tests according to the new array/matrix features --- test/avr328p/Makefile | 4 ++-- test/avr328p/globals.rob | 2 +- test/avr328p/itoa.rob | 45 ++++++++++++++-------------------------- test/avr328p/runtest.sh | 2 +- test/general/Makefile | 2 +- 5 files changed, 21 insertions(+), 34 deletions(-) diff --git a/test/avr328p/Makefile b/test/avr328p/Makefile index 6b30d8c..1aed15a 100644 --- a/test/avr328p/Makefile +++ b/test/avr328p/Makefile @@ -3,7 +3,7 @@ ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) ALL_TT=$(patsubst %.rob,out/%.tt,$(wildcard *.rob)) ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/avr328p.o -ROBCMP=../../robcmp +ROBCMP=../../build/robcmp INCLUDES=-I aux ifndef OPT @@ -19,7 +19,7 @@ DEPENDS=${ROBCMP} Makefile LINK_DEPENDS=out/avr328p.o SERIAL_DEPENDS=out/aux/serial.o out/aux/avr5mcu.o -all: out ${ALL} +all: out test out: mkdir -p out/aux diff --git a/test/avr328p/globals.rob b/test/avr328p/globals.rob index f6b1e21..77eed1e 100644 --- a/test/avr328p/globals.rob +++ b/test/avr328p/globals.rob @@ -7,7 +7,7 @@ vint32 = int32(16000000); int16 main() { ret = int16(1); - if boolean == true { + if boolean { if vint8 + vint16 + vint32 == 16000030 { ret = 0; } diff --git a/test/avr328p/itoa.rob b/test/avr328p/itoa.rob index 903f8b3..bde67c1 100644 --- a/test/avr328p/itoa.rob +++ b/test/avr328p/itoa.rob @@ -3,9 +3,7 @@ use serial; chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; -result = {0:18}; - -void itoa(int16 value, int8 base) { +void itoa(int16 value, int8 base, char[] result) { if base < 2 or base > 16 { result[0] = 0; return; @@ -80,11 +78,11 @@ base16 = { {'7', 'f', 'f', 'f', 0 , 0} }; -bool check10(int8 id) { +bool check(int8 id, char[][] expected, char[] result) { ret = true; i = 0; - while result[i] != 0 and ret == true { - if result[i] != base10[id][i] { + while result[i] != 0 and ret { + if result[i] != expected[id][i] { ret = false; } i++; @@ -92,19 +90,7 @@ bool check10(int8 id) { return ret; } -bool check16(int8 id) { - ret = true; - i = 0; - while result[i] != 0 and ret == true { - if result[i] != base16[id][i] { - ret = false; - } - i++; - } - return ret; -} - -void print_result(avr5_serial s) { +void print_result(avr5_serial s, char[] result) { i = 0; while result[i] != 0 { s.write(result[i]); @@ -118,22 +104,23 @@ int16 main() { serial = avr5_serial(); serial.start(mcu, 9600); + result = {'\0':18}; ret = true; i = 0; - while i < numbers.size and ret == true { - itoa(numbers[i], 10); - ret = check10(i); - print_result(serial); - - if ret == true { - itoa(numbers[i], 16); - ret = check16(i); - print_result(serial); + while i < numbers.size and ret { + itoa(numbers[i], 10, result); + ret = check(i, base10, result); + print_result(serial, result); + + if ret { + itoa(numbers[i], 16, result); + ret = check(i, base16, result); + print_result(serial, result); } i++; } - if ret == true { + if ret { return 0; } else { return 1; diff --git a/test/avr328p/runtest.sh b/test/avr328p/runtest.sh index 7d46083..503dcd3 100755 --- a/test/avr328p/runtest.sh +++ b/test/avr328p/runtest.sh @@ -6,7 +6,7 @@ RED="\033[0;31m" NC="\033[0m" echo -n " $1" -make -s $2 &> /dev/null +make -s $2 if [ "$?" -eq 0 ]; then timeout 10s ${CMD} &> /dev/null #./$2 &> /dev/null diff --git a/test/general/Makefile b/test/general/Makefile index 9007a86..114c03b 100644 --- a/test/general/Makefile +++ b/test/general/Makefile @@ -16,7 +16,7 @@ ifndef OPT OPT=-Oz endif -all: out ${ALL} +all: out test out: mkdir -p out From 774a96dd0375b518c6d31a6a133eb09668e4ff00 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 2 Jun 2024 01:40:19 -0300 Subject: [PATCH 049/117] Injections now working on simavr with ssd1306 \o/ - Refactoring injections: new model based on functions; - Improved code generation warnings on BackLLVM.cpp - Debugger fixes. --- lib/avr328p.rob | 152 ++++++++------- .../examples/avr328p-ssd1306/platformio.ini | 3 +- .../examples/avr328p-ssd1306/src/avr5mcu.rob | 51 ++++- .../examples/avr328p-ssd1306/src/avr5regs.rob | 44 +++-- .../examples/avr328p-ssd1306/src/databus.rob | 2 +- .../examples/avr328p-ssd1306/src/main.rob | 57 ++++-- .../examples/avr328p-ssd1306/src/mcu.rob | 4 +- .../examples/avr328p-ssd1306/src/ssd1306.rob | 41 +++- platformio/platform/boards/avr328p.json | 25 ++- platformio/platform/platform.py | 14 +- src/BackLLVM.cpp | 9 +- src/BuildTypes.h | 5 + src/DebugInfo.cpp | 6 +- src/FunctionCall.cpp | 122 ++++++------ src/FunctionDecl.cpp | 11 ++ src/FunctionDecl.h | 38 +++- src/FunctionImpl.cpp | 29 +-- src/FunctionImpl.h | 28 +-- src/Interface.cpp | 1 - src/Language.y | 4 +- src/LanguageUse.y | 1 + src/Load.cpp | 6 + src/Node.cpp | 4 +- src/Node.h | 2 +- src/Program.cpp | 176 +++++++++++++++--- src/Return.cpp | 18 +- src/Scalar.cpp | 7 +- src/UserType.cpp | 12 +- src/UserType.h | 8 + src/Variable.cpp | 13 +- src/{NullConst.h => ZeroInit.h} | 7 +- 31 files changed, 628 insertions(+), 272 deletions(-) rename src/{NullConst.h => ZeroInit.h} (57%) diff --git a/lib/avr328p.rob b/lib/avr328p.rob index 385d5bc..480a268 100644 --- a/lib/avr328p.rob +++ b/lib/avr328p.rob @@ -2,73 +2,85 @@ * Robcmp interruptions vector for atmega328p */ -void main(); -void __vectors(); - -// implemented in avr5.S -void __do_copy_data(); -void __do_clear_bss(); - -void __vectors() { - /* FIXME: provide proper interrupt functions instead of __vectors - * after implementing "weak" attribute for functions - */ - - /* atmega328p has 26 interruptions */ - asm "rjmp __init"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - asm "rjmp __vectors"; - - asm "__init:"; - // clear r1 (zero reg) - asm "clr r1"; - // clear sreg - asm "out 0x3f, r1"; - // set stack at 0x08FF (0x100+2K-1) - asm "ldi r28, 0xFF"; - asm "ldi r29, 0x08"; - asm "out 0x3e, r29"; - asm "out 0x3d, r28"; - - /* same code in .rob, but it produces a larger assembly code - /*register int8 SREG at 0x3f; - register int16 STACK at 0x3d; - SREG = 0; - STACK = 0x08FF;*/ - - // copy global vars init data - __do_copy_data(); - - // clear zeroed global vars - __do_clear_bss(); - - main(); - - // if main returns, disable interruptions and sleep. - // this is used to quit simavr in our tests - asm "cli"; - asm "sleep"; -} + void main(); + void __vectors(); + + // implemented in avr5.S + void __do_copy_data(); + void __do_clear_bss(); + + void __default_irq() { + asm "reti"; + } + + void __delay_us() { + asm "ldi r18, 5"; + asm "__delay_ms_loop: dec r18"; + asm "brne __delay_ms_loop"; + asm "nop"; + } + + void __vectors() { + /* FIXME: provide proper interrupt functions instead of __vectors + * after implementing "weak" attribute for functions + */ + + /* atmega328p has 26 interruptions */ + asm "rjmp __init"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + asm "rjmp __default_irq"; + + asm "__init:"; + // clear r1 (zero reg) + asm "clr r1"; + // clear sreg + asm "out 0x3f, r1"; + // set stack at 0x08FF (0x100+2K-1) + asm "ldi r28, 0xFF"; + asm "ldi r29, 0x08"; + asm "out 0x3e, r29"; + asm "out 0x3d, r28"; + + /* same code in .rob, but it produces a larger assembly code + /*register int8 SREG at 0x3f; + register int16 STACK at 0x3d; + SREG = 0; + STACK = 0x08FF;*/ + + // copy global vars init data + __do_copy_data(); + + // clear zeroed global vars + __do_clear_bss(); + + main(); + + // if main returns, disable interruptions and sleep. + // this is used to quit simavr in our tests + asm "cli"; + asm "sleep"; + } + \ No newline at end of file diff --git a/platformio/examples/avr328p-ssd1306/platformio.ini b/platformio/examples/avr328p-ssd1306/platformio.ini index b75fd8c..41a6d29 100644 --- a/platformio/examples/avr328p-ssd1306/platformio.ini +++ b/platformio/examples/avr328p-ssd1306/platformio.ini @@ -6,7 +6,8 @@ upload_protocol = serial [env:release] build_type = release +debug_tool = robcmp-ssd1306 [env:debug] build_type = debug -debug_tool = robcmp +debug_tool = robcmp-ssd1306 diff --git a/platformio/examples/avr328p-ssd1306/src/avr5mcu.rob b/platformio/examples/avr328p-ssd1306/src/avr5mcu.rob index e1d88bd..15b68cb 100644 --- a/platformio/examples/avr328p-ssd1306/src/avr5mcu.rob +++ b/platformio/examples/avr328p-ssd1306/src/avr5mcu.rob @@ -5,8 +5,14 @@ use databus; use avr5regs; +void __delay_us(); + type avr5mcu implements mcu { + void set_interruptions(bool enabled) { + sreg.I = enabled; + } + /* implement this idea later! template digport { void mode(m port_mode) { port_config = mode; } @@ -60,35 +66,60 @@ type avr5mcu implements mcu { b5.set(s); } - void wait(int32 q) { - volatile i = q; - while i > 0 { - i--; + void wait_us(int16 us) { + while us > 0 { + __delay_us(); + us--; + } + } + + void wait_ms(int16 ms) { + while ms > 0 { + wait_us(1000); + ms--; } } spi = databus { + // b3 = MOSI + // b4 = MISO + // b5 = SCK void setup(int32 speed) { b3.mode(port_mode.output); - b4.mode(port_mode.output); + b4.mode(port_mode.input); b5.mode(port_mode.output); - spcr.MSTR = true; // master? + spcr.MSTR = true; // master + + // ignoring speed for now + //spcr.SPR0 = true; // fck/16 + //spcr.SPR1 = false; + + //spcr.CPOL = true; + //spcr.CPHA = true; + spsr.SPI2x = true; // 2x speed } + void enable() { spcr.SPE = true; + //spcr.SPIE = true; } + void disable() { spcr.SPE = false; + //spcr.SPIE = false; } - void write(int8 b) { - sprd = b; - while spsr.SPIF == false; + + void write(unsigned8 b) { + spdr = b; + while !spsr.SPIF; } + int8 read() { //FIXME - while spsr.SPIF == false; + while !spsr.SPIF; return spdr; } + bool has_data() { //FIXME return spsr.SPIF; diff --git a/platformio/examples/avr328p-ssd1306/src/avr5regs.rob b/platformio/examples/avr328p-ssd1306/src/avr5regs.rob index 77a405a..07759ca 100644 --- a/platformio/examples/avr328p-ssd1306/src/avr5regs.rob +++ b/platformio/examples/avr328p-ssd1306/src/avr5regs.rob @@ -1,4 +1,26 @@ +/* + * Global Registers + */ + +type sreg_t { + C = false; // Carry Flag + Z = false; // Zero Flag + N = false; // Negative Flag + V = false; // Two’s Complement Overflow Flag + S = false; // Sign Bit + H = false; // Half Carry Flag + T = false; // Bit Copy Storage + I = false; // Global Interrupt Enable +} + +register sreg_t sreg at 0x5f; + + +/* + * IO PORTS + */ + type portb_t { b0 = false; b1 = false; @@ -17,24 +39,24 @@ register portb_t ddrb at 0x24; */ type spcr_t { - SPR0 = false; - SPR1 = false; - CPHA = false; - CPOL = false; - MSTR = false; - DORD = false; - SPE = false; - SPIE = false; + SPR0 = false; // SPI clock rate 0 + SPR1 = false; // SPI clock rate 1 + CPHA = false; // Clock phase + CPOL = false; // Clock polarity + MSTR = false; // Master + DORD = false; // Data order + SPE = false; // SPI enable + SPIE = false; // SPI interruption enable } // SPI Control Register register spcr_t spcr at 0x4c; type spsr_t { - SPI2x = false; + SPI2x = false; // Double SPI speed _reserved = int5(0); - WCOL = false; - SPIF = false; + WCOL = false; // Write COLision flag + SPIF = false; // SPI interrupt flag } // SPI Status Register diff --git a/platformio/examples/avr328p-ssd1306/src/databus.rob b/platformio/examples/avr328p-ssd1306/src/databus.rob index b3f6af1..8d8667d 100644 --- a/platformio/examples/avr328p-ssd1306/src/databus.rob +++ b/platformio/examples/avr328p-ssd1306/src/databus.rob @@ -3,7 +3,7 @@ interface databus { void setup(int32 speed); void enable(); void disable(); - void write(int8 b); + void write(unsigned8 b); int8 read(); bool has_data(); } diff --git a/platformio/examples/avr328p-ssd1306/src/main.rob b/platformio/examples/avr328p-ssd1306/src/main.rob index c47dd94..15d933e 100644 --- a/platformio/examples/avr328p-ssd1306/src/main.rob +++ b/platformio/examples/avr328p-ssd1306/src/main.rob @@ -1,32 +1,55 @@ /* * Robcmp examples: SSD1306 SPI */ - use avr5mcu; use ssd1306; -//bind avr5mcu to mmcu; -//bind avr5mcu.b0 to ssd1306.reset -//bind avr5mcu.spi1 to ssd1306.spi -//alias avr5mcu.b5 to ; -//led[digital,pwm,asdfs] -// +bind avr5mcu to global_instances.mmcu singleton; +bind avr5mcu.spi to global_instances.spi singleton; +bind avr5mcu to ssd1306.mmcu singleton; +bind avr5mcu.b0 to ssd1306.reset singleton; +bind avr5mcu.b1 to ssd1306.datacmd singleton; +bind avr5mcu.b2 to ssd1306.select singleton; +bind avr5mcu.spi to ssd1306.spi singleton; + +// for now, the binding only work inside types. +// this is a type for holding an instance of mcu +type global_instances { + mmcu = mcu(); + spi = databus(); +} int16 main() { - mmcu = avr5mcu(); - spi = mmcu.spi; - spi.init(); + gi = global_instances(); + mmcu = gi.mmcu; - display = ssd1306(); - display.init(); + // setup and enable SPI + spi = gi.spi; + spi.setup(0); + spi.enable(); + display = ssd1306(); + display.init_display(); + + data = 2; loop { - led = true; - //mcu.set_led(true); - mcu.wait(100000); + mmcu.wait_ms(1000); + display.reset_cursor(); + + i = 0; + while i < display.pages() { + j = int16(0); + while j < display.columns() { + display.write_data(data); + j++; + } + i++; + } - //mcu.set_led(false); - mcu.wait(100000); + data *= 2; + if data == 0 { + data = 1; + } } } diff --git a/platformio/examples/avr328p-ssd1306/src/mcu.rob b/platformio/examples/avr328p-ssd1306/src/mcu.rob index 15d7d5a..acecc8a 100644 --- a/platformio/examples/avr328p-ssd1306/src/mcu.rob +++ b/platformio/examples/avr328p-ssd1306/src/mcu.rob @@ -1,6 +1,8 @@ interface mcu { - void wait(int32 us); + void wait_us(int16 us); + void wait_ms(int16 ms); void enable_led(); void set_led(bool s); + void set_interruptions(bool enabled); } diff --git a/platformio/examples/avr328p-ssd1306/src/ssd1306.rob b/platformio/examples/avr328p-ssd1306/src/ssd1306.rob index 3ed23a8..88aa0bf 100644 --- a/platformio/examples/avr328p-ssd1306/src/ssd1306.rob +++ b/platformio/examples/avr328p-ssd1306/src/ssd1306.rob @@ -34,11 +34,22 @@ type ssd1306 { MEM_ADDRESSING = 0x20, CHARGE_PUMP_REGULATOR = 0x8D, CHARGE_PUMP_ON = 0x14, + SET_PAGE_START_ADDR = 0xB0, + SET_COL_LO_NIBBLE = 0x00, + SET_COL_HI_NIBBLE = 0x10, NOP = 0xE3 } enum displayorientation {NORMAL, NORMAL_MIRRORED, UPSIDE_DOWN, UPSIDE_DOWN_MIRRORED} + int8 pages() { + return 64 / 8; + } + + int16 columns() { + return 128; + } + void init_display() { datacmd.mode(port_mode.output); reset.mode(port_mode.output); @@ -71,9 +82,6 @@ type ssd1306 { write_command(0x00); write_command(commands.SET_DISP_CLOCK); - - //FIXME on RobCmp: The warning here is due to write_command - // receiving a signed parameter. We need to implement/fix unsignedness write_command(0x80); write_command(commands.CHARGE_PUMP_REGULATOR); @@ -98,6 +106,14 @@ type ssd1306 { } } + void set_display_mode(bool inverted) { + if inverted { + write_command(commands.DISPLAY_MODE_INVERTED); + } else { + write_command(commands.DISPLAY_MODE_NORMAL); + } + } + void set_contrast(int8 c) { write_command(commands.SET_CONTRAST); write_command(c); @@ -105,13 +121,13 @@ type ssd1306 { void reset_display() { reset.set(true); - mcu.wait(3); + mmcu.wait_us(3); reset.set(false); - mcu.wait(3); + mmcu.wait_us(3); reset.set(true); } - void write_command(int8 c) { + void write_command(unsigned8 c) { datacmd.set(false); select.set(false); spi.write(c); @@ -124,4 +140,17 @@ type ssd1306 { spi.write(d); select.set(true); } + + void reset_cursor() { + write_command(commands.SET_PAGE_START_ADDR); + write_command(commands.SET_COL_HI_NIBBLE); + write_command(commands.SET_COL_LO_NIBBLE); + } + + void flip_power() { + write_command(powerstate.SLEEP); + mmcu.wait_ms(1000); + write_command(powerstate.ON); + mmcu.wait_ms(1000); + } } diff --git a/platformio/platform/boards/avr328p.json b/platformio/platform/boards/avr328p.json index 53a9486..2475f76 100644 --- a/platformio/platform/boards/avr328p.json +++ b/platformio/platform/boards/avr328p.json @@ -7,10 +7,31 @@ "debug": { "target_mcu": "atmega328p", "tools": { - "robcmp": { + "robcmp-led": { + "init_cmds": [ + "target remote $DEBUG_PORT", + "$LOAD_CMDS" + ], + "port": ":1234", + "server": { + "package": "toolchain-robcmp", + "executable": "bin/robcmp-simavr-debug" + } + }, + "robcmp-ssd1306": { + "init_cmds": [ + "target remote $DEBUG_PORT", + "$LOAD_CMDS" + ], + "port": ":1234", + "server": { + "package": "toolchain-robcmp", + "executable": "bin/robcmp-simavr-debug" + } + }, + "robcmp-hd44780": { "init_cmds": [ "target remote $DEBUG_PORT", - "$INIT_BREAK", "$LOAD_CMDS" ], "port": ":1234", diff --git a/platformio/platform/platform.py b/platformio/platform/platform.py index d36aef1..d5a6a11 100644 --- a/platformio/platform/platform.py +++ b/platformio/platform/platform.py @@ -43,12 +43,24 @@ def _add_default_debug_tools(self, board): debug["tools"] = {} if debug.get("target_mcu", ""): - debug["tools"]["robcmp"]["server"]["arguments"] = [ + debug["tools"]["robcmp-led"]["server"]["arguments"] = [ "-f", "$PROG_PATH", "-m", debug["target_mcu"], "-hw", "led", "-g" ] + debug["tools"]["robcmp-ssd1306"]["server"]["arguments"] = [ + "-f", "$PROG_PATH", + "-m", debug["target_mcu"], + "-hw", "ssd1306", + "-g" + ] + debug["tools"]["robcmp-hd44780"]["server"]["arguments"] = [ + "-f", "$PROG_PATH", + "-m", debug["target_mcu"], + "-hw", "hd44780", + "-g" + ] board.manifest["debug"] = debug return board diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index a22ee25..803b99f 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "BackLLVM.h" @@ -101,9 +102,9 @@ void print_llvm_ir(char opt_level) { } TargetOptions opt; - auto RM = optional(); auto targetMachine = Target->createTargetMachine(ai.triple, - ai.cpu, ai.features, opt, RM); + ai.cpu, ai.features, opt, Reloc::PIC_, + CodeModel::Small, CodeGenOptLevel::Aggressive); mainmodule->setDataLayout(targetMachine->createDataLayout()); mainmodule->setTargetTriple(ai.triple); @@ -153,6 +154,8 @@ void print_llvm_ir(char opt_level) { return; } + UpgradeDebugInfo(*mainmodule); + ModulePassManager modulePassManager; if (ol == OptimizationLevel::O0) modulePassManager = passBuilder.buildO0DefaultPipeline(ol); @@ -172,7 +175,7 @@ void print_llvm_ir(char opt_level) { targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, llvm::CGFT_ObjectFile); //targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, llvm::CGFT_AssemblyFile); pass_codegen.run(*mainmodule); - dest.flush(); + dest.close(); } else { // print IR to stdout mainmodule->print(outs(), nullptr); diff --git a/src/BuildTypes.h b/src/BuildTypes.h index dd6e1d5..775098b 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -148,6 +148,11 @@ class BuildTypes { return tinfo[tid].isInterface; } + bool isUserType(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isComplex && !tinfo[tid].isInterface; + } + bool isArray(DataType tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].arrayDimensions == 1; diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index 1ad4cf8..4fb5e1e 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -4,11 +4,7 @@ #include "BackLLVM.h" void DebugInfo::emitLocation(SourceLocation *s) { - if (!debug_info) - return; - if (!s) - return Builder->SetCurrentDebugLocation(DebugLoc()); - if (s->getLineNo() == 0) + if (!debug_info || !s || s->getLineNo() == 0) return; DIScope *scope; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 5034840..b4082b2 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -10,11 +10,10 @@ #include "BackLLVM.h" #include "UserType.h" #include "Program.h" +#include "Interface.h" extern Program *program; - - DataType FunctionCall::getDataType() { if (dt == BuildTypes::undefinedType) { @@ -38,7 +37,11 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock RobDbgInfo.emitLocation(this); string name = ident.getFullName(); - // check if it is a cast call: the function name is a primitive type, e.g., int8(x) + /* check if it is a constructor or cast call: + - cast if the function name is a type, e.g., int8(x), and the call has one argument + - constructor if the function name is a type and the call has no argument + */ + DataType adt = buildTypes->getType(name); if (adt != BuildTypes::undefinedType) { dt = adt; @@ -57,6 +60,7 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock Builder->SetInsertPoint(block); Value *var = leftValue->getLLVMValue(func); if (var == NULL) { + // is a new left var Builder->SetInsertPoint(allocblock); var = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, 0, leftValue->getName()); @@ -68,68 +72,50 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock vector args; args.push_back(var); - // call :init + // find the user type or interface Node *type = findSymbol(name); if (!type) return NULL; + // if calling a constructor of an interface, emit code to bind it + if (buildTypes->isInterface(type->getDataType())) { + dt = type->getDataType(); - Node *fsymbol = type->findMember("init"); - if (!fsymbol) { - //extern map>> injections; - // se presente no injection - // consultar b3, se não criado criar um - // new Scalar("", new FC("b3", new ParamsCall())) - // return new Load("") - Node *scope = leftValue->getScope(); UserType *parent= dynamic_cast(scope); - - if (parent == NULL) { - return NULL; - } - - const string toInjection = parent->getName() + "." + leftValue->getName(); - if (injections.count(toInjection) == 0) { - return NULL; + const string toInjection = parent ? + parent->getName() + "." + leftValue->getName() : + leftValue->getName(); + + const string injectFuncName = ":get_injection_for_" + toInjection; + Node *funcNode = findSymbol(injectFuncName); + FunctionBase *funcDecl = dynamic_cast(funcNode); + if (!funcDecl) { + funcDecl = new FunctionDecl(dt, injectFuncName, new FunctionParams()); + funcDecl->setReturnIsPointer(true); + funcDecl->setScope(program); + funcDecl->generate(NULL, NULL, global_alloc); + program->addSymbol(funcDecl); } + return Builder->CreateCall(funcDecl->getLLVMFunction()); + } else { + // call the init constructor + Node *fsymbol = type->findMember("init"); + assert(fsymbol && "the init method for the type must exists"); + + FunctionBase *initfunc = dynamic_cast(fsymbol); + Builder->SetInsertPoint(block); - const string variableName = ":injectionName__" + injections[toInjection].first; - // if (map_injections.count(variableName) == 0) { - // Variable *injectionVariable = new Scalar(variableName, new FunctionCall(injections[toInjection].first, new ParamsCall())); - // map_injections[variableName] = injectionVariable; - - // // TODO: Verificar se a função main já foi gerada - // // injectionVariable->gene - // program->addChild(injectionVariable); - // program->addSymbol(injectionVariable); - // } - - Load ld(variableName); - - ld.setScope(program); - - // change FunctionCall datatype to the datatype of the injected var - dt = ld.getDataType(); - Node *lsymbol = findSymbol(leftValue->getName()); - lsymbol->setDataType(dt); - - return ld.generate(func, block, allocblock); - } - - FunctionBase *initfunc = dynamic_cast(fsymbol); - - Builder->SetInsertPoint(block); + if (initfunc->needsParent()) { + Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); + Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + args.push_back(ptr); + } - if (initfunc->needsParent()) { - Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); - Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); - args.push_back(ptr); + CallInst *c = Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); + return NULL; } - - CallInst *c = Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); - return NULL; } } @@ -145,6 +131,12 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock if (fsymbol == NULL) { yyerrorcpp("Symbol " + name + " is not a function.", this); return NULL; + } else if (ident.isComplex()) { + Node *stem = ident.getStem().getSymbol(getScope()); + if (Interface *intf = dynamic_cast(stem)) { + yyerrorcpp("Can not call an interface function.", this); + return NULL; + } } if (fsymbol->getNumCodedParams() != parameters->getNumParams()) { @@ -241,6 +233,11 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock if (stemSymbol->isPointerToPointer()) stem = Builder->CreateLoad(stem->getType()->getPointerTo(), stem, "defer"); args.push_back(stem); + } else if (fsymbol->getThisArgDt() != BuildTypes::undefinedType) { + // calling a function of the type itself, without stem + Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); + Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + args.push_back(ptr); } ArrayRef argsRef(args); @@ -249,10 +246,23 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock Value *vfunc = symbol->getLLVMValue(func); Function *cfunc = dyn_cast(vfunc); - // when calling an interface function, generate a complete name - // to enable injection at link time (symbol name substitution) + // symbol->getLLVMValue above can emit another location (preGenerate of the + // function being called), so we emit location again + RobDbgInfo.emitLocation(this); + + // when calling an interface function, we generate a larger function name, + // including the type name. This enable binding the correct function implementattion + // at the end of the build, according to the given hardware .spec if (stemSymbol && buildTypes->isInterface(stemSymbol->getDataType())) { - string inject_name = stemSymbol->getScope()->getName() + ":"; + string inject_name; + + if (UserType *ut = dynamic_cast(stemSymbol->getScope())) + inject_name = stemSymbol->getScope()->getName() + ":"; + else if (buildTypes->isUserType(stemSymbol->getScope()->getDataType())) { + inject_name = buildTypes->name(stemSymbol->getScope()->getDataType()); + inject_name.append(":"); + } + inject_name.append(stemSymbol->getName() + ":"); inject_name.append(ident.getLastName()); Function *intf_cfunc = mainmodule->getFunction(inject_name); diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 9eaf9ee..6e09210 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -34,6 +34,14 @@ bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { return valid; } +void FunctionBase::addParentArgument(DataType dt) { + parentArgDt = dt; + Variable *fp = new Variable(":parent", dt); + fp->setScope(this); + parameters->append(fp); + symbols[fp->getName()] = fp; +} + Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocblock) { Node *symbol = findSymbol(name); @@ -48,6 +56,9 @@ Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocbloc return NULL; Type *xtype = buildTypes->llvmType(dt); + if (returnIsPointer) + xtype = xtype->getPointerTo(); + FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, codeAddrSpace, getFinalName(), mainmodule); nfunc->setDSOLocal(true); diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 60a0155..d9f4967 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -13,7 +13,11 @@ class FunctionBase: public NamedNode { bool declaration = true; bool constructor = false; bool external = false; + bool returnIsPointer = false; DataType thisArgDt = BuildTypes::undefinedType; + Value *thisArg = NULL; + DataType parentArgDt = BuildTypes::undefinedType; + Value *parentArg = NULL; string prefixName; bool validateAndGetArgsTypes(std::vector &args); @@ -90,10 +94,18 @@ class FunctionBase: public NamedNode { return declaration; } + void setDeclaration(bool d) { + declaration = d; + } + bool isConstructor() { return constructor; } + void setConstructor(bool c) { + constructor = c; + } + void setExternal(bool e) { external = e; } @@ -102,12 +114,34 @@ class FunctionBase: public NamedNode { return external; } + void setReturnIsPointer(bool r) { + returnIsPointer = r; + } + void addThisArgument(DataType dt); DataType getThisArgDt() const { return thisArgDt; } + void addParentArgument(DataType dt); + + Value *getThisArg() const { + return thisArg; + } + + Value *getParentArg() const { + return parentArg; + } + + DataType getParentArgDt() const { + return parentArgDt; + } + + virtual bool needsParent() { + return parentArg != NULL; + } + void setPrefixName(const string& prefix) { prefixName = prefix; } @@ -118,10 +152,6 @@ class FunctionBase: public NamedNode { else return prefixName + ":" + name; } - - virtual bool needsParent() { - return false; - } }; class FunctionDecl: public FunctionBase { diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 0026ec2..a2f7d4f 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -26,6 +26,9 @@ bool FunctionImpl::preGenerate() { } Type *xtype = buildTypes->llvmType(dt); + if (returnIsPointer) + xtype = xtype->getPointerTo(); + if (fsymbol) { validateImplementation(fsymbol); func = mainmodule->getFunction(name); @@ -65,9 +68,7 @@ bool FunctionImpl::preGenerate() { func->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); func->setCallingConv(CallingConv::C); - DIFile *funit; - DISubprogram *sp; - if (debug_info) { + if (debug_info && !declaration) { funit = DBuilder->createFile(RobDbgInfo.cunit->getFilename(), RobDbgInfo.cunit->getDirectory()); DIScope *fcontext = funit; sp = DBuilder->createFunction(fcontext, getFinalName(), StringRef(), funit, this->getLineNo(), @@ -123,6 +124,9 @@ bool FunctionImpl::preGenerate() { Idx++; } + if (debug_info) + RobDbgInfo.pop_scope(); + return true; } @@ -131,11 +135,16 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo if (!preGenerated) { if (!preGenerate()) return NULL; - } - - if (isExternal()) + } + + if (isExternal() || isDeclaration()) //can be declaration when came from USEparser return NULL; + if (debug_info) { + RobDbgInfo.push_scope(funit, sp); + RobDbgInfo.emitLocation(this); + } + Value *last_block = generateChildren(this, fblock, falloc); if (!last_block) last_block = fblock; @@ -208,14 +217,6 @@ bool FunctionImpl::validateImplementation(FunctionDecl *decl) { return result; } -void FunctionImpl::addParentArgument(DataType dt) { - parentArgDt = dt; - Variable *fp = new Variable(":parent", dt); - fp->setScope(this); - parameters->append(fp); - symbols[fp->getName()] = fp; -} - void FunctionImpl::accept(Visitor& v) { v.visit(*this); } diff --git a/src/FunctionImpl.h b/src/FunctionImpl.h index bc3897b..921f7d2 100644 --- a/src/FunctionImpl.h +++ b/src/FunctionImpl.h @@ -9,13 +9,12 @@ class Visitor; class FunctionImpl: public FunctionBase { private: SourceLocation endfunction; - Value *thisArg = NULL; - DataType parentArgDt = BuildTypes::undefinedType; - Value *parentArg = NULL; bool preGenerated = false; BasicBlock *falloc = NULL; BasicBlock *fblock = NULL; + DIFile *funit; + DISubprogram *sp; bool preGenerate(); public: @@ -28,25 +27,14 @@ class FunctionImpl: public FunctionBase { bool validateImplementation(FunctionDecl *decl); - void addParentArgument(DataType dt); - - Value *getThisArg() const { - return thisArg; - } - - Value *getParentArg() const { - return parentArg; - } + virtual void accept(Visitor& v) override; - DataType getParentArgDt() const { - return parentArgDt; - } + virtual Value *getLLVMValue(Node *) override; - virtual bool needsParent() override { - return parentArg != NULL; + virtual Function *getLLVMFunction() override { + if (!preGenerated) + preGenerate(); + return func; } - virtual void accept(Visitor& v) override; - - virtual Value *getLLVMValue(Node *) override; }; diff --git a/src/Interface.cpp b/src/Interface.cpp index de52828..33af603 100644 --- a/src/Interface.cpp +++ b/src/Interface.cpp @@ -3,7 +3,6 @@ #include "UserType.h" #include "FunctionImpl.h" #include "FunctionDecl.h" -#include "Int1.h" void Interface::createDataType() { // TRY: prevent opaque type diff --git a/src/Language.y b/src/Language.y index 1b1ab69..a1ebf6c 100644 --- a/src/Language.y +++ b/src/Language.y @@ -233,8 +233,8 @@ simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array); $ simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } bind : TOK_BIND ident_or_xident[id] TOK_TO ident_or_xident[to] bind_scope[scope] ';' { - //extern map>> injections; - // injections[$id].push_back(make_pair(string($to), BindScope($scope))); + injections.insert({$to, make_pair(string($id), BindScope($scope))}); + $$ = NULL; } bind_scope : TOK_SINGLETON { $$ = bs_singleton; } diff --git a/src/LanguageUse.y b/src/LanguageUse.y index dccde84..68201a7 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -105,6 +105,7 @@ function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, std::move(stmts), @ef); func->setExternal(true); + func->setDeclaration(true); func->setLocation(@type); $$ = func; } diff --git a/src/Load.cpp b/src/Load.cpp index e4f6613..ee5dce1 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -76,6 +76,12 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl if (stem->hasQualifier(qvolatile)) symbol->setQualifier(qvolatile); + + // when the new var will be a reference to expr; + // we change its scope to the scope of expr (stem) + // this is needed by injection + if (leftValue) + leftValue->setScope(stem, true); // TODO: When accessing a.x.func(), need to load a and gep x //Load loadstem(ident.getStem()); diff --git a/src/Node.cpp b/src/Node.cpp index d54556e..611f872 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -74,8 +74,8 @@ map const& Node::getSymbols() { return symbols; } -void Node::setScope(Node *s) { - if (scope != NULL) +void Node::setScope(Node *s, bool replace) { + if (scope != NULL && !replace) assert(scope == NULL && "node already has a scope"); scope = s; } diff --git a/src/Node.h b/src/Node.h index 61fc916..56a19b7 100644 --- a/src/Node.h +++ b/src/Node.h @@ -49,7 +49,7 @@ class Node : public SourceLocation { return scope; } - virtual void setScope(Node *s); + virtual void setScope(Node *s, bool replace = false); virtual Node* findSymbol(const string& name, bool recursive = true); diff --git a/src/Program.cpp b/src/Program.cpp index 2c768d0..1604acd 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -3,7 +3,10 @@ #include "HeaderGlobals.h" #include "SymbolizeTree.h" #include "BackLLVM.h" -#include "NullConst.h" +#include "ZeroInit.h" +#include "Return.h" +#include "Load.h" +#include "BuildTypes.h" #include Program::Program() { @@ -116,29 +119,137 @@ Value *Program::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo } void Program::generateInjectionSetup() { - // create a function called :injections, to setup global injection vars with - // their singleton instances - FunctionParams *fp = new FunctionParams(); - FunctionImpl *finject = new FunctionImpl((DataType)tvoid, ":injections", fp, - vector(), *this->getLoct(), true); - vector globals; + // a function to init global vars for singleton injections + FunctionImpl *funcInitGlobals = new FunctionImpl((DataType)tvoid, ":injections_init", + new FunctionParams(), vector(), *this->getLoct(), false); + funcInitGlobals->setScope(this); + addSymbol(funcInitGlobals); + + /* create a function for each injection, named :get_injection_for_[to]: + function :get_injection_for_[to] { + static instance = type() + return instance; + } + */ for (auto &[key, itype] : injections) { - const string variableName = ":injectionName__" + itype.first; - FunctionCall *fc = new FunctionCall(itype.first, new ParamsCall()); - fc->setScope(finject); - Variable *injectionVariable = new Scalar(variableName, fc); + Identifier to(key); + Identifier bind(itype.first); + BindScope scope(itype.second); - globals.push_back(injectionVariable); - } + // injection validation + Identifier bindSubtypes = regex_replace(bind.getFullName(), regex("\\."), ":"); //internal types use : + Node *injectType = bindSubtypes.getSymbol(this); + if (!injectType) { + yyerrorcpp(string_format("Injection symbol %s not found.", + bind.getFullName().c_str()), this); + continue; + } + + DataType destinationTy = BuildTypes::undefinedType; + string destinationTyName; + UserType *bindUserTy = dynamic_cast(injectType); + if (!bindUserTy) { + yyerrorcpp(string_format("Bind symbol %s is not of a bindable type.", + bind.getFullName().c_str()), this); + continue; + } else { + Node *nodeTo = to.getSymbol(this); + if (!nodeTo) { + yyerrorcpp(string_format("Injection destination %s not found.", + bind.getFullName().c_str()), this); + continue; + } else { + destinationTy = nodeTo->getDataType(); + destinationTyName = buildTypes->name(destinationTy); + if (!bindUserTy->implementsInterface(destinationTyName)) { + yyerrorcpp(string_format("Bind symbol %s does not implements %s.", + bind.getFullName().c_str(), destinationTyName.c_str()), this); + continue; + } + } + } + + // generate injection stuff + + const string functionName = ":get_injection_for_" + to.getFullName(); + FunctionImpl *finject = new FunctionImpl(destinationTy, functionName, + new FunctionParams(), vector(), *this->getLoct(), false); + finject->setReturnIsPointer(true); + finject->setScope(this); + + if (scope == bs_singleton) { + string globalVarName; + if (bind.isComplex()) { + globalVarName = ":var_injection_for_" + bind.getFullName(); + } else { + globalVarName = ":var_injection_for_" + bind.getFullName(); + Node *var = findSymbol(globalVarName); + if (!var) { + // alloc the global var + ZeroInit *nc = new ZeroInit(injectType->getDataType()); + Scalar *svar = new Scalar(globalVarName, nc); + svar->setScope(this); + addSymbol(svar); + svar->generate(NULL, NULL, global_alloc); + var = svar; + + FunctionCall *fc = new FunctionCall(bind.getFullName(), new ParamsCall()); + Scalar *sc = new Scalar(globalVarName, fc); + fc->setScope(funcInitGlobals); + sc->setScope(funcInitGlobals); + funcInitGlobals->addChild(sc); + } + } + + Load *load = new Load(globalVarName); + Return *ret = new Return(load); + ret->setScope(finject); + load->setScope(finject); + finject->addChild(ret); + finject->generate(NULL, NULL, global_alloc); - for(auto &g : globals) { - finject->addChild(g); - g->setScope(finject); + } else { // bs_transient + assert(false && "TODO: implement bs_transient scope."); + } + + // generate injection function aliases + for(const auto & [key, symbol] : bindUserTy->getSymbols()) { + if (FunctionImpl *impl = dynamic_cast(symbol)) { + Identifier destTyIntfName = destinationTyName; + Node *destIntf = destTyIntfName.getSymbol(this); + if (destIntf && destIntf->findMember(symbol->getName())) { + // is a interface member implementation, let add an alias to it + string to_name = regex_replace(to.getFullName(), regex("\\."), ":") + ":" + symbol->getName(); + Function *implFunc = impl->getLLVMFunction(); + + Function *aliasFunc = Function::Create(implFunc->getFunctionType(), Function::ExternalLinkage, + codeAddrSpace, to_name, mainmodule); + aliasFunc->setDSOLocal(true); + aliasFunc->setCallingConv(CallingConv::C); + + auto fblock = BasicBlock::Create(global_context, "", aliasFunc); + Builder->SetInsertPoint(fblock); + + vector args; + for(auto& arg : aliasFunc->args()) { + //Value *alloc = Builder->CreateAlloca(arg.getType()); + //Value *store = Builder->CreateStore(&arg, alloc); + //Value *load = Builder->CreateLoad(arg.getType(), alloc); + args.push_back(&arg); + } + + Value *call = Builder->CreateCall(implFunc, args); + if (call->getType()->isVoidTy()) + Builder->CreateRetVoid(); + else + Builder->CreateRet(call); + } + } + } } - finject->setScope(program); - program->addSymbol(finject); - finject->generate(NULL, NULL, global_alloc); + + funcInitGlobals->generate(NULL, NULL, global_alloc); } void Program::generate() { @@ -152,22 +263,22 @@ void Program::generate() { PrintAstVisitor(fs).visit(p); fs.close();*/ - // generate the program! + Node *mainFunc = NULL; + // generate the program! for(auto n: children()) { if (FunctionImpl *func = dynamic_cast(n)) { - if (injections.size() > 0 && (func->getName() == "main" || func->getName() == "__main")) { - generateInjectionSetup(); - FunctionCall *fc = new FunctionCall(":injections", new ParamsCall()); - fc->setScope(func); - func->addChild(fc, true); + if (func->getName() == "main" || func->getName() == "__main") { + // generate main function after all others + mainFunc = n; + continue; } } n->generate(NULL, NULL, global_alloc); // if n is a UserType, there is a injection for it? - if (UserType *ut = dynamic_cast(n)) { + /*if (UserType *ut = dynamic_cast(n)) { for (auto &[key, itype] : injections) { if (itype.first == ut->getName()) { const string variableName = ":injectionName__" + itype.first; @@ -181,9 +292,20 @@ void Program::generate() { break; //TODO: When implementing transient injection, change here. } } - } + }*/ } + if (injections.size() > 0) { + generateInjectionSetup(); + + FunctionCall *fc = new FunctionCall(":injections_init", new ParamsCall()); + fc->setScope(mainFunc); + mainFunc->addChild(fc, true); + } + + if (mainFunc) + mainFunc->generate(NULL, NULL, global_alloc); + if (debug_info) DBuilder->finalize(); } diff --git a/src/Return.cpp b/src/Return.cpp index abd21af..8f47d2f 100644 --- a/src/Return.cpp +++ b/src/Return.cpp @@ -10,14 +10,18 @@ Value *Return::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc if (node) { ret = node->generate(func, block, allocblock); if (ret) { - DataType sdt = node->getDataType(); - if (buildTypes->isComplex(sdt)) { - // defer the pointer before returning - Type *ty = buildTypes->llvmType(sdt); - ret = Builder->CreateLoad(ty, ret, false, "deref"); + Type *retTy = ret->getType(); + Type *funcTy = func->getLLVMFunction()->getReturnType(); + if (retTy != funcTy) { + DataType sdt = node->getDataType(); + if (buildTypes->isComplex(sdt)) { + // defer the pointer before returning + Type *ty = buildTypes->llvmType(sdt); + ret = Builder->CreateLoad(ty, ret, false, "deref"); + } + + ret = Coercion::Convert(ret, funcTy, block, this); } - Type *retty = func->getLLVMFunction()->getReturnType(); - ret = Coercion::Convert(ret, retty, block, this); } } return Builder->CreateRet(ret); diff --git a/src/Scalar.cpp b/src/Scalar.cpp index b8648c7..3d36a4f 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -75,8 +75,11 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc if (symbol->hasQualifier(qconst)) ret = alloc = exprvc; else { - GlobalVariable *gv = new GlobalVariable(*mainmodule, buildTypes->llvmType(dt), - false, GlobalValue::InternalLinkage, exprvc, name); + Type *gty = buildTypes->llvmType(dt); + if (expr->isPointerToPointer()) + gty = gty->getPointerTo(); + GlobalVariable *gv = new GlobalVariable(*mainmodule, gty, false, + GlobalValue::InternalLinkage, exprvc, name); gv->setDSOLocal(true); ret = alloc = gv; diff --git a/src/UserType.cpp b/src/UserType.cpp index ac37ae1..1a51dfc 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -3,10 +3,10 @@ #include "HeaderGlobals.h" #include "Interface.h" #include "FunctionImpl.h" +#include "FunctionDecl.h" #include "FunctionParams.h" #include "FunctionCall.h" #include "ParamsCall.h" -#include "Program.h" #include "Variable.h" #include "Visitor.h" #include "Enum.h" @@ -150,13 +150,19 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all // generate init function/constructor FunctionParams *fp = new FunctionParams(); - FunctionImpl *finit = new FunctionImpl((DataType)tvoid, "init", fp, - std::move(fields), *this->getLoct(), true); + FunctionBase *finit; + if (declaration) { + finit = new FunctionDecl((DataType)tvoid, "init", fp); + } else { + finit = new FunctionImpl((DataType)tvoid, "init", fp, + std::move(fields), *this->getLoct(), true); + } finit->addThisArgument(dt); if (parent) finit->addParentArgument(parent->getDataType()); finit->setPrefixName(getName()); finit->setExternal(declaration); + finit->setConstructor(true); finit->generate(func, block, allocblock); /* set function parameters before generate diff --git a/src/UserType.h b/src/UserType.h index 88fd18e..37a5373 100644 --- a/src/UserType.h +++ b/src/UserType.h @@ -50,4 +50,12 @@ class UserType: public NamedNode { return bitWidth; } + bool implementsInterface(const string& intf) { + return std::find(implements.begin(), implements.end(), intf) != implements.end(); + } + + DataType getDataType() override { + createDataType(); + return dt; + } }; diff --git a/src/Variable.cpp b/src/Variable.cpp index be2cbee..d95cf67 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -13,8 +13,17 @@ Value *Variable::getLLVMValue(Node *stem) { if (func && func->getThisArg()) { // generating a function of a type: get the gep on :this or :parent parameters Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); - Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); - alloc = Builder->CreateStructGEP(thisTy, ptr, gepidx, "gepthis"); + Value *thisptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + if (!stem->getScope() || this->getScope() == stem->getScope()) { + // in the global or same scope, defer :this and gep the field + alloc = Builder->CreateStructGEP(thisTy, thisptr, gepidx, "gepthis"); + } else { + // in distinct scopes, access :parent (gep 0) in :this and gep the field + Type *parentTy = buildTypes->llvmType(this->getScope()->getDataType()); + Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, 0, "gepthis"); + Value *parentptr = Builder->CreateLoad(parentTy->getPointerTo(), parentAlloc, "derefparent"); + alloc = Builder->CreateStructGEP(parentTy, parentptr, gepidx, "gepparent"); + } } else { // accessing a var of a user type: get the gep in the scope (user type) of the scalar Type *udt = buildTypes->llvmType(stem->getDataType()); diff --git a/src/NullConst.h b/src/ZeroInit.h similarity index 57% rename from src/NullConst.h rename to src/ZeroInit.h index 78282ed..8847105 100644 --- a/src/NullConst.h +++ b/src/ZeroInit.h @@ -5,14 +5,15 @@ #include "HeaderGlobals.h" #include "Node.h" -class NullConst: public Node { +class ZeroInit: public Node { public: - NullConst(DataType dt) { + ZeroInit(DataType dt) { this->dt = dt; } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - return ConstantPointerNull::get(PointerType::get(buildTypes->llvmType(dt), 0)); + return ConstantAggregateZero::get(buildTypes->llvmType(dt)); + //return ConstantPointerNull::get(buildTypes->llvmType(dt)->getPointerTo()); } virtual bool isConstExpr() override { From 6b657e9a2e43f612bc3af093642b00585c9e5dc4 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 9 May 2024 23:38:34 -0300 Subject: [PATCH 050/117] Fixes for llvm 18: ConstantExpr methods is being unsupported. --- CMakeLists.txt | 2 +- macbuild | 4 ++-- src/BackLLVM.cpp | 9 +++++---- src/BinaryOp.cpp | 22 ---------------------- src/Coercion.cpp | 30 ++++++------------------------ src/Scalar.cpp | 6 +++--- test/general/constant-fold.rob | 10 ++++++++++ 7 files changed, 27 insertions(+), 56 deletions(-) create mode 100644 test/general/constant-fold.rob diff --git a/CMakeLists.txt b/CMakeLists.txt index d10b261..0d6be1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.0) +cmake_minimum_required(VERSION 3.20.0) cmake_policy(SET CMP0054 NEW) set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -fno-exceptions") diff --git a/macbuild b/macbuild index fb18575..374cb2c 100755 --- a/macbuild +++ b/macbuild @@ -1,5 +1,5 @@ -CXX=/usr/local/robllvm/bin/clang++ -CC=/usr/local/robllvm/bin/clang +CXX=/usr/local/opt/llvm/bin/clang++ +CC=/usr/local/opt/llvm/bin/clang export CXX export CC cmake -DCMAKE_BUILD_TYPE="Debug" .. diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 803b99f..3b139a8 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -16,10 +16,11 @@ #include #include #include -#include #include -#include +#include +#include #include +#include #include #include #include @@ -172,8 +173,8 @@ void print_llvm_ir(char opt_level) { exit(1); } legacy::PassManager pass_codegen; - targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, llvm::CGFT_ObjectFile); - //targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, llvm::CGFT_AssemblyFile); + targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, CodeGenFileType::ObjectFile); + //targetMachine->addPassesToEmitFile(pass_codegen, dest, nullptr, CodeGenFileType::AssemblyFile); pass_codegen.run(*mainmodule); dest.close(); } else { diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index 68bad89..84e4c58 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -95,28 +95,6 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, llvmop = opflt; } - Constant *c0 = dyn_cast(lhs); - Constant *c1 = dyn_cast(rhs); - if (c0 && c1) { - switch (getOperator()) { - case '+': return ConstantExpr::getAdd(c0, c1); - case '-': return ConstantExpr::getSub(c0, c1); - case '*': return ConstantExpr::getMul(c0, c1); - - case TOK_OR: - case '|': return ConstantExpr::getOr(c0, c1); - - case TOK_AND: - case '&': return ConstantExpr::getAnd(c0, c1); - - case '^': return ConstantExpr::getXor(c0, c1); - case TOK_LSHIFT: return ConstantExpr::getShl(c0, c1); - case TOK_RSHIFT: return ConstantExpr::getLShr(c0, c1); - default: - break; - } - } - RobDbgInfo.emitLocation(this); return Builder->CreateBinOp(llvmop, lhs, rhs, "binop"); } diff --git a/src/Coercion.cpp b/src/Coercion.cpp index b10b1d5..23974c2 100644 --- a/src/Coercion.cpp +++ b/src/Coercion.cpp @@ -29,34 +29,22 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati if (ty != destty){ //Float to Integer if (ty->isFloatingPointTy() && destty->isIntegerTy()){ - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getFPToSI(c, destty); - else - r = Builder->CreateFPToSI(v, destty, "fptosi"); + r = Builder->CreateFPToSI(v, destty, "fptosi"); if (!isCast) yywarncpp("Float point converted to integer.", loc); } //Integer to Float else if (destty->isFloatingPointTy() && ty->isIntegerTy()){ - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getSIToFP(c, destty); - else - r = Builder->CreateSIToFP(v, destty, "sitofp"); + r = Builder->CreateSIToFP(v, destty, "sitofp"); } //Floating point to Floating point else if (ty->isFloatingPointTy() && destty->isFloatingPointTy()) { unsigned tybw = GetFloatingPointBitwidth(ty); unsigned dtybw = GetFloatingPointBitwidth(destty); if (dtybw > tybw) - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getFPExtend(c, destty); - else - r = Builder->CreateFPExt(v, destty, "fpext"); + r = Builder->CreateFPExt(v, destty, "fpext"); else if (dtybw < tybw) { - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getFPTrunc(c, destty); - else - r = Builder->CreateFPTrunc(v, destty, "fptrunc"); + r = Builder->CreateFPTrunc(v, destty, "fptrunc"); if (!isCast) yywarncpp("Float point value truncated.", loc); } @@ -66,20 +54,14 @@ Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocati unsigned wty = ty->getIntegerBitWidth(); unsigned wdestty = destty->getIntegerBitWidth(); if (wty > wdestty){ - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getTrunc(c, destty); - else - r = Builder->CreateTrunc(v, destty, "trunc"); + r = Builder->CreateTrunc(v, destty, "trunc"); if (!isCast) { yywarncpp(string_format("Integer value truncated from int%d to int%d.", wty, wdestty), loc); } } else if (wty < wdestty) { - if (Constant *c = dyn_cast(v)) - r = ConstantExpr::getSExt(c, destty); - else - r = Builder->CreateSExt(v, destty, "sext"); + r = Builder->CreateSExt(v, destty, "sext"); } } else { diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 3d36a4f..5189c65 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -151,7 +151,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc // Prepare the mask unsigned bitWidth = buildTypes->bitWidth(symbol->getDataType()); Constant *allone = Constant::getAllOnesValue(Type::getIntNTy(global_context, bitWidth)); - Constant *ones = ConstantExpr::getZExt(allone, req_eq_ty); + Value *ones = Builder->CreateZExt(allone, req_eq_ty); // Coerce the rvalue to the req size exprv = Coercion::Convert(exprv, req_eq_ty, block, expr); @@ -160,10 +160,10 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc unsigned fieldStartBit = reg->getFieldStartBit(symbol); if (fieldStartBit > 0) { Constant *shiftl = ConstantInt::get(req_eq_ty, fieldStartBit); - ones = ConstantExpr::getShl(ones, shiftl); + ones = Builder->CreateShl(ones, shiftl); exprv = Builder->CreateShl(exprv, shiftl, "shift"); } - Constant *mask = ConstantExpr::getNot(ones); + Value *mask = Builder->CreateNot(ones); // Apply mask, than or Value *vaftermask = Builder->CreateAnd(v, mask, "mask"); diff --git a/test/general/constant-fold.rob b/test/general/constant-fold.rob new file mode 100644 index 0000000..676cabd --- /dev/null +++ b/test/general/constant-fold.rob @@ -0,0 +1,10 @@ + +a = (10 + 15 + 17.6) << 3; + +int8 main() { + if a == (10 + 15 + 17.6) << 3 { + return 0; + } else { + return 1; + } +} \ No newline at end of file From 5f2f5697856de5c9f9f2a1f152c58c494ec1041e Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 23 May 2024 18:51:19 -0300 Subject: [PATCH 051/117] Fix constant fold test for llvm18: unsupported << operator --- test/general/constant-fold.rob | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/general/constant-fold.rob b/test/general/constant-fold.rob index 676cabd..a082f26 100644 --- a/test/general/constant-fold.rob +++ b/test/general/constant-fold.rob @@ -1,10 +1,10 @@ -a = (10 + 15 + 17.6) << 3; +a = (10 + 15 + 17.6) * 3; int8 main() { - if a == (10 + 15 + 17.6) << 3 { + if a == (10 + 15 + 17.6) * 3 { return 0; } else { return 1; } -} \ No newline at end of file +} From 7377f66b8927998afb2c336fc69c1d3d6d835b5a Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 23 May 2024 20:03:18 -0300 Subject: [PATCH 052/117] Add signal.h for linux build and bump toolchain to llvm-18 tools --- platformio/toolchain-robcmp/Makefile | 12 ++++++------ src/main.cpp | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/platformio/toolchain-robcmp/Makefile b/platformio/toolchain-robcmp/Makefile index b162636..1d72ca9 100644 --- a/platformio/toolchain-robcmp/Makefile +++ b/platformio/toolchain-robcmp/Makefile @@ -1,14 +1,14 @@ -LLVM_OBJCOPY=$(shell which llvm-objcopy-16) +LLVM_OBJCOPY=$(shell which llvm-objcopy-18) ifeq ($(LLVM_OBJCOPY),) LLVM_OBJCOPY=$(shell which llvm-objcopy) endif -LLVM_LD=$(shell which ld.lld-16) +LLVM_LD=$(shell which ld.lld-18) ifeq ($(LLVM_LD),) LLVM_LD=$(shell which ld.lld) endif -LLVM_SIZE=$(shell which llvm-size-16) +LLVM_SIZE=$(shell which llvm-size-18) ifeq ($(LLVM_SIZE),) LLVM_SIZE=$(shell which llvm-size) endif @@ -79,9 +79,9 @@ package.json: package-orig.json ../toolchain-robcmp-${suffix}-${version}.tar.gz: package.json for f in $(TOOLS); do cp $$f bin; done; for f in $(LIBS); do cp $$f lib; done; - if [ -f bin/ld.lld-16 ]; then cd bin && ln -s ld.lld-16 ld.lld; fi - if [ -f bin/llvm-objcopy-16 ]; then cd bin && ln -s llvm-objcopy-16 llvm-objcopy; fi - tar cfz $@ $^ bin lib share + if [ -f bin/ld.lld-18 ]; then cd bin && ln -s ld.lld-18 ld.lld; fi + if [ -f bin/llvm-objcopy-18 ]; then cd bin && ln -s llvm-objcopy-18 llvm-objcopy; fi + tar cfz $@ $^ bin lib clean: rm -rf bin lib *.tar.gz package.json diff --git a/src/main.cpp b/src/main.cpp index 0424efc..618b613 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,6 +19,7 @@ int specparse(yyscan_t scanner); #include #include +#include void SIGSEGV_handler(int sig) { void *array[10]; size_t size; From f0344932f7f9de68a4b1de5871d7221c5258bb77 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 29 May 2024 11:13:42 -0300 Subject: [PATCH 053/117] Fix test execution on Ubuntu --- test/general/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/general/Makefile b/test/general/Makefile index 114c03b..60368d6 100644 --- a/test/general/Makefile +++ b/test/general/Makefile @@ -38,9 +38,13 @@ out/%.ll : %.rob ${ROBCMP} Makefile %.tt : %.rob @-./runtest.sh $< $(patsubst %.rob,out/%,$<) -ifeq ($(OS), Msys) % : %.o +ifeq ($(OS), Msys) ${LD} -e __main $< -o $@ +else ifeq ($(OS), Darwin) + ${CC} $< -o $@ +else + ${CC} -no-pie $< -o $@ endif test: ${ALL_TT} From 750a1595a034fb333d168357d8e3c865d1b4e0cf Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 12 Jun 2024 09:18:34 -0300 Subject: [PATCH 054/117] Add missing memcpy function in assembly and small fixes on linking. --- lib/avr328p.rob | 7 +++---- lib/avr5.S | 24 ++++++++++++++++++++++++ lib/avr5.ld | 31 +++++++++++++++++++++---------- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/lib/avr328p.rob b/lib/avr328p.rob index 480a268..f393772 100644 --- a/lib/avr328p.rob +++ b/lib/avr328p.rob @@ -9,10 +9,6 @@ void __do_copy_data(); void __do_clear_bss(); - void __default_irq() { - asm "reti"; - } - void __delay_us() { asm "ldi r18, 5"; asm "__delay_ms_loop: dec r18"; @@ -53,6 +49,9 @@ asm "rjmp __default_irq"; asm "rjmp __default_irq"; + asm "__default_irq:"; + asm "reti"; + asm "__init:"; // clear r1 (zero reg) asm "clr r1"; diff --git a/lib/avr5.S b/lib/avr5.S index 0372a50..c469ce1 100644 --- a/lib/avr5.S +++ b/lib/avr5.S @@ -361,3 +361,27 @@ __do_clear_bss_start: ret ENDF __do_clear_bss + +/* memset function for avr, based on avr libc */ +#define dest_hi r25 +#define dest_lo r24 +#define val_lo r22 +#define len_hi r21 +#define len_lo r20 + +DEFUN memset + movw XL, dest_lo + sbrs len_lo, 0 + rjmp .L_memset_start + rjmp .L_memset_odd +.L_memset_loop: + st X+, val_lo +.L_memset_odd: + st X+, val_lo +.L_memset_start: + subi len_lo, lo8(2) + sbci len_hi, hi8(2) + brcc .L_memset_loop + ret +ENDF memset + diff --git a/lib/avr5.ld b/lib/avr5.ld index 1abad0e..951550a 100644 --- a/lib/avr5.ld +++ b/lib/avr5.ld @@ -7,22 +7,22 @@ OUTPUT_ARCH(avr:5) SECTIONS { - .text : AT (0x0) { - _start__vectors = .; + .text : { + _start__vectors = .; KEEP(*(.vectors)) . = ALIGN(2); _end_vectors = .; _stext = .; - *(.progmem*) + *(.progmem*) . = ALIGN(2); *(.text) . = ALIGN(2); *(.text.*) - . = ALIGN(2); - _etext = . ; - } + . = ALIGN(2); + _etext = . ; + } > text - .data : AT (ADDR(.text) + SIZEOF(.text)) { + .data : { PROVIDE (__data_start = .) ; *(.data) *(.data*) @@ -30,12 +30,12 @@ SECTIONS *(.rodata*) /* with -fdata-sections. */ . = ALIGN(2); PROVIDE (__data_end = .) ; - } > data + } > data AT> text - .bss : AT (ADDR (.bss)) { + .bss ADDR(.data) + SIZEOF(.data) : AT (ADDR (.bss)) { PROVIDE (__bss_start = .) ; *(.bss) - *(.bss*) + *(.bss*) *(COMMON) PROVIDE (__bss_end = .) ; } > data @@ -43,6 +43,17 @@ SECTIONS __data_load_start = LOADADDR(.data); __data_load_end = __data_load_start + SIZEOF(.data); + /* will robcmp emits .noinit data? i.e., global vars uninitialized. + this also provides __heap_start, for when we implement malloc. + */ + .noinit ADDR(.bss) + SIZEOF(.bss) : AT (ADDR (.noinit)) { + PROVIDE (__noinit_start = .) ; + *(.noinit*) + PROVIDE (__noinit_end = .) ; + _end = . ; + PROVIDE (__heap_start = .) ; + } > data + /* Global data not cleared after reset. */ .eeprom : { KEEP(*(.eeprom*)) From 944af9ed982b65502cb06724b07ad3e9a17b4968 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 12 Jun 2024 09:29:55 -0300 Subject: [PATCH 055/117] Add sintaxe highlights for unsigned suffix and some keywords. --- .../vscode-syntax/robcmpsyntax-0.0.1.vsix | Bin 3281 -> 4709 bytes .../syntaxes/rob.tmLanguage.json | 6 +++--- rob.vim | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix b/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix index 50f66d74ad22c2484e7e0d458bdb48a4e8596dde..e2e5f47765088d97ae293371f9e6666cbeeaede7 100644 GIT binary patch delta 2616 zcmb7Gdo&aLA0FFWXNtKby)osM7*>Svx~xWqGO0$5A$R$mT zSLKpRZ-v}4w-mXQY$SQ-*Xe!V-|xTQbI#{{pU?T8^F5#Ed(QJY&!0P{_duQOfgl(F zASMPt+IP8CK^KLkwn)#IDWDku0QfT`fJ&4rPThn*5Rj&2nDat;!!C7X?KC1hu92F> z-dhx0_{NgYV+AqK9a&%R8(7FjFeSY|{bsuEYSh22!8knEB(lG1Xvm%8$Dzp5wQ$)z zzhGZ!Q0vvenI`HJvB~9Wu0mWqr^TUTz!gKqSvp+{q^*dU~ z4CdSyB}vWc+(t$woE8g87=QEy9xdJ;z2{F0dAlU5yF5Fkc%NA68uH29bIV7!DW#|q zR+g_iqzpJxGG}D;L#3ENWmvTC$?7Q}M+mgV7$sm!pnz1*g1dw$h63RN&3|K`fO&_9 zdJ{-~M1meEf)I)i_a^D-h7dhcA8%cM5|N-w3JaRgIqR!ztK6oMI8^3Z zzGA!WF+puDG7?=@EOitjU-d#$LQX&I$>8Xt28T;w{Wk|$X!Unb&9!1RHDLvgg{xdj zoVjK(m#MO<4R4~Y!p+|^9Vfyr5f?MQWVnEm5NB6EF3f*l;4{aF(S}FbFQ3rM&AXpV zE)fg0P#qW(KQnN!scFtPl6EJx&6bG{p-vpr&Z!xtts{rp7HVJO56eZ-*X;Vi{BOqP zCEKz4btlpXPO^G|u8aVB;q}?4^l3_bMWUX{G1PFEdxqH|UpH4**J6Xd(p!hDFt>j1 zx&BprCVb@$P=UB|=iWc~ZhbeD7C0VthF?8!SbE;%%&Gsv2E`U=RWX8Y|EQX=xykvq zzIlIL?2$x&i-B)k#1h0<^jS+0*Vq`c0I=p#N+QMAwns@<#OXE9aDhwa;R=CNtV)b% zuBc<|4g@4MHZQGNdKDT4HWwmNpP!Sw7q@pwCS3V(n6xS}&ZtG6)?&80L9mJjbEpAa zuS&3P>`Ze+5VW3)Uz)*NnS*!74EzdGya7z3CN#%!FD)IpmQHL*;A+Cw)G$_HCeVs$$l4`%hA;OV5?G(17x z(|ffS*K#<)<)8+-SeRi~><4}7T|Du`Wo?(&C>2){Y4m};6yf<+!=+-ZAogpb_;qyN z?P~)aBbQs1Z)IwmIqYewO&_D2L#H>8B@ElV<`ILzB@lR)7^808|CyZR2-U~qHGk}i z|F;~=2&JrUc*1-fAEn@X@k#~nvuAarKGwA1jq>i+B6yj{V>xXrf6p5`H*7Ak&Uqff zH_MQNxF|2OXDE-3vQ9NpD)IutJ9Qi$IT7~RN6CFY&&e^gekk}`^G4{G~oDij$x&T_w_uablG~SWo^yxZ~e676yEJUS(}|5Z#!V>2G*9n z2We=Ok2s=YbjTUEKYu?(DW$68!f)*;=N2I_ZXBQAef$-^u;)hW7eA62`K7X>#cj3R z8gh1f<*iD~hj2`mu6#1jI1Ooy7Fiiv(BWy`iHMfH@^DCeJ7U7D4{vYyB@gOmGZ30s zTv~HZ^H}T&)6Av&`p@KkarSP?bj&&!d<=E0=1y9faf(}VtvXqRauz9$R6sZk)F@2E zO`P_WrrnsJyT-yPiqh?*o8{#p+v{nCpfsL+Z2;SFc($kF1OI#=YUc8G{`Jv=dSU45 zr`YA3jw9 zCvjvwg0gdX_`<-~(c#MX z&l~gj>Len=Lsf#|er?vFU2!`%mlIvdcWyZRqBvpR2Hc7K6= zxT_TNu7G^a&&)87=9+fb3GX@Ub~5-iIj-S?Ltq1gVB|UuF$7KeK(}K&k92g&R zwAl`G^Y7d{eJWovKEic8nTqv;i^^}7$S8L=o3??gDmWCnn{Q5io{jTy6f1JfD!_$) zz?dtMod@yQuw}eQvFy{kdpO5zMQ+;Kn5fd5#V#-fYvD2u~A zPt?c}o(06;-nJCOw;MJ%_=`H`{Bsqw7Oc;zLJ04e@BWtH6^oJBDX8F%ER)UG2dKV^wn}b-KL|}ol@TRh$#0^RUvw(6ENL?PpXw*(@Fc( z8}z9ve!xki+0wX6-8=28@naEzRZV@xu&(QH!YSt%az>F!=4xP8+zW_oAu`lY?8Fn+ z)$v-bf~BFOh5I_jHHustMFN)hDE9N5_5-}8Jt+XYDH)B*eRil>f?~bA$ntA3@fRT% zJtd@1D}r}<+ei{>p5UATdDfcbo?-K0RKgKfsih>(WDpp+93_K1fKDw=S!r~yAbkAF z8>%o`%md^YV=1_0`!gt)r#geSKnRX2wt@!s*0lo!|{vzb4;InC(z9~;s+Ia8Z7RKXEq^!rj zkMvsfri|(|o&0kI_uT_`d3WW*$IDGNCrCS5C$Y#~u%)xcj@GMP8?QEl@U8t1;1}q> z&Uvxt+WPf}$~uo9oexWZX8IpE%%p&VDLATjPaBPSDjf7-u0Ks*w~{~8v;JvY?audY z)}i{S5vjpcwn9U4fx zOJH&i2h0Q?M|ial=!Q6Vu!0Q+G2ex^oY2wwYx<-x0MH`34yAxn9(B&mv^!Ui)`Hr OGz07f{{Y&y)%^v+#h*w3 delta 1201 zcmaE=a#4~mz?+#xgn@yBgFz)lD10N|dnR5GV~)e^woMES3>uTUn5F7V`@Q)N8SuD# zpQChY-mVP}9A7sx59{~))3@P+lA=nNenYmf8@$8o-4B{SMyYO z%LSDQe!tU8&+0cHet7T4^B9iLkFUPsh4_mD=&#n9FT*x}V&2cl0%A?x%Id%@l_IqH z2kRL|7Ueen@X5D%%wR##%#5pY!R)OeFBLm(PWf`7 zJWw>mP{`rfFNN!?gpL?E$R5}r!esX$RyzFHvBO8YVwa)9)8h!}ecxL_ByRXIj(}mxqtL4kDI_`efyY%LU_cq&ZTzDDeDW^4a%bFDj z+McZ7Q?-nKu3&O{sg7=R3daMm$&^3SV5dM7YTjQ)PWiD1yzuvCvvEE=l-Th>cchQ;{ zoA-B%N*`a_em!q*C3|MqnJ}l#J{PX6+tE@otM8VJSDt3ZZvM^7Dyj|^i@CnmO!%_p zrtV@6v*(+4bay-u^17DJx=eff_wUaiOc3sL8X?^#x^kZe>-D7e8;^Nrk3pVWH-go4~tOKt@ZDg;!i+|y#{6qK9 z<^Kf_mCRNxDrj{%+h^3;m+RoGdC&g z7Ec!vW@ryN%qp4oRYzCgR>GH~XRnk;D)1_|)V)@kK2@oA^2u-d0p9E!T+#-qCz%)+ z=Cd;}1b8zt*)t<@d3TAz>HR>ta~uo|V!%w!z%W@&Ko2e7CkmJ-fHDlz9n}>Dj0_B6 z%nS^wV8sw(N#ix;!cAy%Hxog-bzvR)F>@UQ@$Iigc@Cj)7NiL8I0Mo+%Z2$lO diff --git a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json index 1ca058e..c939174 100644 --- a/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json +++ b/platformio/vscode-syntax/syntaxes/rob.tmLanguage.json @@ -42,7 +42,7 @@ "keywords": { "patterns": [{ "name": "keyword.control.rob", - "match": "\\b(while|loop|if|else|delay|print|return|register|at|volatile|const|type|interface|implements|use|and|or|copy)\\b" + "match": "\\b(while|loop|if|else|delay|print|return|register|at|volatile|const|asm|type|interface|implements|use|and|or|copy|bind|to|singleton|transient)\\b" }] }, "types": { @@ -61,7 +61,7 @@ "numeric-consts": { "patterns": [{ "name": "constant.numeric.rob", - "match": "\\b(\\d+\\.\\d+L?D?|\\d+|0x[0-9a-fA-F]+|0b[0-1]+)\\b" + "match": "\\b(\\d+\\.\\d+L?D?|\\d+[Uu]?|0x[0-9a-fA-F]+|0b[0-1]+)\\b" },{ "name": "constant.numeric.rob", "match": "'\\\\?.'" @@ -95,4 +95,4 @@ } }, "scopeName": "source.rob" -} \ No newline at end of file +} diff --git a/rob.vim b/rob.vim index 807ba7c..4403f2f 100644 --- a/rob.vim +++ b/rob.vim @@ -7,12 +7,12 @@ if exists("b:current_syntax") finish endif -syn keyword keywords while loop if else delay print return register at volatile const asm type use interface copy -syn keyword typeKeywords void char int8 int16 int32 int64 long unsigned float double bool enum +syn keyword keywords while loop if else delay print return register at volatile const asm type interface implements use copy bind to singleton transient +syn keyword typeKeywords void char int8 int16 int32 int64 uint8 uint16 uint32 uint64 long float double bool enum syn keyword operatorKeywords and or quando esta servo syn keyword booleanKeyword true false -syn match integerConstants "\<\d\+\>" +syn match integerConstants "\<\d\+[Uu]\?\>" syn match hexConstants "\<0x[0-9a-fA-F]\+\>" syn match floatConstants "\<\d\+\.\d\+L\?D\?\>" syn match charConstants "'\\\?.'" From db62bc6ae114383f191dec43a0c2116cddc18662 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 12 Jun 2024 18:20:29 -0300 Subject: [PATCH 056/117] Refactoring coercion and supporting unsigned numbers; also improves debug line numbering. --- src/Array.cpp | 24 +- src/Array.h | 23 +- src/ArrayElements.h | 2 +- src/BackLLVM.cpp | 1 - src/BackLLVM.h | 1 - src/BinaryOp.cpp | 121 ++----- src/BinaryOp.h | 14 +- src/BuildTypes.cpp | 18 +- src/BuildTypes.h | 46 ++- src/Capsule.cpp | 7 - src/Capsule.h | 12 - src/Cast.cpp | 22 -- src/Cast.h | 17 - src/Char.h | 2 +- src/CmpOp.cpp | 97 +++--- src/CmpOp.h | 18 +- src/Coercion.cpp | 102 ------ src/Coercion.h | 12 - src/ConstructorCall.cpp | 77 +++++ src/ConstructorCall.h | 26 ++ src/Delay.cpp | 19 -- src/Delay.h | 16 - src/Double.h | 11 +- src/Enum.cpp | 36 +- src/Enum.h | 10 +- src/FlipOp.cpp | 2 +- src/Float.h | 9 +- src/Float128.h | 9 +- src/FunctionCall.cpp | 133 ++------ src/FunctionCall.h | 10 +- src/FunctionDecl.cpp | 61 +++- src/FunctionDecl.h | 52 +-- src/FunctionImpl.cpp | 23 +- src/FunctionImpl.h | 6 +- src/Header.h | 9 - src/HeaderGlobals.h | 1 - src/Identifier.cpp | 2 +- src/Identifier.h | 3 +- src/If.cpp | 12 +- src/If.h | 8 +- src/InPort.cpp | 18 - src/InPort.h | 16 - src/InlineAssembly.h | 2 +- src/Int1.cpp | 2 +- src/Int1.h | 6 +- src/Int16.cpp | 6 +- src/Int16.h | 29 +- src/Int32.cpp | 6 +- src/Int32.h | 23 +- src/Int64.cpp | 6 +- src/Int64.h | 27 +- src/Int8.cpp | 7 +- src/Int8.h | 25 +- src/Interface.h | 5 +- src/Language.l | 13 +- src/Language.y | 129 +++---- src/LanguageHeader.y | 3 +- src/LanguageUse.y | 72 ++-- src/Load.cpp | 34 +- src/Load.h | 19 +- src/LoadArray.cpp | 2 +- src/LoadArray.h | 6 +- src/LoadMatrix.h | 4 +- src/Loop.cpp | 2 +- src/Loop.h | 2 +- src/Matrix.cpp | 16 +- src/Matrix.h | 10 +- src/MemCopy.cpp | 6 +- src/MemCopy.h | 13 +- src/NamedConst.h | 4 +- src/Node.cpp | 27 +- src/Node.h | 18 +- src/OutPort.cpp | 29 -- src/OutPort.h | 16 - src/ParamsCall.h | 2 +- src/Pointer.cpp | 4 +- src/Pointer.h | 2 +- src/Print.cpp | 37 -- src/Print.h | 13 - src/PrintAstVisitor.cpp | 36 +- src/PrintAstVisitor.h | 18 +- src/Program.cpp | 81 ++--- src/Program.h | 2 +- src/PropagateTypes.cpp | 390 ++++++++++++++++++++++ src/PropagateTypes.h | 204 +++++++++++ src/RecursiveVisitor.cpp | 5 +- src/RecursiveVisitor.h | 2 +- src/Return.cpp | 25 +- src/Return.h | 20 +- src/Scalar.cpp | 22 +- src/Scalar.h | 17 +- src/Scanner.cpp | 8 - src/Scanner.h | 2 - src/SourceLocation.h | 11 +- src/StringConst.h | 2 +- src/SymbolizeTree.h | 51 ++- src/UpdateArray.cpp | 16 +- src/UpdateArray.h | 18 +- src/UpdateMatrix.h | 3 +- src/UserType.cpp | 37 +- src/UserType.h | 9 +- src/Variable.h | 4 +- src/Visitor.h | 22 +- src/While.cpp | 6 +- src/While.h | 4 +- src/ZeroInit.h | 2 +- src/main.cpp | 2 +- test/avr328p/Makefile | 6 +- test/avr328p/aux/serial.rob | 10 +- test/avr328p/bsscheck.rob | 23 ++ test/avr328p/bssinjcheck.rob | 45 +++ test/avr328p/itoa.rob | 6 +- test/avr328p/memcpycheck.rob | 42 +++ test/avr328p/runtest.sh | 2 +- test/debug/.gitignore | 5 + test/debug/README | 4 + test/debug/platformio.ini | 12 + test/debug/src/.empty | 0 test/debug/src/.gitignore | 1 + test/general/Makefile | 4 +- test/general/Vector_Int_R.rob | 2 +- test/general/abs.rob | 33 ++ test/general/bellmanford.rob | 20 +- test/general/bitoper.rob | 58 ++++ test/general/bsscheck.rob | 1 + test/general/bssinjcheck.rob | 1 + test/general/byref-array.rob | 14 +- test/general/byref-matrix.rob | 18 +- test/general/cast.rob | 9 + test/general/enum-hex.rob | 17 + test/general/enum-simple.rob | 14 + test/general/{enum.rob => enum-types.rob} | 0 test/general/fibonacci.rob | 2 +- test/general/intfscope.rob | 6 +- test/general/itoa.rob | 133 ++++---- test/general/memcpycheck.rob | 1 + test/general/runtest.sh | 8 +- test/general/sort.rob | 4 +- test/general/unsigned.rob | 16 + 139 files changed, 2047 insertions(+), 1224 deletions(-) delete mode 100644 src/Capsule.cpp delete mode 100644 src/Capsule.h delete mode 100644 src/Cast.cpp delete mode 100644 src/Cast.h delete mode 100644 src/Coercion.cpp delete mode 100644 src/Coercion.h create mode 100644 src/ConstructorCall.cpp create mode 100644 src/ConstructorCall.h delete mode 100644 src/Delay.cpp delete mode 100644 src/Delay.h delete mode 100644 src/InPort.cpp delete mode 100644 src/InPort.h delete mode 100644 src/OutPort.cpp delete mode 100644 src/OutPort.h delete mode 100644 src/Print.cpp delete mode 100644 src/Print.h create mode 100644 src/PropagateTypes.cpp create mode 100644 src/PropagateTypes.h create mode 100644 test/avr328p/bsscheck.rob create mode 100644 test/avr328p/bssinjcheck.rob create mode 100644 test/avr328p/memcpycheck.rob create mode 100644 test/debug/.gitignore create mode 100644 test/debug/README create mode 100644 test/debug/platformio.ini create mode 100644 test/debug/src/.empty create mode 100644 test/debug/src/.gitignore create mode 100644 test/general/abs.rob create mode 100644 test/general/bitoper.rob create mode 120000 test/general/bsscheck.rob create mode 120000 test/general/bssinjcheck.rob create mode 100644 test/general/cast.rob create mode 100644 test/general/enum-hex.rob create mode 100644 test/general/enum-simple.rob rename test/general/{enum.rob => enum-types.rob} (100%) create mode 120000 test/general/memcpycheck.rob create mode 100644 test/general/unsigned.rob diff --git a/src/Array.cpp b/src/Array.cpp index bcd4e18..0fb251c 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -1,15 +1,16 @@ #include "Array.h" #include "ArrayElements.h" -#include "Coercion.h" #include "BackLLVM.h" #include "Visitor.h" #include "FunctionImpl.h" #include "NamedConst.h" #include "BinaryOp.h" +#include "PropagateTypes.h" -Array::Array(const string& n, ArrayElements *aes) : Variable(n), elements(aes) { - NamedConst *nc = new NamedConst("size", getNodeForIntConst(aes->getArraySize())); +Array::Array(const string& n, ArrayElements *aes, location_t loc) : Variable(n, loc), elements(aes) { + NamedConst *nc = new NamedConst("size", getNodeForUIntConst(aes->getArraySize(), loc), loc); addChild(nc); + addSymbol("size", nc); } DataType Array::getDataType() { @@ -29,7 +30,7 @@ void Array::createDataType() { //Get Type of elements in Array of Elements, and define as I. element_dt = elements->getArrayType(); dt = buildTypes->getArrayType(buildTypes->name(element_dt), - *this->getLoct(), 1, true); + this->getLoc(), 1, true); Type* I = buildTypes->llvmType(element_dt); //Declare array type. @@ -51,7 +52,6 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb Value *val = elValue->generate(func, block, allocblock); if (!val) return NULL; - val = Coercion::Convert(val, arrayType->getElementType(), block, elValue); if (!dyn_cast(val)) allConst = false; @@ -121,8 +121,8 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb return alloc; } -void Array::accept(Visitor& v) { - v.visit(*this); +Node* Array::accept(Visitor& v) { + return v.visit(*this); } Type* Array::getLLVMType() { @@ -158,5 +158,13 @@ Node *Array::getElementIndex(Node *p1, Node *p2, const string& name, int p1size, return p1; // Generate index of element for matrix - return new BinaryOp(new BinaryOp(p1, '*', columnNumber), '+', p2); + Node *i16p1; + if (buildTypes->isSignedDataType(p1->getDataType())) + i16p1 = new SExtInt(p1, tint16); + else + i16p1 = new ZExtInt(p1, tint16u); + BinaryOp *op = new BinaryOp(new BinaryOp(i16p1, '*', columnNumber), '+', p2); + PropagateTypes pt; + pt.visit(*op); + return op; } diff --git a/src/Array.h b/src/Array.h index 0d9adfb..44aad99 100644 --- a/src/Array.h +++ b/src/Array.h @@ -7,27 +7,16 @@ class ArrayElements; -/*class LinearDataStructure: public Variable { -protected: - DataType element_dt = BuildTypes::undefinedType; -public: - LinearDataStructure(const string &n): Variable(n) {} - virtual Node *getElementIndex(Node *p1, Node *p2) = 0; - virtual DataType getElementDt() { - return element_dt; - } -};*/ - class ParamArray: public Variable { protected: DataType element_dt = BuildTypes::undefinedType; public: - ParamArray(const string& n, string element_dt_name, location_t loc): Variable(n) { + ParamArray(const string& n, string element_dt_name, location_t loc): Variable(n, loc) { this->element_dt = buildTypes->getType(element_dt_name, true); this->dt = buildTypes->getArrayType(element_dt_name, loc, 1, true); } - ParamArray(const string &n, DataType dt): Variable(n) { + ParamArray(const string &n, DataType dt, location_t loc): Variable(n, loc) { this->dt = dt; this->element_dt = buildTypes->getArrayElementType(dt); } @@ -42,7 +31,7 @@ class Array: public Variable { void createDataType(); public: - Array(const string& n, ArrayElements *aes); + Array(const string& n, ArrayElements *aes, location_t loc); virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; @@ -53,12 +42,16 @@ class Array: public Variable { return elements->getElements(); } - virtual void accept(Visitor& v) override; + virtual Node* accept(Visitor& v) override; virtual Type *getLLVMType() override; DataType getDataType() override; + DataType getElementDataType() { + return element_dt; + } + int getSize() const { return size; } diff --git a/src/ArrayElements.h b/src/ArrayElements.h index 37f4a3c..e5ddac2 100644 --- a/src/ArrayElements.h +++ b/src/ArrayElements.h @@ -25,7 +25,7 @@ class ArrayElements { DataType getArrayType(); static DataType getArrayConstType(const set& types, SourceLocation *location); - std::vector const& getElements() { + std::vector& getElements() { return elements; } }; diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 3b139a8..5575439 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -44,7 +44,6 @@ unsigned int dataAddrSpace = 0; // Injections map> injections; -map map_injections; enum SupportedTargets currentTargetId; extern char *build_outputfilename; diff --git a/src/BackLLVM.h b/src/BackLLVM.h index bb09d1b..8ccc163 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -30,4 +30,3 @@ class Variable; enum BindScope {bs_singleton, bs_transient}; extern map> injections; -extern map map_injections; diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index 84e4c58..543a20a 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -2,21 +2,18 @@ #include "Language_gen_y.hpp" #include "BinaryOp.h" -#include "Coercion.h" -BinaryOp::BinaryOp(Node *l, int op, Node *r) { - this->lhsn = l; - this->rhsn = r; +BinaryOp::BinaryOp(Node *l, int op, Node *r) : Node(l->getLoc()) { this->op = op; - this->addChild(lhsn); - this->addChild(rhsn); + this->addChild(l); + this->addChild(r); } Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - Value *lhs = lhsn->generate(func, block, allocblock); - Value *rhs = rhsn->generate(func, block, allocblock); + Value *lhs = lhsn()->generate(func, block, allocblock); + Value *rhs = rhsn()->generate(func, block, allocblock); Type *lhsty = lhs->getType(); Type *rhsty = rhs->getType(); @@ -33,107 +30,35 @@ Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, enum Instruction::BinaryOps opflt, FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - Value *lhs = lhsn->generate(func, block, allocblock); - Value *rhs = rhsn->generate(func, block, allocblock); + DataType lty = lhsn()->getDataType(); + DataType rty = rhsn()->getDataType(); + + Value *lhs = lhsn()->generate(func, block, allocblock); + Value *rhs = rhsn()->generate(func, block, allocblock); if (lhs == NULL || rhs == NULL) return NULL; - Type *Ty1 = lhs->getType(); - Type *Ty2 = rhs->getType(); - enum Instruction::BinaryOps llvmop; - - Builder->SetInsertPoint(block); - - if (Ty1->isIntegerTy() && Ty2->isIntegerTy()) { - /*fallback SDiv disabled - if (opint == Instruction::SDiv) { - vector args; - args.push_back(lhs); - args.push_back(rhs); - ArrayRef argsRef(args); - return CallInst::Create(i16div, argsRef, "", block); - }*/ - - if (opint == Instruction::Shl || opint == Instruction::LShr) { - // zext the left operator if we know the rside bitwidth - Constant *c = NULL; - if (rhsn->isConstExpr()) { - Value *v = rhsn->generate(NULL, block, allocblock); - c = dyn_cast(v); - } - if (c) { - RobDbgInfo.emitLocation(this); - int64_t v = c->getUniqueInteger().getZExtValue(); - if (Ty1->getIntegerBitWidth() < v) { - if (v >= 8 && v <= 15) - lhs = Builder->CreateZExt(lhs, Type::getInt16Ty(global_context), "zext16"); - else if (v >= 16 && v <= 31) - lhs = Builder->CreateZExt(lhs, Type::getInt32Ty(global_context), "zext32"); - else if (v >= 32 && v <= 63) - lhs = Builder->CreateZExt(lhs, Type::getInt64Ty(global_context), "zext64"); - else - yyerrorcpp("Number of shift bits exceeds the max int precision for left side.", this); - Ty1 = lhs->getType(); - } - } + if (buildTypes->isIntegerDataType(lty)) { // it suffices to check one side, operands has been coerced + if (buildTypes->isUnsignedDataType(lty)) { + if (opint == Instruction::SDiv) + opint = Instruction::UDiv; + else if (opint == Instruction::SRem) + opint = Instruction::URem; + else if (opint == Instruction::AShr) + opint = Instruction::LShr; } - - if (dyn_cast(Ty1)->getBitWidth() > dyn_cast(Ty2)->getBitWidth()) - rhs = Coercion::Convert(rhs, Ty1, block, rhsn); - else - lhs = Coercion::Convert(lhs, Ty2, block, lhsn); - llvmop = opint; - } - else { - RobDbgInfo.emitLocation(this); - if (Ty1->isIntegerTy()) - lhs = Builder->CreateSIToFP(lhs, Ty2, "castitof"); - else if (Ty2->isIntegerTy()) - rhs = Builder->CreateSIToFP(rhs, Ty1, "castitof"); + } else { llvmop = opflt; } + Builder->SetInsertPoint(block); RobDbgInfo.emitLocation(this); return Builder->CreateBinOp(llvmop, lhs, rhs, "binop"); } DataType BinaryOp::getDataType() { - if (dt == BuildTypes::undefinedType) { - DataType lty = lhsn->getDataType(); - DataType rty = rhsn->getDataType(); - if (buildTypes->isIntegerDataType(lty) && buildTypes->isIntegerDataType(rty)) { - if (op == TOK_LSHIFT || op == TOK_RSHIFT) { - // zext the left operator if we know the rside bitwidth - Constant *c = NULL; - if (rhsn->isConstExpr()) { - Value *v = rhsn->generate(NULL, NULL, NULL); - c = dyn_cast(v); - } - if (c) { - int64_t v = c->getUniqueInteger().getZExtValue(); - if (buildTypes->bitWidth(lty) < v) { - if (v >= 8 && v <= 15) - dt = tint16; - else if (v >= 16 && v <= 31) - dt = tint32; - else if (v >= 32 && v <= 63) - dt = tint64; - else - dt = tvoid; - } - } - } - dt = buildTypes->bitWidth(lty) > buildTypes->bitWidth(rty) ? lty : rty; - - } else { - if (buildTypes->isIntegerDataType(lty)) - dt = rty; - else - dt = lty; - } - } return dt; } @@ -148,7 +73,7 @@ Value *BinaryOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all case '&' : return binary_operator(Instruction::And, Instruction::And, func, block, allocblock); case '^' : return binary_operator(Instruction::Xor, Instruction::Xor, func, block, allocblock); case TOK_LSHIFT: return binary_operator(Instruction::Shl, Instruction::Shl, func, block, allocblock); - case TOK_RSHIFT: return binary_operator(Instruction::LShr, Instruction::LShr, func, block, allocblock); + case TOK_RSHIFT: return binary_operator(Instruction::AShr, Instruction::AShr, func, block, allocblock); case TOK_AND : return logical_operator(BinaryOperator::And, func, block, allocblock); case TOK_OR : return logical_operator(BinaryOperator::Or, func, block, allocblock); default: return NULL; @@ -156,6 +81,6 @@ Value *BinaryOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all } bool BinaryOp::isConstExpr() { - return lhsn->isConstExpr() && - rhsn->isConstExpr(); + return lhsn()->isConstExpr() && + rhsn()->isConstExpr(); } diff --git a/src/BinaryOp.h b/src/BinaryOp.h index cf6413b..068679a 100644 --- a/src/BinaryOp.h +++ b/src/BinaryOp.h @@ -2,12 +2,11 @@ #pragma once #include "Node.h" +#include "Visitor.h" class BinaryOp: public Node { private: int op; - Node *lhsn; - Node *rhsn; public: BinaryOp(Node *l, int op, Node *r); @@ -26,4 +25,15 @@ class BinaryOp: public Node { virtual bool isConstExpr() override; + Node *lhsn() { + return node_children[0]; + } + + Node *rhsn() { + return node_children[1]; + }; + + Node* accept(Visitor &v) override { + return v.visit(*this); + } }; diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 34c51d7..b4f5e43 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -20,10 +20,10 @@ BuildTypes::BuildTypes(DataType targetPointerType) { tinfo[tint16] = {"int16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_signed}; tinfo[tint32] = {"int32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_signed}; tinfo[tint64] = {"int64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_signed}; - tinfo[tint8u] = {"unsigned8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; - tinfo[tint16u] = {"unsigned16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; - tinfo[tint32u] = {"unsigned32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; - tinfo[tint64u] = {"unsigned64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint8u] = {"uint8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint16u] = {"uint16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint32u] = {"uint32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint64u] = {"uint64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tfloat] = {"float", 32, Type::getFloatTy(global_context), dwarf::DW_ATE_float}; tinfo[tdouble] = {"double", 64, Type::getDoubleTy(global_context), dwarf::DW_ATE_float}; tinfo[tldouble] = {"long double", 128, Type::getFP128Ty(global_context), dwarf::DW_ATE_float}; @@ -92,9 +92,12 @@ DataType BuildTypes::getArrayElementType(DataType arrayDt) { DataType BuildTypes::getType(const string& name, bool createUndefined) { auto ut = namedTypes.find(name); if (ut == namedTypes.end()) { - if (createUndefined) - return addDataType(DataTypeInfo(name)); - } else if (tinfo[ut->second].isDefined || createUndefined) { + if (createUndefined) { + DataTypeInfo dti(name); + dti.isComplex = true; + return addDataType(dti); + } + } else /*if (tinfo[ut->second].isDefined || createUndefined)*/ { return ut->second; } return undefinedType; @@ -123,6 +126,7 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi info.llvmType = llvmType; info.isDefined = true; info.isComplex = !isEnum; + info.isEnum = isEnum; info.dwarfEnc = 0; info.bitWidth = bitWidth; info.isInternal = false; diff --git a/src/BuildTypes.h b/src/BuildTypes.h index 775098b..f1c7388 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -7,6 +7,9 @@ typedef int DataType; +/* Don't change the order of these types without updating the code below accordingly. + In another words, don't change it. + */ enum BasicDataType {tvoid, tbool, tchar, tint2, tint3, tint4, tint5, tint6, tint7, tint8, tint16, tint32, tint64, tint8u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, @@ -26,6 +29,7 @@ struct DataTypeInfo { SourceLocation *sl; bool isDefined; bool isComplex; + bool isEnum; bool isInterface; bool isInternal; unsigned char arrayDimensions; @@ -41,6 +45,7 @@ struct DataTypeInfo { this->diPointerType = NULL; this->isDefined = false; this->isComplex = false; + this->isEnum = false; this->isInternal = false; this->isInterface = false; this->arrayDimensions = 0; @@ -49,7 +54,7 @@ struct DataTypeInfo { DataTypeInfo(const char* name, unsigned bitWidth, Type *llvmType, unsigned dwarfEnc): name(name), bitWidth(bitWidth), llvmType(llvmType), dwarfEnc(dwarfEnc), diType(NULL), diPointerType(NULL), sl(NULL), isDefined(true), isComplex(false), isInternal(false), - isInterface(false), arrayDimensions(0) {}; + isInterface(false), isEnum(false), arrayDimensions(0) {}; }; class BuildTypes { @@ -107,16 +112,24 @@ class BuildTypes { return tinfo[tid].sl; } + bool isPrimitiveType(DataType tid) const { + return tid >= tbool && tid < __bdt_last; + } + + bool isNumericDataType(DataType tid) { + return (tid >= tbool && tid <= tldouble) || isEnum(tid); + } + bool isIntegerDataType(DataType tid) const { - return tid >= tint8 && tid <= tint64u; + return tid >= tbool && tid <= tint64u; } bool isSignedDataType(DataType tid) const { - return tid >= tint8 && tid <= tint64; + return (tid >= tint8 && tid <= tint64) || (tid == tbool); } bool isUnsignedDataType(DataType tid) const { - return tid >= tint8u && tid <= tint64u; + return (tid >= tint8u && tid <= tint64u) || (tid == tchar); } bool isFloatDataType(DataType tid) const { @@ -127,6 +140,11 @@ class BuildTypes { assert(tid != -1 && "Undefined type"); return tinfo[tid].isComplex; } + + bool isEnum(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isEnum; + } bool isInternal(DataType tid) { assert(tid != -1 && "Undefined type"); @@ -172,6 +190,26 @@ class BuildTypes { assert(tid != -1 && "Undefined type"); return tinfo[tid].arrayDimensions; } + + DataType unsignedToSigned(DataType tid) { + assert(isUnsignedDataType(tid)); + if (tid == tchar) + return tint8; + else + return tid - (tint64u - tint64); + } + + DataType signedToUnsigned(DataType tid) { + assert(isSignedDataType(tid)); + if (tid != tbool) + tid += tint64u - tint64; + return tid; + } + + bool isDefined(DataType tid) { + assert(tid != -1 && "Undefined type"); + return tinfo[tid].isDefined; + } }; // TODO: Replace all places with buildType::name diff --git a/src/Capsule.cpp b/src/Capsule.cpp deleted file mode 100644 index 50cdb61..0000000 --- a/src/Capsule.cpp +++ /dev/null @@ -1,7 +0,0 @@ - -#include "Capsule.h" - -Value *Capsule::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - return node->generate(func, block, allocblock); -} - diff --git a/src/Capsule.h b/src/Capsule.h deleted file mode 100644 index 544de26..0000000 --- a/src/Capsule.h +++ /dev/null @@ -1,12 +0,0 @@ - -#pragma once - -#include "Node.h" - -class Capsule: public Node { -private: - Node *node; -public: - Capsule (Node *n) : node(n) {} - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); -}; diff --git a/src/Cast.cpp b/src/Cast.cpp deleted file mode 100644 index 9c79e3c..0000000 --- a/src/Cast.cpp +++ /dev/null @@ -1,22 +0,0 @@ - -#include "Cast.h" -#include "Coercion.h" - -Value *Cast::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) -{ - Value *exprv = expr->generate(func, block, allocblock); - if (!exprv) - return NULL; - - Type *destty = buildTypes->llvmType(dt); - Value *ret = Coercion::Convert(exprv, destty, block, expr, true); - - if (ret == NULL) { - yyerrorcpp(string_format("Can't cast from '%s' to '%s'.", - buildTypes->name(expr->getDataType()), - buildTypes->name(dt)), this); - return NULL; - } - - return ret; -} diff --git a/src/Cast.h b/src/Cast.h deleted file mode 100644 index 9363e92..0000000 --- a/src/Cast.h +++ /dev/null @@ -1,17 +0,0 @@ - -#pragma once - -#include "Node.h" - -class Cast: public Node { -private: - Node *expr; - -public: - Cast(DataType dt, Node *expr): expr(expr) { - this->dt = dt; - node_children.push_back(expr); - } - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - -}; diff --git a/src/Char.h b/src/Char.h index 4220dd5..0099e6d 100644 --- a/src/Char.h +++ b/src/Char.h @@ -8,7 +8,7 @@ class Char: public Node { char value; public: - Char(char v): value(v) {} + Char(char v, location_t loc): Node(loc), value(v) {} char getValue() const { return value; } diff --git a/src/CmpOp.cpp b/src/CmpOp.cpp index 1889ecb..64e267b 100644 --- a/src/CmpOp.cpp +++ b/src/CmpOp.cpp @@ -2,69 +2,70 @@ #include "CmpOp.h" #include "FlexDependencies.h" #include "Language_gen_y.hpp" -#include "Coercion.h" -CmpOp::CmpOp (Node *l, int op, Node *r) : lexpn(l), rexpn(r) { +CmpOp::CmpOp (Node *l, int op, Node *r): Node(l->getLoc()) { this->op = op; this->dt = tbool; - addChild(lexpn); - addChild(rexpn); + addChild(l); + addChild(r); } Value *CmpOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { CmpInst::Predicate predicate; - Value *lexp = lexpn->generate(func, block, allocblock); - Value *rexp = rexpn->generate(func, block, allocblock); + Value *lexp = lexpn()->generate(func, block, allocblock); + Value *rexp = rexpn()->generate(func, block, allocblock); if (rexp == NULL || lexp == NULL) // can't generate values, error message emitted during generate. - return ConstantInt::get(Type::getInt1Ty(global_context), 1); // error recover + return ConstantInt::get(Type::getInt1Ty(global_context), 1); // error recovery - Type *tl = lexp->getType(); - Type *tr = rexp->getType(); + // it suffices to check one side, operands has been coerced + DataType edt = lexpn()->getDataType(); + bool isFloatCmp = buildTypes->isFloatDataType(edt); + bool isSignedCmp = buildTypes->isSignedDataType(edt); + bool isUnsignedCmp = buildTypes->isUnsignedDataType(edt); - bool canCompare = (tl->isIntegerTy() || tl->isFloatingPointTy()) && - (tr->isIntegerTy() || tr->isFloatingPointTy()); - if (!canCompare) { - yyerrorcpp("Can not compare " + getTypeName(tl) + " and " + - getTypeName(tr) + " types.", lexpn); - return ConstantInt::get(Type::getInt1Ty(global_context), 1); // error recover - } - - RobDbgInfo.emitLocation(this); - - bool isFloatPointCmp = true; - if (tl->isFloatingPointTy() && tr->isIntegerTy()) - rexp = Coercion::Convert(rexp, tl, block, rexpn); - else if (tl->isIntegerTy() && tr->isFloatingPointTy()) - lexp = Coercion::Convert(lexp, tr, block, lexpn); - else if (tl->isIntegerTy() && tr->isIntegerTy()) { - // left and right are integers - isFloatPointCmp = false; - unsigned tlbw = tl->getIntegerBitWidth(); - unsigned trbw = tr->getIntegerBitWidth(); - if (tlbw > trbw) - rexp = Coercion::Convert(rexp, tl, block, rexpn); - else if (tlbw < trbw) - lexp = Coercion::Convert(lexp, tr, block, lexpn); - } + if (buildTypes->isEnum(edt)) + isUnsignedCmp = true; + + const string op_error = "Invalid operator for comparison."; - if (rexp == NULL || lexp == NULL) // coercion not possible, error message during coercion - return ConstantInt::get(Type::getInt1Ty(global_context), 1); // error recover - - if (op == EQ_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_OEQ : ICmpInst::ICMP_EQ; - else if (op == NE_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_UNE : ICmpInst::ICMP_NE; - else if (op == GE_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_OGE : ICmpInst::ICMP_SGE; - else if (op == LE_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_OLE : ICmpInst::ICMP_SLE; - else if (op == GT_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_OGT : ICmpInst::ICMP_SGT; - else if (op == LT_OP) predicate = isFloatPointCmp ? FCmpInst::FCMP_OLT : ICmpInst::ICMP_SLT; - else { - yyerrorcpp("Invalid predicate for comparison.", lexpn); - return NULL; - } + if (isFloatCmp) { + switch (op) { + case EQ_OP: predicate = FCmpInst::FCMP_OEQ; break; + case NE_OP: predicate = FCmpInst::FCMP_ONE; break; + case GE_OP: predicate = FCmpInst::FCMP_OGE; break; + case LE_OP: predicate = FCmpInst::FCMP_OLE; break; + case GT_OP: predicate = FCmpInst::FCMP_OGT; break; + case LT_OP: predicate = FCmpInst::FCMP_OLT; break; + default: yyerrorcpp(op_error, lexpn()); break; + } + } else if (isSignedCmp) { + switch (op) { + case EQ_OP: predicate = FCmpInst::ICMP_EQ; break; + case NE_OP: predicate = FCmpInst::ICMP_NE; break; + case GE_OP: predicate = FCmpInst::ICMP_SGE; break; + case LE_OP: predicate = FCmpInst::ICMP_SLE; break; + case GT_OP: predicate = FCmpInst::ICMP_SGT; break; + case LT_OP: predicate = FCmpInst::ICMP_SLT; break; + default: yyerrorcpp(op_error, lexpn()); break; + } + } else if (isUnsignedCmp) { + switch (op) { + case EQ_OP: predicate = FCmpInst::ICMP_EQ; break; + case NE_OP: predicate = FCmpInst::ICMP_NE; break; + case GE_OP: predicate = FCmpInst::ICMP_UGE; break; + case LE_OP: predicate = FCmpInst::ICMP_ULE; break; + case GT_OP: predicate = FCmpInst::ICMP_UGT; break; + case LT_OP: predicate = FCmpInst::ICMP_ULT; break; + default: yyerrorcpp(op_error, lexpn()); break; + } + } else + yyerrorcpp(op_error, lexpn()); + RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); - if (isFloatPointCmp) + if (isFloatCmp) return Builder->CreateFCmp(predicate, lexp, rexp, "cmpf"); else { return Builder->CreateICmp(predicate, lexp, rexp, "cmpi"); diff --git a/src/CmpOp.h b/src/CmpOp.h index 22af857..16a7ce8 100644 --- a/src/CmpOp.h +++ b/src/CmpOp.h @@ -1,18 +1,24 @@ -#ifndef __CMPOP_H__ -#define __CMPOP_H__ +#pragma oncd + #include "Node.h" +#include "Visitor.h" class CmpOp: public Node { private: - Node *lexpn; - Node *rexpn; int op; public: CmpOp (Node *l, int op, Node *r); int getOperator() const { return op; }; virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + Node *lexpn() { + return node_children[0]; + } + Node *rexpn() { + return node_children[1]; + } + Node* accept(Visitor &v) override { + return v.visit(*this); + } }; - -#endif diff --git a/src/Coercion.cpp b/src/Coercion.cpp deleted file mode 100644 index 23974c2..0000000 --- a/src/Coercion.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "Coercion.h" -#include "HeaderGlobals.h" -#include "BuildTypes.h" - -unsigned Coercion::GetFloatingPointBitwidth(Type *ty) { - switch (ty->getTypeID()) { - case Type::FloatTyID: - return 32; - case Type::DoubleTyID: - return 64; - case Type::X86_FP80TyID: - return 80; - case Type::PPC_FP128TyID: - case Type::FP128TyID: - return 128; - default: - return 0; - } -} - -Value *Coercion::Convert(Value *v, Type *destty, BasicBlock *block, SourceLocation *loc, bool isCast){ - - Value *r = v; - Type *ty = v->getType(); - - RobDbgInfo.emitLocation(loc); - Builder->SetInsertPoint(block); - - if (ty != destty){ - //Float to Integer - if (ty->isFloatingPointTy() && destty->isIntegerTy()){ - r = Builder->CreateFPToSI(v, destty, "fptosi"); - if (!isCast) - yywarncpp("Float point converted to integer.", loc); - } - //Integer to Float - else if (destty->isFloatingPointTy() && ty->isIntegerTy()){ - r = Builder->CreateSIToFP(v, destty, "sitofp"); - } - //Floating point to Floating point - else if (ty->isFloatingPointTy() && destty->isFloatingPointTy()) { - unsigned tybw = GetFloatingPointBitwidth(ty); - unsigned dtybw = GetFloatingPointBitwidth(destty); - if (dtybw > tybw) - r = Builder->CreateFPExt(v, destty, "fpext"); - else if (dtybw < tybw) { - r = Builder->CreateFPTrunc(v, destty, "fptrunc"); - if (!isCast) - yywarncpp("Float point value truncated.", loc); - } - } - //Generic ExtInt to Int - else if (destty->isIntegerTy() && ty->isIntegerTy()){ - unsigned wty = ty->getIntegerBitWidth(); - unsigned wdestty = destty->getIntegerBitWidth(); - if (wty > wdestty){ - r = Builder->CreateTrunc(v, destty, "trunc"); - if (!isCast) { - yywarncpp(string_format("Integer value truncated from int%d to int%d.", - wty, wdestty), loc); - } - } - else if (wty < wdestty) { - r = Builder->CreateSExt(v, destty, "sext"); - } - } - else { - yyerrorcpp("No coercion between " + getTypeName(ty) + " and " + - getTypeName(destty) + " implemented.", loc); - } - } else { - // check composite types - bool distinct = ty->getNumContainedTypes() != destty->getNumContainedTypes(); - if (!distinct && ty->getNumContainedTypes() > 0) { - for(int i = 0; i < ty->getNumContainedTypes(); i++) { - auto ity = ty->getContainedType(i); - auto dity = destty->getContainedType(i); - if (ity != dity) { - distinct = true; - } else { - if (ity->isIntegerTy() && dity->isIntegerTy()) { - unsigned wity = ity->getIntegerBitWidth(); - unsigned wdity = dity->getIntegerBitWidth(); - if (wity != wdity) - distinct = true; - } else if (ity->isFloatingPointTy() && dity->isFloatingPointTy()) { - unsigned wity = GetFloatingPointBitwidth(ity); - unsigned wdity = GetFloatingPointBitwidth(dity); - if (wity != wdity) - distinct = true; - } - } - if (distinct) - break; - } - if (distinct) - yyerrorcpp("No coercion between " + getTypeName(ty) + " and " + - getTypeName(destty) + " implemented.", loc); - } - } - return r; -} diff --git a/src/Coercion.h b/src/Coercion.h deleted file mode 100644 index 20348cf..0000000 --- a/src/Coercion.h +++ /dev/null @@ -1,12 +0,0 @@ - -#pragma once - -#include "HeaderExternals.h" -#include "SourceLocation.h" - -class Coercion{ -public: - static Value *Convert(Value *v, Type *destty, BasicBlock *block, SourceLocation *loc, - bool isCast = false); - static unsigned GetFloatingPointBitwidth(Type *ty); -}; diff --git a/src/ConstructorCall.cpp b/src/ConstructorCall.cpp new file mode 100644 index 0000000..ae75677 --- /dev/null +++ b/src/ConstructorCall.cpp @@ -0,0 +1,77 @@ + +#include "ConstructorCall.h" +#include "BackLLVM.h" +#include "Program.h" +#include "UserType.h" + +Value* ConstructorCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + if (dt == BuildTypes::undefinedType) + getDataType(); + + // alloc + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + Value *var = leftValue->getLLVMValue(func); + if (var == NULL) { + // is a new left var + Builder->SetInsertPoint(allocblock); + var = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, 0, + leftValue->getName()); + leftValue->setAlloca(var); + leftValue->setDataType(dt); + if (debug_info) + RobDbgInfo.declareVar(leftValue, var, allocblock); + } + vector args; + args.push_back(var); + + // if calling a constructor of an interface, emit code to bind it + if (buildTypes->isInterface(dt)) { + Node *scope = leftValue->getScope(); + UserType *parent= dynamic_cast(scope); + const string toInjection = parent ? + parent->getName() + "." + leftValue->getName() : + leftValue->getName(); + + const string injectFuncName = ":get_injection_for_" + toInjection; + Node *funcNode = findSymbol(injectFuncName); + FunctionBase *funcDecl = dynamic_cast(funcNode); + if (!funcDecl) { + funcDecl = new FunctionDecl(dt, injectFuncName, new FunctionParams(), this->getLoc()); + funcDecl->setReturnIsPointer(true); + funcDecl->setScope(program); + funcDecl->setLocation(this); + funcDecl->generate(NULL, NULL, global_alloc); + funcDecl->setInline(true); + program->addSymbol(funcDecl); + } + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateCall(funcDecl->getLLVMFunction()); + + } else { + // call the init constructor + + // find the user type + Node *type = findSymbol(name); + if (!type) + return NULL; + + Node *fsymbol = type->findMember("init"); + assert(fsymbol && "the init method for the type must exists"); + + FunctionBase *initfunc = dynamic_cast(fsymbol); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + + if (initfunc->needsParent()) { + Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); + Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + args.push_back(ptr); + } + + CallInst *c = Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); + return NULL; // init doesn't return; is a call to a void func + } +} diff --git a/src/ConstructorCall.h b/src/ConstructorCall.h new file mode 100644 index 0000000..6cb7aa3 --- /dev/null +++ b/src/ConstructorCall.h @@ -0,0 +1,26 @@ + +#pragma once + +#include "Node.h" +#include "Variable.h" +#include "FunctionImpl.h" + +class ConstructorCall: public Node { +protected: + Variable *leftValue = NULL; + string name; +public: + ConstructorCall(const string tyName, location_t loc): Node(loc), name(tyName) { } + + virtual void setLeftValue(Variable *symbol) override { + leftValue = symbol; + } + + virtual Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + DataType getDataType() override { + if (dt == BuildTypes::undefinedType) + dt = buildTypes->getType(name); + return dt; + } +}; diff --git a/src/Delay.cpp b/src/Delay.cpp deleted file mode 100644 index d798bd3..0000000 --- a/src/Delay.cpp +++ /dev/null @@ -1,19 +0,0 @@ - -#include "Delay.h" - -Delay::Delay(Node *mseg) : ms(mseg) { - addChild(ms); -} - -Value *Delay::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - /*Value *msv = ms->generate(func, block, allocblock); - Value *msv32 = new SExtInst(msv, Type::getInt32Ty(global_context), "conv", block); - - vector args; - args.push_back(msv32); - ArrayRef argsRef(args); - return CallInst::Create(delay, argsRef, "", block);*/ - - // TODO: Implement a new delay without C depedency - return NULL; -} diff --git a/src/Delay.h b/src/Delay.h deleted file mode 100644 index ca05f00..0000000 --- a/src/Delay.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __DELAY_H__ -#define __DELAY_H__ -#include "Node.h" -#include "Int32.h" - -class Delay: public Node { -private: - Node *ms; - -public: - Delay (Node *mseg); - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - -}; - -#endif diff --git a/src/Double.h b/src/Double.h index 2001c46..42b1f77 100644 --- a/src/Double.h +++ b/src/Double.h @@ -1,12 +1,13 @@ -#ifndef __DOUBLE_H__ -#define __DOUBLE_H__ + +#pragma once + #include "Node.h" class Double: public Node { private: - float number; + double number; public: - Double(float n): number(n) {} + Double(double n, location_t loc): Node(loc), number(n) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; virtual bool isConstExpr() override { return true; @@ -15,5 +16,3 @@ class Double: public Node { return tdouble; } }; - -#endif diff --git a/src/Enum.cpp b/src/Enum.cpp index 756c807..18fb8a0 100644 --- a/src/Enum.cpp +++ b/src/Enum.cpp @@ -9,17 +9,28 @@ void Enum::createDataType() { return; } + dt = buildTypes->getType(name); + if (dt != BuildTypes::undefinedType && buildTypes->isDefined(dt)) { + yyerrorcpp("Type " + name + " alread defined.", this); + yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); + return; + } + /* set enum items values * enum A {B=1, C, D, E, F=10, G, H=127, I} => C=2, D=3 ... G=11 ... I=-128 * enum B {C=3, D=2, E, F} => E=4, F=5 */ - int8_t v = 0; - map values; + uint8_t v = 0; + map values; for(Node *n : children()) { NamedConst *nc = (NamedConst*)n; - Int8 *i8 = dynamic_cast(nc->getValue()); - if (i8) { - v = i8->getNumber(); + Node *nv = nc->getValue(); + if (nv) { + if (Int8 *i8 = dynamic_cast(nv)) + v = i8->getNumber(); + else if (UInt8 *ui8 = dynamic_cast(nv)) + v = ui8->getNumber(); + if (values.count(v) == 1) { yyerrorcpp(string_format("Value %d alread taken for %s.", v, values[v]->getName().c_str()), nc); @@ -29,18 +40,13 @@ void Enum::createDataType() { } else { while (values.count(v) == 1) v++; - nc->setValue(new Int8(v)); + nc->setValue(new UInt8(v, nc->getLoc())); values[v] = nc; } } dt = buildTypes->addDataType(this, buildTypes->llvmType(tint8), buildTypes->bitWidth(tint8), true); - if (dt == BuildTypes::undefinedType) { - yyerrorcpp("Type " + name + " alread defined.", this); - yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); - return; - } for(Node *n : children()) { n->setDataType(dt); @@ -48,6 +54,12 @@ void Enum::createDataType() { } Value* Enum::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - createDataType(); + getDataType(); return NULL; +} + +DataType Enum::getDataType() { + if (dt == BuildTypes::undefinedType) + createDataType(); + return dt; } \ No newline at end of file diff --git a/src/Enum.h b/src/Enum.h index 151a518..423b22b 100644 --- a/src/Enum.h +++ b/src/Enum.h @@ -2,14 +2,22 @@ #pragma once #include "Node.h" +#include "Visitor.h" class Enum : public NamedNode { private: void createDataType(); public: - Enum(const string& name, vector &&items): NamedNode(name, std::move(items)) { + Enum(const string& name, vector &&items, location_t loc): + NamedNode(name, std::move(items), loc) { } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual DataType getDataType() override; + + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } }; diff --git a/src/FlipOp.cpp b/src/FlipOp.cpp index 4ff469f..da75554 100644 --- a/src/FlipOp.cpp +++ b/src/FlipOp.cpp @@ -1,7 +1,7 @@ #include "FlipOp.h" -FlipOp::FlipOp(Node *value) : value(value) { +FlipOp::FlipOp(Node *value) : Node(value->getLoc()), value(value) { this->addChild(value); }; diff --git a/src/Float.h b/src/Float.h index 3cfb2f4..2f1c19e 100644 --- a/src/Float.h +++ b/src/Float.h @@ -1,12 +1,13 @@ -#ifndef __FLOAT_H__ -#define __FLOAT_H__ + +#pragma once + #include "Node.h" class Float: public Node { private: float number; public: - Float(float n): number(n) {} + Float(float n, location_t loc): Node(loc), number(n) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; virtual bool isConstExpr() override { return true; @@ -16,5 +17,3 @@ class Float: public Node { return tfloat; } }; - -#endif diff --git a/src/Float128.h b/src/Float128.h index 7bcb58f..983de29 100644 --- a/src/Float128.h +++ b/src/Float128.h @@ -1,12 +1,12 @@ -#ifndef __FLOAT128_H__ -#define __FLOAT128_H__ +#pragma once + #include "Node.h" class Float128: public Node { private: - float number; + long double number; public: - Float128(float n): number(n) {} + Float128(long double n, location_t loc): Node(loc), number(n) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; virtual bool isConstExpr() override { @@ -18,4 +18,3 @@ class Float128: public Node { } }; -#endif diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index b4082b2..f495c2a 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -1,10 +1,9 @@ #include "FunctionCall.h" #include "BuildTypes.h" -#include "Cast.h" #include "FunctionDecl.h" #include "FunctionImpl.h" #include "HeaderGlobals.h" -#include "Coercion.h" +#include "PropagateTypes.h" #include "Load.h" #include "Visitor.h" #include "BackLLVM.h" @@ -17,7 +16,7 @@ extern Program *program; DataType FunctionCall::getDataType() { if (dt == BuildTypes::undefinedType) { - // is a cast or constructor? + // is a constructor? this can occur while running PropagateTypes. dt = buildTypes->getType(ident.getFullName()); if (parameters->getNumParams() <= 1 && dt != BuildTypes::undefinedType) { return dt; @@ -37,88 +36,6 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock RobDbgInfo.emitLocation(this); string name = ident.getFullName(); - /* check if it is a constructor or cast call: - - cast if the function name is a type, e.g., int8(x), and the call has one argument - - constructor if the function name is a type and the call has no argument - */ - - DataType adt = buildTypes->getType(name); - if (adt != BuildTypes::undefinedType) { - dt = adt; - unsigned p = parameters->getNumParams(); - // call with only one parameter is a cast - if (p == 1) { - Node *param = parameters->getParamElement(0); - Cast ca(dt, param); - ca.setScope(this); - if (!param->getScope()) - param->setScope(&ca); - return ca.generate(func, block, allocblock); - - } else if (p == 0) { // it's a constructor - // alloc - Builder->SetInsertPoint(block); - Value *var = leftValue->getLLVMValue(func); - if (var == NULL) { - // is a new left var - Builder->SetInsertPoint(allocblock); - var = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, 0, - leftValue->getName()); - leftValue->setAlloca(var); - leftValue->setDataType(dt); - if (debug_info) - RobDbgInfo.declareVar(leftValue, var, allocblock); - } - vector args; - args.push_back(var); - - // find the user type or interface - Node *type = findSymbol(name); - if (!type) - return NULL; - - // if calling a constructor of an interface, emit code to bind it - if (buildTypes->isInterface(type->getDataType())) { - dt = type->getDataType(); - - Node *scope = leftValue->getScope(); - UserType *parent= dynamic_cast(scope); - const string toInjection = parent ? - parent->getName() + "." + leftValue->getName() : - leftValue->getName(); - - const string injectFuncName = ":get_injection_for_" + toInjection; - Node *funcNode = findSymbol(injectFuncName); - FunctionBase *funcDecl = dynamic_cast(funcNode); - if (!funcDecl) { - funcDecl = new FunctionDecl(dt, injectFuncName, new FunctionParams()); - funcDecl->setReturnIsPointer(true); - funcDecl->setScope(program); - funcDecl->generate(NULL, NULL, global_alloc); - program->addSymbol(funcDecl); - } - return Builder->CreateCall(funcDecl->getLLVMFunction()); - - } else { - // call the init constructor - Node *fsymbol = type->findMember("init"); - assert(fsymbol && "the init method for the type must exists"); - - FunctionBase *initfunc = dynamic_cast(fsymbol); - Builder->SetInsertPoint(block); - - if (initfunc->needsParent()) { - Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); - Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); - args.push_back(ptr); - } - - CallInst *c = Builder->CreateCall(initfunc->getLLVMFunction(), ArrayRef(args)); - return NULL; - } - } - } - if (!symbol) symbol = ident.getSymbol(getScope(), false); @@ -167,10 +84,11 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock } vector args; - for (int i = 0, j = 0; i < parameters->getNumParams(); i++, j++) { + vector dataTypes; + for (int i = 0; i < parameters->getNumParams(); i++) { Node *param = parameters->getParamElement(i); DataType call_dt = param->getDataType(); - DataType def_dt = fsymbol->getParameters().getParamType(j); + DataType def_dt = fsymbol->getParameters().getParamType(i); Value *valor = param->generate(func, block, allocblock); if (!valor) @@ -200,11 +118,10 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock Value *indexList[2] = {zero, zero}; Value *ptr = Builder->CreateGEP(param->getLLVMType(), valor, ArrayRef(indexList), "gep"); valor = ptr; - } else { - Type *pty = buildTypes->llvmType(def_dt); - valor = Coercion::Convert(valor, pty, block, this); } - args.push_back(valor); + + args.insert(args.begin() + i, valor); + dataTypes.insert(dataTypes.begin() + i, def_dt); // add a size parameter after each array, or .rows and .cols for matrixes if (buildTypes->isArrayOrMatrix(call_dt)) { @@ -218,12 +135,12 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock for(const string& p: params) { string pname = param->getName() + p; - Load ld(pname); + Load ld(Identifier(pname, param->getLoc())); ld.setScope(func); - valor = ld.generate(func, block, allocblock); - valor = Coercion::Convert(valor, buildTypes->llvmType(tint32), block, this); - args.push_back(valor); - j++; + Node *coerced = PropagateTypes::coerceTo(&ld, tint32u); + Value *value = coerced->generate(func, block, allocblock); + args.push_back(value); + dataTypes.push_back(coerced->getDataType()); } } } @@ -233,17 +150,22 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock if (stemSymbol->isPointerToPointer()) stem = Builder->CreateLoad(stem->getType()->getPointerTo(), stem, "defer"); args.push_back(stem); + dataTypes.push_back(stemSymbol->getDataType()); } else if (fsymbol->getThisArgDt() != BuildTypes::undefinedType) { // calling a function of the type itself, without stem Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); args.push_back(ptr); + dataTypes.push_back(fsymbol->getThisArgDt()); } ArrayRef argsRef(args); Builder->SetInsertPoint(allocblock); Value *vfunc = symbol->getLLVMValue(func); + if (!vfunc) { + return NULL; //FIXME:?? + } Function *cfunc = dyn_cast(vfunc); // symbol->getLLVMValue above can emit another location (preGenerate of the @@ -271,14 +193,27 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock codeAddrSpace, inject_name, mainmodule); intf_cfunc->setDSOLocal(true); intf_cfunc->setCallingConv(CallingConv::C); + intf_cfunc->addFnAttr(Attribute::AlwaysInline); } cfunc = intf_cfunc; } Builder->SetInsertPoint(block); - return Builder->CreateCall(cfunc, argsRef); + CallInst *call = Builder->CreateCall(cfunc, argsRef); + + // set signedness + if (cfunc->hasRetAttribute(Attribute::ZExt)) + call->addRetAttr(Attribute::ZExt); + int i = 0; + for(DataType adt : dataTypes) { + if (buildTypes->isUnsignedDataType(adt)) + call->addParamAttr(i, Attribute::ZExt); + i++; + } + + return call; } -void FunctionCall::accept(Visitor& v) { - v.visit(*this); +Node* FunctionCall::accept(Visitor& v) { + return v.visit(*this); } diff --git a/src/FunctionCall.h b/src/FunctionCall.h index 7320a12..28d3b43 100644 --- a/src/FunctionCall.h +++ b/src/FunctionCall.h @@ -14,7 +14,7 @@ class FunctionCall: public Node { Variable *leftValue = NULL; public: - FunctionCall(const string& name, ParamsCall *pc): ident(name) { + FunctionCall(const string& name, ParamsCall *pc, location_t loc): Node(loc), ident(name, loc) { parameters = pc; node_children.reserve(pc->getNumParams()); node_children.insert(end(node_children), pc->getParameters().begin(), @@ -29,9 +29,13 @@ class FunctionCall: public Node { leftValue = symbol; } - std::vector const& getParameters() { + std::vector& getParameters() { return parameters->getParameters(); } - void accept(Visitor& v) override; + Node* accept(Visitor& v) override; + + const string getName() const override { + return ident.getFullName(); + } }; diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 6e09210..020375b 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -4,7 +4,7 @@ void FunctionBase::addThisArgument(DataType dt) { thisArgDt = dt; - Variable *fp = new Variable(":this", dt); + Variable *fp = new Variable(":this", dt, this->getLoc()); fp->setScope(this); parameters->append(fp); symbols[fp->getName()] = fp; @@ -20,14 +20,14 @@ bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { for (int i = 0; i < parameters->getParameters().size(); i++) { DataType dt = parameters->getParamType(i); Type *atype = buildTypes->llvmType(dt); - if (buildTypes->isComplex(dt) || buildTypes->isArrayOrMatrix(dt)) { - atype = atype->getPointerTo(); - } if (!atype) { yyerrorcpp(string_format("Type %s for argument %s is not defined.", buildTypes->name(dt), parameters->getParamName(i).c_str()), this); valid = false; } else { + if (buildTypes->isComplex(dt) || buildTypes->isArrayOrMatrix(dt)) { + atype = atype->getPointerTo(); + } argsty.push_back(atype); } } @@ -36,12 +36,47 @@ bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { void FunctionBase::addParentArgument(DataType dt) { parentArgDt = dt; - Variable *fp = new Variable(":parent", dt); + Variable *fp = new Variable(":parent", dt, this->getLoc()); fp->setScope(this); parameters->append(fp); symbols[fp->getName()] = fp; } +void FunctionBase::addPseudoParameters() { + // add a size parameter after each array, or .rows and .cols for matrixes + std::vector const& vparams = this->parameters->getParameters(); + for (int i = 0; i < vparams.size(); ++i) { + Variable *p = vparams[i]; + + DataType pdt = p->getDataType(); + if (buildTypes->isArrayOrMatrix(pdt)) { + vector pseudos; + if (buildTypes->isArray(pdt)) + pseudos.push_back("size"); + else if (buildTypes->isMatrix(pdt)) { + pseudos.push_back("rows"); + pseudos.push_back("cols"); + } + + for(const string& s: pseudos) { + //TODO: There is something better than fix this to Int32? Fix here and in FunctionCall::generate + string spname = p->getName() + "." + s; + Variable *sp = new Variable(spname, tint32u, p->getLoc()); + this->parameters->append(sp); + + // add a pseudo symbol to resolve to pname.s + p->addSymbol(s, sp); + } + + // ParamMatrix need to know the number of cols to compute element indexes + if (buildTypes->isMatrix(pdt)) { + if (ParamMatrix *pm = dynamic_cast(p)) + pm->addSymbol("cols", vparams.back()); + } + } + } +} + Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocblock) { Node *symbol = findSymbol(name); @@ -64,6 +99,22 @@ Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocbloc nfunc->setDSOLocal(true); nfunc->setCallingConv(CallingConv::C); + if (attrInline) + nfunc->addFnAttr(Attribute::AlwaysInline); + + if (buildTypes->isUnsignedDataType(dt)) + nfunc->addRetAttr(Attribute::ZExt); + + unsigned Idx = 0; + for (auto &Arg : nfunc->args()) { + Variable *fp = parameters->getParameters()[Idx]; + DataType ptype = fp->getDataType(); + + if (buildTypes->isUnsignedDataType(ptype)) + Arg.addAttr(Attribute::ZExt); + Idx++; + } + func = nfunc; return func; } diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index d9f4967..1b37d5c 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -14,6 +14,7 @@ class FunctionBase: public NamedNode { bool constructor = false; bool external = false; bool returnIsPointer = false; + bool attrInline = false; DataType thisArgDt = BuildTypes::undefinedType; Value *thisArg = NULL; DataType parentArgDt = BuildTypes::undefinedType; @@ -23,56 +24,23 @@ class FunctionBase: public NamedNode { bool validateAndGetArgsTypes(std::vector &args); public: - FunctionBase(DataType dt, string name, FunctionParams *fp) : NamedNode(name) { + FunctionBase(DataType dt, string name, FunctionParams *fp, location_t loc) : + NamedNode(name, loc) { this->dt = dt; this->parameters = fp; addPseudoParameters(); } FunctionBase(DataType dt, string name, FunctionParams *fp, vector &&stmts, - bool constructor = false) : - NamedNode(name, std::move(stmts)) { + location_t loc, bool constructor = false) : + NamedNode(name, std::move(stmts), loc) { this->dt = dt; this->parameters = fp; this->constructor = constructor; addPseudoParameters(); } - void addPseudoParameters() { - // add a size parameter after each array, or .rows and .cols for matrixes - std::vector const& vparams = this->parameters->getParameters(); - for (int i = 0; i < vparams.size(); ++i) { - Variable *p = vparams[i]; - - DataType pdt = p->getDataType(); - if (buildTypes->isArrayOrMatrix(pdt)) { - vector pseudos; - if (buildTypes->isArray(pdt)) - pseudos.push_back("size"); - else if (buildTypes->isMatrix(pdt)) { - // let it inverted here, because of the insert below (i+1) - pseudos.push_back("cols"); - pseudos.push_back("rows"); - } - - for(const string& s: pseudos) { - //TODO: There is something better than fix this to Int32? Fix here and in FunctionCall::generate - string spname = p->getName() + "." + s; - Variable *sp = new Variable(spname, tint32); - this->parameters->insert(i+1, sp); - - // add a pseudo symbol to resolve to pname.s - p->addSymbol(s, sp); - } - - // ParamMatrix need to know the number of cols to compute element indexes - if (buildTypes->isMatrix(pdt)) { - if (ParamMatrix *pm = dynamic_cast(p)) - pm->addSymbol("cols", vparams[i+2]); - } - } - } - } + void addPseudoParameters(); FunctionParams& getParameters() { return *parameters; @@ -110,6 +78,10 @@ class FunctionBase: public NamedNode { external = e; } + void setInline(bool i) { + attrInline = i; + } + bool isExternal() { return external; } @@ -156,8 +128,8 @@ class FunctionBase: public NamedNode { class FunctionDecl: public FunctionBase { public: - FunctionDecl(DataType dt, string name, FunctionParams *fp) : - FunctionBase(dt, name, fp) { + FunctionDecl(DataType dt, string name, FunctionParams *fp, location_t loc) : + FunctionBase(dt, name, fp, loc) { declaration = true; } diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index a2f7d4f..cfe9462 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -3,10 +3,9 @@ #include "BackLLVM.h" FunctionImpl::FunctionImpl(DataType dt, string name, FunctionParams *fp, vector &&stmts, - location_t ef, bool constructor) : - FunctionBase(dt, name, fp, std::move(stmts), constructor) { + location_t loc, location_t ef, bool constructor) : + FunctionBase(dt, name, fp, std::move(stmts), loc, constructor), endfunction(ef) { this->declaration = false; - this->endfunction = ef; for(auto p: fp->getParameters()) { symbols[p->getName()] = p; @@ -54,12 +53,13 @@ bool FunctionImpl::preGenerate() { attrs.addAttribute("frame-pointer", "all"); attrs.addAttribute("stack-protector-buffer-size", "8"); - if ((name == "init") || - (node_children.size() == 1)) { + if (attrInline) { // inline constructors and functions with only one node. // TODO: Check the resulting binary size. + //if (!debug_info) + attrs.addAttribute(Attribute::AlwaysInline); + } else if (node_children.size() == 1) attrs.addAttribute(Attribute::InlineHint); - } if (name == "__vectors") { // FIXME: remove after adding functions attributes to language func->setSection(".vectors"); @@ -68,6 +68,9 @@ bool FunctionImpl::preGenerate() { func->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); func->setCallingConv(CallingConv::C); + if (buildTypes->isUnsignedDataType(dt)) + func->addRetAttr(Attribute::ZExt); + if (debug_info && !declaration) { funit = DBuilder->createFile(RobDbgInfo.cunit->getFilename(), RobDbgInfo.cunit->getDirectory()); DIScope *fcontext = funit; @@ -91,6 +94,10 @@ bool FunctionImpl::preGenerate() { Variable *fp = parameters->getParameters()[Idx]; DataType ptype = fp->getDataType(); const string& argname = fp->getName(); + Arg.setName(argname); + + if (buildTypes->isUnsignedDataType(ptype)) + Arg.addAttr(Attribute::ZExt); Type *talloc = buildTypes->llvmType(ptype); if (buildTypes->isComplex(ptype) || buildTypes->isArrayOrMatrix(ptype)) { @@ -217,8 +224,8 @@ bool FunctionImpl::validateImplementation(FunctionDecl *decl) { return result; } -void FunctionImpl::accept(Visitor& v) { - v.visit(*this); +Node* FunctionImpl::accept(Visitor& v) { + return v.visit(*this); } Value* FunctionImpl::getLLVMValue(Node *) { diff --git a/src/FunctionImpl.h b/src/FunctionImpl.h index 921f7d2..2eb434f 100644 --- a/src/FunctionImpl.h +++ b/src/FunctionImpl.h @@ -18,8 +18,8 @@ class FunctionImpl: public FunctionBase { bool preGenerate(); public: - FunctionImpl(DataType dt, string name, FunctionParams *fp, vector &&stmts, location_t ef, - bool constructor = false); + FunctionImpl(DataType dt, string name, FunctionParams *fp, vector &&stmts, location_t loc, + location_t ef, bool constructor = false); virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; @@ -27,7 +27,7 @@ class FunctionImpl: public FunctionBase { bool validateImplementation(FunctionDecl *decl); - virtual void accept(Visitor& v) override; + virtual Node* accept(Visitor& v) override; virtual Value *getLLVMValue(Node *) override; diff --git a/src/Header.h b/src/Header.h index e332111..5b78c31 100644 --- a/src/Header.h +++ b/src/Header.h @@ -15,10 +15,7 @@ #include "ArrayElements.h" #include "AttachInterrupt.h" #include "BinaryOp.h" -#include "Capsule.h" #include "CmpOp.h" -#include "Coercion.h" -#include "Delay.h" #include "Double.h" #include "Float.h" #include "Float128.h" @@ -33,15 +30,12 @@ #include "Int16.h" #include "Int32.h" #include "Int64.h" -#include "InPort.h" #include "Load.h" #include "LoadArray.h" #include "LoadMatrix.h" #include "Matrix.h" #include "MatrixElements.h" -#include "OutPort.h" #include "ParamsCall.h" -#include "Print.h" #include "Program.h" #include "Return.h" #include "Scalar.h" @@ -54,7 +48,6 @@ #include "Loop.h" #include "Pointer.h" #include "FlipOp.h" -#include "Cast.h" #include "InlineAssembly.h" #include "Interface.h" #include "UserType.h" @@ -62,5 +55,3 @@ #include "MemCopy.h" #include "BackLLVM.h" #include "NamedConst.h" - -extern Node* getNodeForIntConst(int64_t i); diff --git a/src/HeaderGlobals.h b/src/HeaderGlobals.h index 7c9e737..9c0795f 100644 --- a/src/HeaderGlobals.h +++ b/src/HeaderGlobals.h @@ -49,4 +49,3 @@ string string_format(const char *format, Args ... args) { } class Node; -extern Node* getNodeForIntConst(int64_t i); diff --git a/src/Identifier.cpp b/src/Identifier.cpp index 236e4a7..8e93a39 100644 --- a/src/Identifier.cpp +++ b/src/Identifier.cpp @@ -29,7 +29,7 @@ Node* Identifier::getSymbol(Node *scope, bool validate) { Identifier Identifier::getStem() { assert(complex && "identifier is not complex."); size_t last = ident.find_last_of('.'); - return ident.substr(0, last); + return Identifier(ident.substr(0, last), this->getLoc()); } string const Identifier::getLastName() const { diff --git a/src/Identifier.h b/src/Identifier.h index 2b0e810..bf7581e 100644 --- a/src/Identifier.h +++ b/src/Identifier.h @@ -9,7 +9,8 @@ class Identifier: public SourceLocation { bool complex; public: - Identifier(const string& ident): ident(ident) { + Identifier(const string& ident, location_t loc): SourceLocation(loc) { + this->ident = ident; complex = ident.find('.') != string::npos; } diff --git a/src/If.cpp b/src/If.cpp index edb752e..5cb943f 100644 --- a/src/If.cpp +++ b/src/If.cpp @@ -3,15 +3,15 @@ #include "FunctionImpl.h" #include "Visitor.h" -If::If(Node *e, vector &&tst): expr(e) { +If::If(Node *e, vector &&tst, location_t loc): Node(loc), expr(e) { addChild(expr); - thenst = new Node(std::move(tst)); + thenst = new Node(std::move(tst), loc); addChild(thenst); elsest = NULL; } -If::If(Node *e, vector &&tst, vector &&est): If(e, std::move(tst)) { - elsest = new Node(std::move(est)); +If::If(Node *e, vector &&tst, vector &&est, location_t loc): If(e, std::move(tst), loc) { + elsest = new Node(std::move(est), loc); addChild(elsest); } @@ -55,6 +55,6 @@ Value *If::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbloc return mergb; } -void If::accept(Visitor& v) { - v.visit(*this); +Node* If::accept(Visitor& v) { + return v.visit(*this); } diff --git a/src/If.h b/src/If.h index a0d2398..a46ccce 100644 --- a/src/If.h +++ b/src/If.h @@ -8,8 +8,8 @@ class If: public Node { Node *thenst; Node *elsest; public: - If(Node *e, vector &&tst); - If(Node *e, vector &&tst, vector &&est); - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - virtual void accept(Visitor& v) override; + If(Node *e, vector &&tst, location_t loc); + If(Node *e, vector &&tst, vector &&est, location_t loc); + virtual Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + virtual Node* accept(Visitor& v) override; }; diff --git a/src/InPort.cpp b/src/InPort.cpp deleted file mode 100644 index 182f6f3..0000000 --- a/src/InPort.cpp +++ /dev/null @@ -1,18 +0,0 @@ - -#include "InPort.h" - -Value *InPort::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - /*vector args; - - Int8 prt(atoi(port.c_str())); - Value *v = prt.generate(func, block, allocblock); - //v = Coercion::Convert(v, Type::getInt8Ty(global_context)); - args.push_back(v); - - ArrayRef argsRef(args); - return CallInst::Create(analogRead, argsRef, "", block);*/ - - //TODO: Implement a new way of reading ports - return NULL; -} - diff --git a/src/InPort.h b/src/InPort.h deleted file mode 100644 index b0c3db1..0000000 --- a/src/InPort.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __INPORT_H__ -#define __INPORT_H__ -#include "Node.h" -#include "Int8.h" - -class InPort: public Node { -private: - string port; -public: - InPort(const char *p): port(p) {} - - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); - -}; - -#endif diff --git a/src/InlineAssembly.h b/src/InlineAssembly.h index 9dae37d..95e94d1 100644 --- a/src/InlineAssembly.h +++ b/src/InlineAssembly.h @@ -7,6 +7,6 @@ class InlineAssembly: public Node { private: string assembly; public: - InlineAssembly(const char *a): assembly(a) { } + InlineAssembly(const char *a, location_t loc): Node(loc), assembly(a) { } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/Int1.cpp b/src/Int1.cpp index a19f7ff..6781a5a 100644 --- a/src/Int1.cpp +++ b/src/Int1.cpp @@ -3,5 +3,5 @@ Value *Int1::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt1Ty(global_context), number); + return ConstantInt::get(Type::getInt1Ty(global_context), value); } diff --git a/src/Int1.h b/src/Int1.h index 06874c1..edfa329 100644 --- a/src/Int1.h +++ b/src/Int1.h @@ -5,11 +5,11 @@ class Int1: public Node { private: - char number; + bool value; public: - Int1(char n): number(n) {} - char getNumber() const { return number; } + Int1(bool v, location_t loc): Node(loc), value(v) {} + bool getValue() const { return value; } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; virtual bool isConstExpr() override { diff --git a/src/Int16.cpp b/src/Int16.cpp index 8acf1a9..244eade 100644 --- a/src/Int16.cpp +++ b/src/Int16.cpp @@ -2,5 +2,9 @@ #include "Int16.h" Value *Int16::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt16Ty(global_context), number, IsSigned); + return ConstantInt::get(Type::getInt16Ty(global_context), number, true); +} + +Value *UInt16::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt16Ty(global_context), number, false); } diff --git a/src/Int16.h b/src/Int16.h index 6f427a5..e53df30 100644 --- a/src/Int16.h +++ b/src/Int16.h @@ -1,14 +1,14 @@ -#ifndef __INT16_H__ -#define __INT16_H__ + +#pragma once + #include "Node.h" class Int16: public Node { private: short number; - bool IsSigned; public: - Int16(short n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + Int16(short n, location_t loc): Node(loc), number(n) {} short getNumber() const { return number; } @@ -24,4 +24,23 @@ class Int16: public Node { }; -#endif +class UInt16: public Node { +private: + unsigned short number; + +public: + UInt16(unsigned short n, location_t loc): Node(loc), number(n) {} + + unsigned short getNumber() const { return number; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tint16u; + } + +}; diff --git a/src/Int32.cpp b/src/Int32.cpp index 84b7a67..0dcfc54 100644 --- a/src/Int32.cpp +++ b/src/Int32.cpp @@ -2,5 +2,9 @@ #include "Int32.h" Value *Int32::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt32Ty(global_context), number, IsSigned); + return ConstantInt::get(Type::getInt32Ty(global_context), number, true); +} + +Value *UInt32::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt32Ty(global_context), number, false); } diff --git a/src/Int32.h b/src/Int32.h index a80bb25..2fddf56 100644 --- a/src/Int32.h +++ b/src/Int32.h @@ -6,10 +6,9 @@ class Int32: public Node { private: int number; - bool IsSigned; public: - Int32(int n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + Int32(int n, location_t loc): Node(loc), number(n) {} int getNumber() const { return number; } @@ -23,3 +22,23 @@ class Int32: public Node { return tint32; } }; + +class UInt32: public Node { +private: + unsigned int number; + +public: + UInt32(unsigned int n, location_t loc): Node(loc), number(n) {} + + unsigned int getNumber() const { return number; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tint32u; + } +}; diff --git a/src/Int64.cpp b/src/Int64.cpp index 86523dd..21663d8 100644 --- a/src/Int64.cpp +++ b/src/Int64.cpp @@ -2,5 +2,9 @@ #include "Int64.h" Value *Int64::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt64Ty(global_context), number, IsSigned); + return ConstantInt::get(Type::getInt64Ty(global_context), number, true); +} + +Value *UInt64::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + return ConstantInt::get(Type::getInt64Ty(global_context), number, false); } diff --git a/src/Int64.h b/src/Int64.h index 4f323c7..907f857 100644 --- a/src/Int64.h +++ b/src/Int64.h @@ -5,13 +5,12 @@ class Int64: public Node { private: - int number; - bool IsSigned; + int64_t number; public: - Int64(int n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + Int64(int64_t n, location_t loc): Node(loc), number(n) {} - int getNumber() const { return number; } + int64_t getNumber() const { return number; } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; @@ -23,3 +22,23 @@ class Int64: public Node { return tint64; } }; + +class UInt64: public Node { +private: + uint64_t number; + +public: + UInt64(uint64_t n, location_t loc): Node(loc), number(n) {} + + uint64_t getNumber() const { return number; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } + + virtual DataType getDataType() override { + return tint64u; + } +}; diff --git a/src/Int8.cpp b/src/Int8.cpp index a14087c..bd95f32 100644 --- a/src/Int8.cpp +++ b/src/Int8.cpp @@ -3,5 +3,10 @@ Value *Int8::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantInt::get(Type::getInt8Ty(global_context), number, IsSigned); + return ConstantInt::get(Type::getInt8Ty(global_context), number, true); +} + +Value *UInt8::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) +{ + return ConstantInt::get(Type::getInt8Ty(global_context), number, false); } diff --git a/src/Int8.h b/src/Int8.h index 3867bad..f2a556c 100644 --- a/src/Int8.h +++ b/src/Int8.h @@ -6,10 +6,11 @@ class Int8: public Node { private: int8_t number; - bool IsSigned; public: - Int8(int8_t n, bool IsSigned = false): number(n), IsSigned(IsSigned) {} + Int8(int8_t n, location_t loc): Node(loc), number(n) { + dt = tint8; + } int8_t getNumber() const { return number; } @@ -18,8 +19,22 @@ class Int8: public Node { virtual bool isConstExpr() override { return true; } +}; + +class UInt8: public Node { +private: + uint8_t number; - virtual DataType getDataType() override { - return tint8; +public: + UInt8(uint8_t n, location_t loc): Node(loc), number(n) { + dt = tint8u; } -}; + + uint8_t getNumber() const { return number; } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual bool isConstExpr() override { + return true; + } +}; \ No newline at end of file diff --git a/src/Interface.h b/src/Interface.h index 5920ae5..a6f6eca 100644 --- a/src/Interface.h +++ b/src/Interface.h @@ -8,11 +8,12 @@ class Interface: public NamedNode { void createDataType(); public: - Interface(const string& name) : NamedNode(name) { + Interface(const string& name, location_t loc) : NamedNode(name, loc) { createDataType(); } - Interface(const string& name, vector stmts): NamedNode(name, std::move(stmts)) { + Interface(const string& name, vector stmts, location_t loc): + NamedNode(name, std::move(stmts), loc) { createDataType(); } diff --git a/src/Language.l b/src/Language.l index 0cb9a19..bf1ac60 100644 --- a/src/Language.l +++ b/src/Language.l @@ -117,14 +117,19 @@ ID {A}({A}|{D})* return TOK_LDOUBLE; } "0x"[0-9a-fA-F]+ { char *aux = strndup(yytext, yyleng); - yylval->nint = strtoll(aux, NULL, 16); + yylval->unint = strtoull(aux, NULL, 16); free(aux); - return TOK_INTEGER; } + return TOK_UINTEGER; } "0b"[0-1]+ { char *aux = strndup(yytext+2, yyleng-2); - yylval->nint = strtoll(aux, NULL, 2); + yylval->unint = strtoull(aux, NULL, 2); free(aux); - return TOK_INTEGER; } + return TOK_UINTEGER; } + +[0-9]+[Uu] { char *aux = strndup(yytext, yyleng-1); + yylval->unint = strtoull(aux, NULL, 10); + free(aux); + return TOK_UINTEGER; } [0-9]+ { char *aux = strndup(yytext, yyleng); yylval->nint = strtoll(aux, NULL, 10); diff --git a/src/Language.y b/src/Language.y index a1ebf6c..2bbd4af 100644 --- a/src/Language.y +++ b/src/Language.y @@ -31,6 +31,7 @@ %type TOK_IDENTIFIER TOK_XIDENTIFIER ident_or_xident %type TOK_INTEGER TOK_CHAR qualifier bind_scope +%type TOK_UINTEGER %type TOK_FLOAT %type TOK_DOUBLE %type TOK_LDOUBLE @@ -77,8 +78,13 @@ use : TOK_USE TOK_IDENTIFIER ';' { $$ = NULL; } +use : TOK_USE TOK_XIDENTIFIER ';' { + parseUseFile($2, @TOK_USE); + $$ = NULL; +} + enum : TOK_ENUM TOK_IDENTIFIER[id] '{' enum_items '}' { - $$ = new Enum($id, std::move(*$enum_items)); + $$ = new Enum($id, std::move(*$enum_items), @id); } enum_items : enum_items[items] ',' enum_item { @@ -92,23 +98,30 @@ enum_items : enum_item { } enum_item : TOK_IDENTIFIER[id] '=' TOK_INTEGER[intg] { - $$ = new NamedConst($id, new Int8($intg)); + $$ = new NamedConst($id, new Int8($intg, @intg), @id); +} + +enum_item : TOK_IDENTIFIER[id] '=' '-' TOK_INTEGER[intg] { + $$ = new NamedConst($id, new Int8($intg * -1, @intg), @id); +} + +enum_item : TOK_IDENTIFIER[id] '=' TOK_UINTEGER[intg] { + $$ = new NamedConst($id, new UInt8($intg, @intg), @id); } enum_item : TOK_IDENTIFIER[id] { - $$ = new NamedConst($id); + $$ = new NamedConst($id, @id); } function : function_decl | function_impl function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' ';' { - $$ = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params); - $$->setLocation(@type); + $$ = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params, @id); } function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' '{' stmts '}'[ef] { FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, - std::move(*$stmts), @ef); + std::move(*$stmts), @id, @ef); func->setLocation(@type); $$ = func; } @@ -143,7 +156,7 @@ function_params: %empty { } function_param : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] { - $$ = new Variable($id, buildTypes->getType($type, true)); + $$ = new Variable($id, buildTypes->getType($type, true), @type); } function_param : TOK_IDENTIFIER[type] '[' ']' TOK_IDENTIFIER[id] { @@ -155,19 +168,16 @@ function_param : TOK_IDENTIFIER[type] '[' ']' '[' ']' TOK_IDENTIFIER[id] { } register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT expr ';' { - $$ = new Pointer($name, buildTypes->getType($type, true), $5); + $$ = new Pointer($name, buildTypes->getType($type, true), $5, @name); $$->setQualifier(qvolatile); - $$->setLocation(@name); } -interface : TOK_INTF TOK_IDENTIFIER '{' interface_decls[intf] '}' { - $$ = new Interface($TOK_IDENTIFIER, std::move(*$intf)); - $$->setLocation(@TOK_INTF); +interface : TOK_INTF TOK_IDENTIFIER[id] '{' interface_decls[intf] '}' { + $$ = new Interface($id, std::move(*$intf), @id); } -interface : TOK_INTF TOK_IDENTIFIER '{' '}' { - $$ = new Interface($TOK_IDENTIFIER); - $$->setLocation(@TOK_INTF); +interface : TOK_INTF TOK_IDENTIFIER[id] '{' '}' { + $$ = new Interface($id, @id); } interface_decls : interface_decls function_decl { @@ -184,20 +194,17 @@ interface_decls : function_decl { interface_impl : TOK_IDENTIFIER[id] '=' TOK_IDENTIFIER[intfname] '{' type_stmts '}' { vector intf; intf.push_back($intfname); - UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(intf)); - ut->setLocation(@id); + UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(intf), @id); $$ = ut; } -type : TOK_TYPE TOK_IDENTIFIER TOK_IMPL type_impls '{' type_stmts '}' { - UserType *ut = new UserType($TOK_IDENTIFIER, std::move(*$type_stmts), std::move(*$type_impls)); - ut->setLocation(@TOK_TYPE); +type : TOK_TYPE TOK_IDENTIFIER[id] TOK_IMPL type_impls '{' type_stmts '}' { + UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(*$type_impls), @id); $$ = ut; } -type : TOK_TYPE TOK_IDENTIFIER '{' type_stmts '}' { - UserType *ut = new UserType($TOK_IDENTIFIER, std::move(*$type_stmts)); - ut->setLocation(@TOK_TYPE); +type : TOK_TYPE TOK_IDENTIFIER[id] '{' type_stmts '}' { + UserType *ut = new UserType($id, std::move(*$type_stmts), @id); $$ = ut; } @@ -229,8 +236,8 @@ type_stmt : simplevar_decl ';' | enum simplevar_decl : TOK_IDENTIFIER[id] '=' logicexpr { $$ = new Scalar($id, $logicexpr); $$->setLocation(@id); } -simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } -simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array, @id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix, @id); } bind : TOK_BIND ident_or_xident[id] TOK_TO ident_or_xident[to] bind_scope[scope] ';' { injections.insert({$to, make_pair(string($id), BindScope($scope))}); @@ -280,18 +287,18 @@ stmts : stmt { $stmt->setLocation(@stmt); } -stmt : ident_or_xident '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '+', new Int8(1))); } - | ident_or_xident '-' '-' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '-', new Int8(1))); } - | ident_or_xident '+' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '+', $4)); } - | ident_or_xident '-' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '-', $4)); } - | ident_or_xident '*' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '*', $4)); } - | ident_or_xident '/' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '/', $4)); } - | ident_or_xident '|' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '|', $4)); } - | ident_or_xident '&' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '&', $4)); } - | ident_or_xident '^' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1), '^', $4)); } - | ident_or_xident '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6);} - | ident_or_xident '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9); } - | asminline ';' { $$ = new InlineAssembly($1); $$->setLocation(@1); } +stmt : ident_or_xident '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '+', new Int8(1, @1))); } + | ident_or_xident '-' '-' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '-', new Int8(1, @1))); } + | ident_or_xident '+' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '+', $4)); } + | ident_or_xident '-' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '-', $4)); } + | ident_or_xident '*' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '*', $4)); } + | ident_or_xident '/' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '/', $4)); } + | ident_or_xident '|' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '|', $4)); } + | ident_or_xident '&' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '&', $4)); } + | ident_or_xident '^' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '^', $4)); } + | ident_or_xident '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6, @1);} + | ident_or_xident '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9, @1); } + | asminline ';' { $$ = new InlineAssembly($1, @1); } | qualifier simplevar_decl ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } | simplevar_decl ';' | complexvar_set ';' @@ -302,11 +309,11 @@ stmt : ident_or_xident '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Lo | interface_impl complexvar_set : TOK_XIDENTIFIER[id] '=' logicexpr { $$ = new Scalar($id, $logicexpr); $$->setLocation(@id); } -complexvar_set : TOK_XIDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } -complexvar_set : TOK_XIDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } +complexvar_set : TOK_XIDENTIFIER[id] '=' array { $$ = new Array($id, $array, @id); } +complexvar_set : TOK_XIDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix, @id); } returnblock : TOK_RETURN logicexpr { $$ = new Return($2); } -returnblock : TOK_RETURN { $$ = new Return(); } +returnblock : TOK_RETURN { $$ = new Return(@1); } /* * Conditional @@ -314,13 +321,11 @@ returnblock : TOK_RETURN { $$ = new Return(); } condblock : TOK_IF logicexpr '{' stmts '}' { $logicexpr->setLocation(@logicexpr); - $$ = new If($logicexpr, std::move(*$stmts)); - $$->setLocation(@TOK_IF); + $$ = new If($logicexpr, std::move(*$stmts), @TOK_IF); } condblock : TOK_IF logicexpr '{' stmts '}' elseblock { $logicexpr->setLocation(@logicexpr); - $$ = new If($logicexpr, std::move(*$stmts), std::move(*$elseblock)); - $$->setLocation(@TOK_IF); + $$ = new If($logicexpr, std::move(*$stmts), std::move(*$elseblock), @TOK_IF); } elseblock : TOK_ELSE '{' stmts '}' { $$ = $stmts; } @@ -336,19 +341,16 @@ elseblock : TOK_ELSE condblock { whileblock : TOK_WHILE logicexpr '{' stmts '}' { $logicexpr->setLocation(@logicexpr); - $$ = new While($logicexpr, std::move(*$stmts)); - $$->setLocation(@TOK_WHILE); + $$ = new While($logicexpr, std::move(*$stmts), @TOK_WHILE); } whileblock : TOK_WHILE logicexpr ';' { $logicexpr->setLocation(@logicexpr); - $$ = new While($logicexpr); - $$->setLocation(@TOK_WHILE); + $$ = new While($logicexpr, @TOK_WHILE); } whileblock : TOK_LOOP '{' stmts '}' { - $$ = new Loop(std::move(*$stmts)); - $$->setLocation(@TOK_LOOP); + $$ = new Loop(std::move(*$stmts), @TOK_LOOP); } /* @@ -374,7 +376,7 @@ logicfactor : '(' logicexpr ')' { $$ = $2; } | logicunary ; -logicunary : '!' logicfactor { $$ = new BinaryOp(new Int1(1), '-', $2); } +logicunary : '!' logicfactor { $$ = new BinaryOp(new Int1(1, @2), '-', $2); } /* * Arithmetic @@ -400,23 +402,24 @@ term2 : term2 '&' factor { $$ = new BinaryOp($1, '&', $3); } ; factor : '(' expr ')' { $$ = $2; } - | ident_or_xident { $$ = new Load($1); } - | TOK_TRUE { $$ = new Int1(1); } - | TOK_FALSE { $$ = new Int1(0); } - | TOK_CHAR { $$ = new Char($1); } - | TOK_INTEGER { $$ = getNodeForIntConst($1); } - | TOK_FLOAT { $$ = new Float($1); } - | TOK_DOUBLE { $$ = new Double($1); } - | TOK_LDOUBLE { $$ = new Float128($1); } - | ident_or_xident[id] '[' expr ']' { $$ = new LoadArray($1, $3);} - | ident_or_xident[id] '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6);} + | ident_or_xident { $$ = new Load($1, @1); } + | TOK_TRUE { $$ = new Int1(1, @1); } + | TOK_FALSE { $$ = new Int1(0, @1); } + | TOK_CHAR { $$ = new Char($1, @1); } + | TOK_INTEGER { $$ = getNodeForIntConst($1, @1); } + | TOK_UINTEGER { $$ = getNodeForUIntConst($1, @1); } + | TOK_FLOAT { $$ = new Float($1, @1); } + | TOK_DOUBLE { $$ = new Double($1, @1); } + | TOK_LDOUBLE { $$ = new Float128($1, @1); } + | ident_or_xident[id] '[' expr ']' { $$ = new LoadArray($1, $3, @id);} + | ident_or_xident[id] '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6, @id);} | call_or_cast | unary ; ident_or_xident: TOK_IDENTIFIER | TOK_XIDENTIFIER -unary : '-' factor { $$ = new BinaryOp($2, '*', getNodeForIntConst(-1)); } +unary : '-' factor { $$ = new BinaryOp($2, '*', getNodeForIntConst(-1, @factor)); } | '~' factor { $$ = new FlipOp($2); } ; @@ -425,7 +428,7 @@ call_or_cast : ident_or_xident[id] '(' paramscall ')' { $$ = new MemCopy($paramscall->getParamElement(0)); //else if buildTypes->get($id) && complex, call constructor else { - $$ = new FunctionCall($id, $paramscall); + $$ = new FunctionCall($id, $paramscall, @id); } $$->setLocation(@id); } diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index df92b1c..19b925e 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -24,7 +24,7 @@ %token TOK_LOOP TOK_WHILE %token TOK_AND TOK_OR %token TOK_IDENTIFIER TOK_XIDENTIFIER -%token TOK_CHAR +%token TOK_CHAR TOK_UINTEGER %token TOK_FLOAT TOK_DOUBLE TOK_LDOUBLE TOK_INTEGER TOK_STRING TOK_TRUE TOK_FALSE %token TOK_FINT8 TOK_FINT16 TOK_FINT32 TOK_FINT64 %token TOK_FFLOAT TOK_FDOUBLE TOK_FCHAR TOK_FLONG TOK_FUNSIGNED TOK_FBOOL @@ -39,6 +39,7 @@ char *ident; char *str; int64_t nint; + uint64_t unint; float nfloat; double ndouble; long double nldouble; diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 68201a7..1642745 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -29,8 +29,9 @@ %type function_params %type function_param -%type TOK_IDENTIFIER +%type TOK_IDENTIFIER TOK_XIDENTIFIER %type TOK_INTEGER qualifier +%type TOK_UINTEGER %printer { fprintf(yyo, "'%s'", $$); } %printer { fprintf(yyo, "'%s'", $$ ? $$->getName().c_str() : ""); } @@ -71,8 +72,13 @@ use : TOK_USE TOK_IDENTIFIER ';' { $$ = NULL; } +use : TOK_USE TOK_XIDENTIFIER ';' { + parseUseFile($2, @TOK_USE); + $$ = NULL; +} + enum : TOK_ENUM TOK_IDENTIFIER[id] '{' enum_items '}' { - $$ = new Enum($id, std::move(*$enum_items)); + $$ = new Enum($id, std::move(*$enum_items), @id); } enum_items : enum_items[items] ',' enum_item { @@ -86,24 +92,31 @@ enum_items : enum_item { } enum_item : TOK_IDENTIFIER[id] '=' TOK_INTEGER[intg] { - $$ = new NamedConst($id, new Int8($intg)); + $$ = new NamedConst($id, new Int8($intg, @intg), @id); +} + +enum_item : TOK_IDENTIFIER[id] '=' '-' TOK_INTEGER[intg] { + $$ = new NamedConst($id, new Int8($intg * -1, @intg), @id); +} + +enum_item : TOK_IDENTIFIER[id] '=' TOK_UINTEGER[intg] { + $$ = new NamedConst($id, new UInt8($intg, @intg), @id); } enum_item : TOK_IDENTIFIER[id] { - $$ = new NamedConst($id); + $$ = new NamedConst($id, @id); } function : function_decl | function_impl function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' ';' { - $$ = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params); - $$->setLocation(@type); + $$ = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params, @id); } function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' '{' stmts '}'[ef] { vector stmts; FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, - std::move(stmts), @ef); + std::move(stmts), @type, @ef); func->setExternal(true); func->setDeclaration(true); func->setLocation(@type); @@ -130,7 +143,7 @@ function_params: %empty { } function_param : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] { - $$ = new Variable($id, buildTypes->getType($type, true)); + $$ = new Variable($id, buildTypes->getType($type, true), @type); } function_param : TOK_IDENTIFIER[type] '[' ']' TOK_IDENTIFIER[id] { @@ -142,18 +155,17 @@ function_param : TOK_IDENTIFIER[type] '[' ']' '[' ']' TOK_IDENTIFIER[id] { } register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT const_expr ';' { - $$ = new Pointer($name, buildTypes->getType($type, true), $5); + $$ = new Pointer($name, buildTypes->getType($type, true), $5, @name); $$->setQualifier(qvolatile); - $$->setLocation(@name); } -interface : TOK_INTF TOK_IDENTIFIER '{' interface_decls[intf] '}' { - $$ = new Interface($TOK_IDENTIFIER, std::move(*$intf)); +interface : TOK_INTF TOK_IDENTIFIER[id] '{' interface_decls[intf] '}' { + $$ = new Interface($id, std::move(*$intf), @id); $$->setLocation(@TOK_INTF); } -interface : TOK_INTF TOK_IDENTIFIER '{' '}' { - $$ = new Interface($TOK_IDENTIFIER); +interface : TOK_INTF TOK_IDENTIFIER[id] '{' '}' { + $$ = new Interface($id, @id); $$->setLocation(@TOK_INTF); } @@ -171,21 +183,18 @@ interface_decls : function_decl { interface_impl : TOK_IDENTIFIER[id] '=' TOK_IDENTIFIER[intfname] '{' type_stmts '}' { vector intf; intf.push_back($intfname); - UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(intf)); - ut->setLocation(@id); + UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(intf), @id); $$ = ut; } -type : TOK_TYPE TOK_IDENTIFIER TOK_IMPL type_impls '{' type_stmts '}' { - UserType *ut = new UserType($TOK_IDENTIFIER, std::move(*$type_stmts), std::move(*$type_impls)); - ut->setLocation(@TOK_TYPE); +type : TOK_TYPE TOK_IDENTIFIER[id] TOK_IMPL type_impls '{' type_stmts '}' { + UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(*$type_impls), @id); ut->setDeclaration(true); $$ = ut; } -type : TOK_TYPE TOK_IDENTIFIER '{' type_stmts '}' { - UserType *ut = new UserType($TOK_IDENTIFIER, std::move(*$type_stmts)); - ut->setLocation(@TOK_TYPE); +type : TOK_TYPE TOK_IDENTIFIER[id] '{' type_stmts '}' { + UserType *ut = new UserType($id, std::move(*$type_stmts), @id); ut->setDeclaration(true); $$ = ut; } @@ -218,8 +227,8 @@ type_stmt : simplevar_decl ';' | enum simplevar_decl : TOK_IDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } -simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array); $$->setLocation(@id); } -simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array, @id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix, @id); } array : '{' elements '}' { $$ = $elements; } matrix : '{' melements '}' { $$ = $melements; } @@ -249,9 +258,10 @@ elements : elements ',' element { $1->append($3); element : expr ':' TOK_INTEGER { $$ = new ArrayElement($1, (unsigned)$3); } | expr { $$ = new ArrayElement($1, 1); } -const_expr : TOK_INTEGER { $$ = getNodeForIntConst($1); } - | TOK_TRUE { $$ = new Int1(1); } - | TOK_FALSE { $$ = new Int1(0); } +const_expr : TOK_INTEGER { $$ = getNodeForIntConst($1, @1); } + | TOK_UINTEGER { $$ = getNodeForUIntConst($1, @1); } + | TOK_TRUE { $$ = new Int1(1, @1); } + | TOK_FALSE { $$ = new Int1(0, @1); } //TODO: Add other constant nodes here! expr : const_expr @@ -261,15 +271,15 @@ expr : const_expr cast : TOK_IDENTIFIER[id] '(' ignore_param ')' { ParamsCall *pc = new ParamsCall(); - pc->append(new Node()); - $$ = new FunctionCall($id, pc); + pc->append(new Node(@id)); + $$ = new FunctionCall($id, pc, @id); $$->setLocation(@id); } constructor : TOK_IDENTIFIER[id] '(' ')' { ParamsCall *pc = new ParamsCall(); - pc->append(new Node()); - $$ = new FunctionCall($id, pc); + pc->append(new Node(@id)); + $$ = new FunctionCall($id, pc, @id); $$->setLocation(@id); } diff --git a/src/Load.cpp b/src/Load.cpp index ee5dce1..f4a3952 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -5,35 +5,43 @@ #include "Variable.h" #include "Pointer.h" +Node* Load::getIdentSymbol() { + if (!identSymbol) { + identSymbol = ident.getSymbol(getScope(), false); + } + if (!identSymbol) + yyerrorcpp("Symbol " + ident.getFullName() + " not found.", this); + return identSymbol; +} + DataType Load::getDataType() { if (dt == BuildTypes::undefinedType) { - Node *rsym = ident.getSymbol(getScope(), false); - if (rsym) { - dt = rsym->getDataType(); - } + if (getIdentSymbol()) + dt = identSymbol->getDataType(); } return dt; } Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - if (!isymbol) { - isymbol = ident.getSymbol(getScope(), false); - if (!isymbol) - isymbol = ident.getSymbol(func, false); + if (!identSymbol) { + identSymbol = ident.getSymbol(getScope(), false); + if (!identSymbol) { + identSymbol = ident.getSymbol(func, false); + //assert(false && "when this is executed?");//FIXME + } } - if (isymbol && isymbol->isConstExpr()) - return isymbol->getLLVMValue(func); + if (identSymbol && identSymbol->isConstExpr()) + return identSymbol->getLLVMValue(func); - Variable *symbol = dynamic_cast(isymbol); + Variable *symbol = dynamic_cast(identSymbol); if (!symbol) { yyerrorcpp("Symbol " + ident.getFullName() + " not found.", this); return NULL; } - dt = isymbol->getDataType(); - symbols = symbol->getSymbols(); + dt = identSymbol->getDataType(); if (block == NULL && (allocblock == NULL || allocblock == global_alloc)) { // trying to load a variable to initialize a global one. diff --git a/src/Load.h b/src/Load.h index a887718..030c62c 100644 --- a/src/Load.h +++ b/src/Load.h @@ -2,17 +2,20 @@ #include "Node.h" #include "Identifier.h" +#include "Visitor.h" class Load: public Node { private: Identifier ident; Variable *leftValue = NULL; - Node *isymbol = NULL; + Node *identSymbol = NULL; public: - Load(const char* i): ident(i) { } - Load(Identifier i): ident(i) { } - Load(Node *n): isymbol(n), ident(n->getName()) { } + Load(const char* i, location_t loc): Node(loc), ident(i, loc) { } + Load(Identifier i): Node(i.getLoc()), ident(i.getFullName(), i.getLoc()) { } + Load(Node *n): Node(n->getLoc()), ident(n->getName(), n->getLoc()) { + identSymbol = n; + } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; @@ -25,4 +28,12 @@ class Load: public Node { virtual const string getName() const override { return ident.getFullName(); } + + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } + + Node* getIdentSymbol(); + + friend class SymbolizeTree; }; diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index 597cb73..f7e8c54 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -4,7 +4,7 @@ #include "BuildTypes.h" #include "FunctionImpl.h" -LoadArray::LoadArray(const string &i, Node *pos): BaseArrayOper(i, pos, NULL) { +LoadArray::LoadArray(const string &i, Node *pos, location_t loc): BaseArrayOper(i, pos, NULL, loc) { addChild(pos); } diff --git a/src/LoadArray.h b/src/LoadArray.h index aef3660..d7d4cf7 100644 --- a/src/LoadArray.h +++ b/src/LoadArray.h @@ -10,8 +10,8 @@ class BaseArrayOper: public Node { Node *position; Node *position2; public: - BaseArrayOper(const string& i, Node *pos, Node *pos2): ident(i), position(pos), - position2(pos2) {} + BaseArrayOper(const string& i, Node *pos, Node *pos2, location_t loc): + Node(loc), ident(i, loc), position(pos), position2(pos2) {} virtual Node* getElementIndex(Node *symbol); @@ -30,7 +30,7 @@ class BaseArrayOper: public Node { class LoadArray: public BaseArrayOper { public: - LoadArray(const string& i, Node *pos); + LoadArray(const string& i, Node *pos, location_t loc); virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; diff --git a/src/LoadMatrix.h b/src/LoadMatrix.h index 97037ea..2d63e11 100644 --- a/src/LoadMatrix.h +++ b/src/LoadMatrix.h @@ -8,7 +8,7 @@ class LoadMatrix: public LoadArray { public: - LoadMatrix(const string &i, Node *p1, Node *p2): LoadArray(i, p1) { + LoadMatrix(const string &i, Node *p1, Node *p2, location_t loc): LoadArray(i, p1, loc) { this->position2 = p2; addChild(p2); } @@ -25,7 +25,7 @@ class LoadMatrix: public LoadArray { if (const Matrix *mx = dynamic_cast(symbol)) { rows = mx->getRows(); cols = mx->getCols(); - mcols = getNodeForIntConst(cols); + mcols = getNodeForIntConst(cols, matrix->getLoc()); } else if (Node *s = symbol->findSymbol("cols", false)) { mcols = new Load(s); mcols->setScope(symbol); diff --git a/src/Loop.cpp b/src/Loop.cpp index 98e03db..11b657c 100644 --- a/src/Loop.cpp +++ b/src/Loop.cpp @@ -2,7 +2,7 @@ #include "Loop.h" #include "FunctionImpl.h" -Loop::Loop(vector &&stms) : Node(std::move(stms)) { +Loop::Loop(vector &&stms, location_t loc) : Node(std::move(stms), loc) { } Value *Loop::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { diff --git a/src/Loop.h b/src/Loop.h index ddf8cef..25579e2 100644 --- a/src/Loop.h +++ b/src/Loop.h @@ -5,7 +5,7 @@ class Loop: public Node { public: - Loop(vector &&stmts); + Loop(vector &&stmts, location_t loc); virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 0db0d77..27a9b45 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -1,16 +1,17 @@ #include "Matrix.h" -#include "Coercion.h" #include "Array.h" #include "Visitor.h" #include "BackLLVM.h" #include "FunctionImpl.h" #include "NamedConst.h" -Matrix::Matrix(const char *n, MatrixElements *me) : Variable(n), melements(me) { - NamedConst *rows = new NamedConst("rows", getNodeForIntConst(me->getRowCount())); - NamedConst *cols = new NamedConst("cols", getNodeForIntConst(me->getColumnCount())); +Matrix::Matrix(const char *n, MatrixElements *me, location_t loc) : Variable(n, loc), melements(me) { + NamedConst *rows = new NamedConst("rows", getNodeForUIntConst(me->getRowCount(), this->getLoc()), loc); + NamedConst *cols = new NamedConst("cols", getNodeForUIntConst(me->getColumnCount(), this->getLoc()), loc); addChild(rows); + addSymbol("rows", rows); addChild(cols); + addSymbol("cols", cols); } Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { @@ -35,7 +36,6 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Value *val = elValue->generate(func, block, allocblock); if (!val) return NULL; - val = Coercion::Convert(val, matrixType->getElementType(), block, elValue); if (!dyn_cast(val)) allConst = false; for (int l=0; l < k->count; l++) @@ -105,8 +105,8 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc return alloc; } -void Matrix::accept(Visitor& v) { - v.visit(*this); +Node* Matrix::accept(Visitor& v) { + return v.visit(*this); } @@ -123,7 +123,7 @@ void Matrix::createDataType() { //Get Type of elements in Vector of Elements, and define as I. element_dt = melements->getMatrixType(); dt = buildTypes->getArrayType(buildTypes->name(element_dt), - *this->getLoct(), 2, true); + this->getLoc(), 2, true); Type* I = buildTypes->llvmType(element_dt); // The matrix type and size diff --git a/src/Matrix.h b/src/Matrix.h index 743c118..31456f3 100644 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -8,7 +8,7 @@ class ParamMatrix: public Variable { private: DataType element_dt; public: - ParamMatrix(const string& n, string element_dt_name, location_t loc): Variable(n) { + ParamMatrix(const string& n, string element_dt_name, location_t loc): Variable(n, loc) { this->element_dt = buildTypes->getType(element_dt_name, true); this->dt = buildTypes->getArrayType(element_dt_name, loc, 2, true); } @@ -24,7 +24,7 @@ class Matrix: public Variable { unsigned int cols = 0; public: - Matrix(const char *n, MatrixElements *me); + Matrix(const char *n, MatrixElements *me, location_t loc); virtual Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; @@ -32,12 +32,16 @@ class Matrix: public Variable { return melements->getElements(); } - void accept(Visitor& v) override; + Node* accept(Visitor& v) override; virtual Type *getLLVMType() override; DataType getDataType() override; + DataType getElementDataType() { + return element_dt; + } + int getRows() const { return rows; } diff --git a/src/MemCopy.cpp b/src/MemCopy.cpp index 5824f5e..33cfc3d 100644 --- a/src/MemCopy.cpp +++ b/src/MemCopy.cpp @@ -28,7 +28,7 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo DataType eldt = buildTypes->getArrayElementType(dt); TypeSize eltsize = dl.getTypeAllocSize(buildTypes->llvmType(eldt)); ConstantInt *elbytes = ConstantInt::get(Type::getInt32Ty(global_context), eltsize); - Load ld("size"); + Load ld("size", this->getLoc()); ld.setScope(expr); nelem = ld.generate(func, allocblock, allocblock); Builder->SetInsertPoint(allocblock); @@ -38,9 +38,9 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo DataType eldt = buildTypes->getArrayElementType(dt); TypeSize eltsize = dl.getTypeAllocSize(buildTypes->llvmType(eldt)); ConstantInt *elbytes = ConstantInt::get(Type::getInt32Ty(global_context), eltsize); - Load ldrows("rows"); + Load ldrows("rows", this->getLoc()); ldrows.setScope(expr); - Load ldcols("cols"); + Load ldcols("cols", this->getLoc()); ldcols.setScope(expr); Builder->SetInsertPoint(allocblock); Value *nrows = ldrows.generate(func, allocblock, allocblock); diff --git a/src/MemCopy.h b/src/MemCopy.h index b30d6f2..d41c461 100644 --- a/src/MemCopy.h +++ b/src/MemCopy.h @@ -3,6 +3,7 @@ #include "Node.h" #include "Variable.h" +#include "Visitor.h" class MemCopy: public Node { private: @@ -10,7 +11,7 @@ class MemCopy: public Node { Variable *leftValue = NULL; public: - MemCopy(Node *expr) { + MemCopy(Node *expr): Node(expr->getLoc()) { addChild(expr); this->expr = expr; } @@ -22,4 +23,14 @@ class MemCopy: public Node { virtual const string getName() const override { return leftValue->getName(); } + + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } + + DataType getDataType() override { + return expr->getDataType(); + } + + friend class SymbolizeTree; }; diff --git a/src/NamedConst.h b/src/NamedConst.h index 0c44e23..1b7cd9f 100644 --- a/src/NamedConst.h +++ b/src/NamedConst.h @@ -8,9 +8,9 @@ class NamedConst: public NamedNode { Node *value = NULL; public: - NamedConst(const char *name) : NamedNode(name) {} + NamedConst(const char *name, location_t loc) : NamedNode(name, loc) {} - NamedConst(const char *name, Node *value) : NamedNode(name), value(value) { + NamedConst(const char *name, Node *value, location_t loc) : NamedNode(name, loc), value(value) { dt = value->getDataType(); } diff --git a/src/Node.cpp b/src/Node.cpp index 611f872..2ff73a1 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -8,15 +8,15 @@ Node::~Node() {} -Node::Node(vector &&children) : node_children(children) { +Node::Node(vector &&children, location_t loc) : SourceLocation(loc), node_children(children) { } std::vector const& Node::children() const { return node_children; } -void Node::accept(Visitor& v) { - v.visit(*this); +Node* Node::accept(Visitor& v) { + return v.visit(*this); } Node* Node::findMember(const string& name) { @@ -102,13 +102,24 @@ Type* Node::getLLVMType() { return taux; } -Node* getNodeForIntConst(int64_t i) { +Node* getNodeForUIntConst(uint64_t i, location_t loc) { + if (i <= UCHAR_MAX) + return new UInt8(i, loc); + else if (i <= USHRT_MAX) + return new UInt16(i, loc); + else if (i <= UINT_MAX) + return new UInt32(i, loc); + else + return new UInt64(i, loc); +} + +Node* getNodeForIntConst(int64_t i, location_t loc) { if (i >= SCHAR_MIN && i <= SCHAR_MAX) - return new Int8(i); + return new Int8(i, loc); else if (i >= SHRT_MIN && i <= SHRT_MAX) - return new Int16(i); + return new Int16(i, loc); else if (i >= INT_MIN && i <= INT_MAX) - return new Int32(i); + return new Int32(i, loc); else - return new Int64(i); + return new Int64(i, loc); } diff --git a/src/Node.h b/src/Node.h index 56a19b7..599f302 100644 --- a/src/Node.h +++ b/src/Node.h @@ -20,8 +20,8 @@ class Node : public SourceLocation { bool pointerToPointer = false; public: - Node() {} - Node(vector &&children); + Node(location_t l) : SourceLocation(l) {} + Node(vector &&children, location_t l); virtual ~Node(); @@ -35,7 +35,7 @@ class Node : public SourceLocation { virtual std::vector const& children() const; - virtual void accept(Visitor &); + virtual Node* accept(Visitor &); virtual bool hasName() { return false; @@ -57,7 +57,7 @@ class Node : public SourceLocation { void addChild(Node *n, bool prepend = false); - map const& getSymbols(); + virtual map const& getSymbols(); virtual void addSymbol(const string& label, NamedNode *nm); virtual void addSymbol(NamedNode *nm); @@ -97,6 +97,7 @@ class Node : public SourceLocation { friend class UserType; friend class Program; friend class MemCopy; + friend class PropagateTypes; }; class NamedNode: public Node { @@ -104,10 +105,10 @@ class NamedNode: public Node { string name; public: - NamedNode(const string &name) : name(name) {} + NamedNode(const string &name, location_t loc) : Node(loc), name(name) {} - NamedNode(const string &name, vector &&children) : - Node(std::move(children)), name(name) {} + NamedNode(const string &name, vector &&children, location_t loc) : + Node(std::move(children), loc), name(name) {} virtual const string getName() const override { return name; @@ -121,3 +122,6 @@ class NamedNode: public Node { return true; } }; + +extern Node* getNodeForIntConst(int64_t, location_t); +extern Node* getNodeForUIntConst(uint64_t, location_t); diff --git a/src/OutPort.cpp b/src/OutPort.cpp deleted file mode 100644 index acf45f9..0000000 --- a/src/OutPort.cpp +++ /dev/null @@ -1,29 +0,0 @@ - -#include "OutPort.h" - -OutPort::OutPort (const char *p, Node *e) : port(Int8(atoi(p))) { - expr = e; - addChild(&port); - addChild(e); -} - -Value *OutPort::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - /*vector args; - - args.push_back(port.generate(func, block, allocblock)); - - Value *value = expr->generate(func, block, allocblock); - Value *nvalue = value; - if (value->getType()->isFloatTy()) - nvalue = new FPToSIInst(value, Type::getInt16Ty(global_context), "trunci", block); - - args.push_back(nvalue); - //Value *int8v = new TruncInst(value, Type::getInt8Ty(global_context), "", block); - //args.push_back(int8v); - - ArrayRef argsRef(args); - return CallInst::Create(analogWrite, argsRef, "", block);*/ - - //TODO: Implement a new way of reading ports - return NULL; -} diff --git a/src/OutPort.h b/src/OutPort.h deleted file mode 100644 index 79720c8..0000000 --- a/src/OutPort.h +++ /dev/null @@ -1,16 +0,0 @@ - -#pragma once - -#include "Node.h" -#include "Int8.h" -#include "Int16.h" -#include "Float.h" - -class OutPort: public Node { -private: - Int8 port; - Node *expr; -public: - OutPort (const char *p, Node *e); - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; -}; diff --git a/src/ParamsCall.h b/src/ParamsCall.h index fb3c39b..ad27ce0 100644 --- a/src/ParamsCall.h +++ b/src/ParamsCall.h @@ -14,7 +14,7 @@ class ParamsCall { unsigned getNumParams() const; Node *getParamElement (int position) const; - std::vector const& getParameters() { + std::vector& getParameters() { return parameters; } }; diff --git a/src/Pointer.cpp b/src/Pointer.cpp index b526b86..0e79f90 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -3,8 +3,8 @@ #include "BackLLVM.h" #include "UserType.h" -Pointer::Pointer(const char *name, DataType type, Node *address): - Variable(name), address(address) { +Pointer::Pointer(const char *name, DataType type, Node *address, location_t loc): + Variable(name, loc), address(address) { dt = type; addChild(address); } diff --git a/src/Pointer.h b/src/Pointer.h index f06b2ea..8123910 100644 --- a/src/Pointer.h +++ b/src/Pointer.h @@ -8,7 +8,7 @@ class Pointer: public Variable { Node *address; public: - Pointer(const char *name, DataType type, Node *address); + Pointer(const char *name, DataType type, Node *address, location_t loc); virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; diff --git a/src/Print.cpp b/src/Print.cpp deleted file mode 100644 index 8d74ae2..0000000 --- a/src/Print.cpp +++ /dev/null @@ -1,37 +0,0 @@ - -#include "Print.h" - -Value *Print::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - /*vector args; - - Value *lexp = expr->generate(func, block, allocblock); - char cty1 = -1; - if (lexp != NULL) { - Type *ty1 = lexp->getType(); - if (ty1->isIntegerTy()) - cty1 = 0; - else if (ty1->isFloatTy()) - cty1 = 1; - else if (ty1->isArrayTy()) - cty1 = 2; - } - - if (cty1 == -1) { - yyerrorcpp("Type not supported by print.", this); - return NULL; - } - - Int8 prt(cty1); - args.push_back(prt.generate(func, block, allocblock)); - - AllocaInst *ptr_aux = new AllocaInst(lexp->getType(), 0, "prntaux", block); - new StoreInst(lexp, ptr_aux, false, block); - CastInst *cinst = new BitCastInst(ptr_aux, PointerType::get(IntegerType::get(global_context, 8), 0), "bitcast", block); - args.push_back(cinst); - - ArrayRef argsRef(args); - return CallInst::Create(print, argsRef, "", block);*/ - - //TODO: Implement a new way of print (serial interface with simavr!) - return NULL; -} diff --git a/src/Print.h b/src/Print.h deleted file mode 100644 index d1da129..0000000 --- a/src/Print.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __PRINT_H__ -#define __PRINT_H__ -#include "Node.h" - -class Print: public Node { -private: - Node *expr; -public: - Print(Node *e) : expr(e) {} - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); -}; - -#endif diff --git a/src/PrintAstVisitor.cpp b/src/PrintAstVisitor.cpp index e175198..57eefb9 100644 --- a/src/PrintAstVisitor.cpp +++ b/src/PrintAstVisitor.cpp @@ -31,19 +31,21 @@ void PrintAstVisitor::visit_children(Node& n) { } } -void PrintAstVisitor::visit(Node& n) { - if (before(n)) { return; } +Node* PrintAstVisitor::visit(Node& n) { + if (before(n)) { return NULL; } visit_children(n); after(n); + return NULL; } PrintAstVisitor::PrintAstVisitor(std::ostream& _os) : os(_os) { } -void PrintAstVisitor::visit(Program& p) { - if (before(p)) { return; } +Node* PrintAstVisitor::visit(Program& p) { + if (before(p)) { return NULL; } visit_children(p); after(p); + return NULL; } bool PrintAstVisitor::before(Program& p) { @@ -58,19 +60,22 @@ void PrintAstVisitor::after(Program& p) { this->os << "}\n"; } -void PrintAstVisitor::visit(Int8& n) { +Node* PrintAstVisitor::visit(Int8& n) { this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << std::dec << (int)n.getNumber() << ")\"];\n"; + return NULL; } -void PrintAstVisitor::visit(Int16& n) { +Node* PrintAstVisitor::visit(Int16& n) { this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << std::dec << n.getNumber() << ")\"];\n"; + return NULL; } -void PrintAstVisitor::visit(Int32& n) { +Node* PrintAstVisitor::visit(Int32& n) { this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << std::dec << n.getNumber() << ")\"];\n"; + return NULL; } const string PrintAstVisitor::getOperatorName(int op) { @@ -81,39 +86,38 @@ const string PrintAstVisitor::getOperatorName(int op) { case GE_OP: return ">="; case LT_OP: return "<"; case GT_OP: return ">"; - case '+' : return "+"; - case '-' : return "-"; - case '*' : return "*"; - case '/' : return "/"; - case '%' : return "%"; case TOK_AND : return "and"; case TOK_OR : return "or"; default: return std::to_string(op); } } -void PrintAstVisitor::visit(CmpOp& n) { +Node* PrintAstVisitor::visit(CmpOp& n) { this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << std::dec << getOperatorName(n.getOperator()) << ")\"];\n"; visit_children(n); + return NULL; } -void PrintAstVisitor::visit(BinaryOp& n) { +Node* PrintAstVisitor::visit(BinaryOp& n) { this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << std::dec << getOperatorName(n.getOperator()) << ")\"];\n"; visit_children(n); + return NULL; } -void PrintAstVisitor::visit(Load& n) { +Node* PrintAstVisitor::visit(Load& n) { this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << n.getName() << ")\"];\n"; visit_children(n); + return NULL; } -void PrintAstVisitor::visit(Scalar& n) { +Node* PrintAstVisitor::visit(Scalar& n) { this->os << "N" << std::hex << (uint64_t)&n << "[label=\"" << get_typename(n) << "(" << n.getName() << ")\"];\n"; visit_children(n); + return NULL; } diff --git a/src/PrintAstVisitor.h b/src/PrintAstVisitor.h index 4eb4e81..9a8eaa6 100644 --- a/src/PrintAstVisitor.h +++ b/src/PrintAstVisitor.h @@ -10,22 +10,22 @@ class PrintAstVisitor: public RecursiveVisitor { public: PrintAstVisitor(std::ostream& _os); - virtual void visit(Node& p) override; + virtual Node* visit(Node& p) override; void visit_children(Node& n); bool before(Node& n) override; void after(Node& n) override; - virtual void visit(Program& p) override; - virtual void visit(Int8& n) override; - virtual void visit(Int16& n) override; - virtual void visit(Int32& n) override; + virtual Node* visit(Program& p) override; + virtual Node* visit(Int8& n) override; + virtual Node* visit(Int16& n) override; + virtual Node* visit(Int32& n) override; const string getOperatorName(int op); - virtual void visit(CmpOp& n) override; - virtual void visit(BinaryOp& n) override; + virtual Node* visit(CmpOp& n) override; + virtual Node* visit(BinaryOp& n) override; - virtual void visit(Load& n) override; - virtual void visit(Scalar& n) override; + virtual Node* visit(Load& n) override; + virtual Node* visit(Scalar& n) override; virtual bool before(Program& p) override; virtual void after(Program& p) override; diff --git a/src/Program.cpp b/src/Program.cpp index 1604acd..6931880 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -2,14 +2,17 @@ #include "FunctionImpl.h" #include "HeaderGlobals.h" #include "SymbolizeTree.h" +#include "PropagateTypes.h" +#include "PrintAstVisitor.h" #include "BackLLVM.h" #include "ZeroInit.h" #include "Return.h" #include "Load.h" #include "BuildTypes.h" +#include "ConstructorCall.h" #include -Program::Program() { +Program::Program() : Node({0,0,0,0}) { mainmodule = new Module(this->getFile(), global_context); Builder = make_unique>(global_context); @@ -118,11 +121,13 @@ Value *Program::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo return NULL; } -void Program::generateInjectionSetup() { +void Program::generateInjectionSetup(SourceLocation *sl) { + + location_t loc = sl->getLoc(); // a function to init global vars for singleton injections FunctionImpl *funcInitGlobals = new FunctionImpl((DataType)tvoid, ":injections_init", - new FunctionParams(), vector(), *this->getLoct(), false); + new FunctionParams(), vector(), loc, loc, false); funcInitGlobals->setScope(this); addSymbol(funcInitGlobals); @@ -132,13 +137,15 @@ void Program::generateInjectionSetup() { return instance; } */ + vector finjects; for (auto &[key, itype] : injections) { - Identifier to(key); - Identifier bind(itype.first); + Identifier to(key, loc); + Identifier bind(itype.first, loc); BindScope scope(itype.second); // injection validation - Identifier bindSubtypes = regex_replace(bind.getFullName(), regex("\\."), ":"); //internal types use : + auto subTypeName = regex_replace(bind.getFullName(), regex("\\."), ":"); //internal types use : + Identifier bindSubtypes(subTypeName, loc); Node *injectType = bindSubtypes.getSymbol(this); if (!injectType) { yyerrorcpp(string_format("Injection symbol %s not found.", @@ -174,9 +181,10 @@ void Program::generateInjectionSetup() { const string functionName = ":get_injection_for_" + to.getFullName(); FunctionImpl *finject = new FunctionImpl(destinationTy, functionName, - new FunctionParams(), vector(), *this->getLoct(), false); + new FunctionParams(), vector(), loc, loc, false); finject->setReturnIsPointer(true); finject->setScope(this); + finject->setInline(true); if (scope == bs_singleton) { string globalVarName; @@ -187,27 +195,27 @@ void Program::generateInjectionSetup() { Node *var = findSymbol(globalVarName); if (!var) { // alloc the global var - ZeroInit *nc = new ZeroInit(injectType->getDataType()); + ZeroInit *nc = new ZeroInit(injectType->getDataType(), loc); Scalar *svar = new Scalar(globalVarName, nc); svar->setScope(this); addSymbol(svar); svar->generate(NULL, NULL, global_alloc); var = svar; - FunctionCall *fc = new FunctionCall(bind.getFullName(), new ParamsCall()); - Scalar *sc = new Scalar(globalVarName, fc); - fc->setScope(funcInitGlobals); + ConstructorCall *cc = new ConstructorCall(bind.getFullName(), loc); + Scalar *sc = new Scalar(globalVarName, cc); + cc->setScope(funcInitGlobals); sc->setScope(funcInitGlobals); funcInitGlobals->addChild(sc); } } - Load *load = new Load(globalVarName); + Load *load = new Load(Identifier(globalVarName, loc)); Return *ret = new Return(load); ret->setScope(finject); load->setScope(finject); finject->addChild(ret); - finject->generate(NULL, NULL, global_alloc); + finjects.push_back(finject); } else { // bs_transient assert(false && "TODO: implement bs_transient scope."); @@ -216,17 +224,22 @@ void Program::generateInjectionSetup() { // generate injection function aliases for(const auto & [key, symbol] : bindUserTy->getSymbols()) { if (FunctionImpl *impl = dynamic_cast(symbol)) { - Identifier destTyIntfName = destinationTyName; + Identifier destTyIntfName(destinationTyName, loc); Node *destIntf = destTyIntfName.getSymbol(this); if (destIntf && destIntf->findMember(symbol->getName())) { // is a interface member implementation, let add an alias to it string to_name = regex_replace(to.getFullName(), regex("\\."), ":") + ":" + symbol->getName(); Function *implFunc = impl->getLLVMFunction(); - Function *aliasFunc = Function::Create(implFunc->getFunctionType(), Function::ExternalLinkage, - codeAddrSpace, to_name, mainmodule); - aliasFunc->setDSOLocal(true); - aliasFunc->setCallingConv(CallingConv::C); + // if the function is declared in this module, FunctionCall already create it + Function *aliasFunc = mainmodule->getFunction(to_name); + if (!aliasFunc) { + aliasFunc = Function::Create(implFunc->getFunctionType(), Function::ExternalLinkage, + codeAddrSpace, to_name, mainmodule); + aliasFunc->setDSOLocal(true); + aliasFunc->setCallingConv(CallingConv::C); + aliasFunc->addFnAttr(Attribute::AlwaysInline); + } auto fblock = BasicBlock::Create(global_context, "", aliasFunc); Builder->SetInsertPoint(fblock); @@ -249,18 +262,27 @@ void Program::generateInjectionSetup() { } } + for(auto *finject : finjects) + finject->generate(NULL, NULL, global_alloc); + funcInitGlobals->generate(NULL, NULL, global_alloc); } +extern bool parseIsCompleted; + void Program::generate() { + parseIsCompleted = true; // instrumentation passes SymbolizeTree st; st.visit(*this); + PropagateTypes pt; + pt.visit(*this); + /*std::fstream fs; fs.open("ast", std::fstream::out); - PrintAstVisitor(fs).visit(p); + PrintAstVisitor(fs).visit(*this); fs.close();*/ Node *mainFunc = NULL; @@ -276,29 +298,12 @@ void Program::generate() { } n->generate(NULL, NULL, global_alloc); - - // if n is a UserType, there is a injection for it? - /*if (UserType *ut = dynamic_cast(n)) { - for (auto &[key, itype] : injections) { - if (itype.first == ut->getName()) { - const string variableName = ":injectionName__" + itype.first; - DataType var_dt = buildTypes->getType(itype.first); - Variable *injectionVariable = new Scalar(variableName, new NullConst(var_dt)); - injectionVariable->setScope(program); - map_injections[variableName] = injectionVariable; - - program->addSymbol(injectionVariable); - injectionVariable->generate(NULL, NULL, global_alloc); - break; //TODO: When implementing transient injection, change here. - } - } - }*/ } if (injections.size() > 0) { - generateInjectionSetup(); + generateInjectionSetup(mainFunc); - FunctionCall *fc = new FunctionCall(":injections_init", new ParamsCall()); + FunctionCall *fc = new FunctionCall(":injections_init", new ParamsCall(), mainFunc->getLoc()); fc->setScope(mainFunc); mainFunc->addChild(fc, true); } diff --git a/src/Program.h b/src/Program.h index f7cf239..bb1082c 100644 --- a/src/Program.h +++ b/src/Program.h @@ -11,7 +11,7 @@ class Program : public Node { Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); void generate(); - void generateInjectionSetup(); + void generateInjectionSetup(SourceLocation *sl); }; extern Program* program; diff --git a/src/PropagateTypes.cpp b/src/PropagateTypes.cpp new file mode 100644 index 0000000..77e7b80 --- /dev/null +++ b/src/PropagateTypes.cpp @@ -0,0 +1,390 @@ + +#include "PropagateTypes.h" +#include "ConstructorCall.h" + +void PropagateTypes::propagateChildren(Node& n, std::function lambda) { + for (auto it = n.node_children.begin(); it != n.node_children.end(); ++it) { + Node *replace = (*it)->accept(*this); + if (replace) { + *it = replace; + } + if (lambda) + lambda(**it); + } +} + +Node* PropagateTypes::coerceTo(Node *n, const DataType destTy, bool warns) { + if (isUndefined(n)) + return NULL; + DataType valueTy = n->getDataType(); + + // can coerce only between numeric types + bool lIsNumeric = buildTypes->isNumericDataType(destTy); + bool rIsNumeric = buildTypes->isNumericDataType(valueTy); + if (!lIsNumeric || !rIsNumeric) { + yyerrorcpp(string_format("Can not cast from '%s' to '%s'.", + buildTypes->name(valueTy), + buildTypes->name(destTy)), n); + return NULL; + } + + bool destUnsigned = buildTypes->isUnsignedDataType(destTy); + bool valueUnsigned = buildTypes->isUnsignedDataType(valueTy); + uint destBWidth = buildTypes->bitWidth(destTy); + uint valueBWidth = buildTypes->bitWidth(valueTy); + + // both sides integer + if (buildTypes->isIntegerDataType(destTy) && buildTypes->isIntegerDataType(valueTy)) { + + // if we have signed and unsigned operands, convert valueTy to destTy + if (warns) { + if ((destUnsigned ^ valueUnsigned) && valueTy != tbool) { + // if value is constant, convert it to the dest type + bool valueIsConstant = n->isConstExpr(); + if (valueIsConstant) { + valueTy = valueUnsigned ? buildTypes->unsignedToSigned(valueTy) : + buildTypes->signedToUnsigned(valueTy); + } else { + string name = n->getName(); + if (name == "") + name = "Value"; + if (destUnsigned) + yywarncpp(string_format("%s has been returned as unsigned.", name.c_str()), n); + else + yywarncpp(string_format("%s has been returned as signed.", name.c_str()), n); + } + } + } + + // if destTy is larger, SExtended or ZExtended value + if (destBWidth > valueBWidth) { + Node *expand; + if (destUnsigned) + expand = new ZExtInt(n, destTy); + else + expand = new SExtInt(n, destTy); + return expand; + + } else if (destBWidth < valueBWidth) { + if (warns) { + string name = n->getName(); + if (name == "") + name = "Value"; + yywarncpp(string_format("%s has been truncated to %s.", name.c_str(), + buildTypes->name(destTy)), n); + } + return new TruncInt(n, destTy); + } + } + + // both sides float point + if (buildTypes->isFloatDataType(destTy) && buildTypes->isFloatDataType(valueTy)) { + + // if destTy is larger, Extended value + if (destBWidth > valueBWidth) + return new ExtendFloat(n, destTy); + else if (destBWidth < valueBWidth) { + if (warns) + yywarncpp(string_format("Value has been truncated to %s.", buildTypes->name(destTy)), n); + return new TruncFloat(n, destTy); + } + } + + bool isDestInteger = buildTypes->isIntegerDataType(destTy); + bool isDestFloat = buildTypes->isFloatDataType(destTy); + bool isValueInteger = buildTypes->isIntegerDataType(valueTy); + bool isValueFloat = buildTypes->isFloatDataType(valueTy); + + if (isDestInteger && isValueFloat) { + if (warns) + yywarncpp(string_format("Float value has been truncated to %s.", buildTypes->name(destTy)), n); + return new FloatToInt(n, destTy); + } else if (isValueInteger && isDestFloat) { + return new IntToFloat(n, destTy); + } + + return n; +} + +Value *ForcedCast::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + Node *converted = PropagateTypes::coerceTo(node, dt, false); + if (converted) + return converted->generate(func, block, allocblock); + else + return NULL; +}; + +DataType PropagateTypes::coerceArithOrCmp(Node &n, Node *lNode, Node *rNode) { + DataType returnTy = BuildTypes::undefinedType; + + if (isUndefined(lNode) || isUndefined(rNode)) + return returnTy; + + DataType lTy = lNode->getDataType(); + DataType rTy = rNode->getDataType(); + + // binary operations only between numeric types + bool lIsNumeric = buildTypes->isNumericDataType(lTy); + bool rIsNumeric = buildTypes->isNumericDataType(rTy); + if (!lIsNumeric || !rIsNumeric) { + yyerrorcpp("Non-numeric types are not supported by this operator.", &n); + return returnTy; + } + + uint lBWidth = buildTypes->bitWidth(lTy); + uint rBWidth = buildTypes->bitWidth(rTy); + + // both sides integer + if (buildTypes->isIntegerDataType(lTy) && buildTypes->isIntegerDataType(rTy)) { + + bool lUnsigned = buildTypes->isUnsignedDataType(lTy); + bool rUnsigned = buildTypes->isUnsignedDataType(rTy); + + // if we have signed and unsigned operands + if (lUnsigned ^ rUnsigned) { + // if one side is constant, convert it to the other side type + bool lIsConstant = lNode->isConstExpr(); + bool rIsConstant = rNode->isConstExpr(); + if (lIsConstant ^ rIsConstant) { + if (lIsConstant) { + lTy = lUnsigned ? buildTypes->unsignedToSigned(lTy) : buildTypes->signedToUnsigned(lTy); + returnTy = rTy; + } else { + rTy = rUnsigned ? buildTypes->unsignedToSigned(rTy) : buildTypes->signedToUnsigned(rTy); + returnTy = lTy; + } + + } else { + yywarncpp("The unsigned operand was converted to signed.", &n); + if (lUnsigned) + lTy = buildTypes->unsignedToSigned(lTy); + else + rTy = buildTypes->unsignedToSigned(rTy); + } + } + + // At this point, rTy has the same signedness of lTy. + // Thus, temporarily set returnTy to check the signedness below + returnTy = rTy; + + // if sizes are distinct, the smaller int is SExtended or ZExtended + if (lBWidth != rBWidth) { + Node *convert = lBWidth < rBWidth ? lNode : rNode; + DataType newTy = lBWidth < rBWidth ? rTy : lTy; + Node *expand; + if (buildTypes->isSignedDataType(returnTy)) + expand = new SExtInt(convert, newTy); + else + expand = new ZExtInt(convert, newTy); + n.node_children[lBWidth < rBWidth ? 0 : 1] = expand; + return newTy; + } + } + + // both sides float point + if (buildTypes->isFloatDataType(lTy) && buildTypes->isFloatDataType(rTy)) { + + // if sizes are distinct, the smaller float is extended + if (lBWidth != rBWidth) { + Node *convert = lBWidth < rBWidth ? lNode : rNode; + DataType newTy = lBWidth < rBWidth ? rTy : lTy; + ExpandFloat *ef = new ExpandFloat(convert, newTy); + n.node_children[lBWidth < rBWidth ? 0 : 1] = ef; + return newTy; + } + } + + // one side float and other side int + bool lIsInteger = buildTypes->isIntegerDataType(lTy); + bool lIsFloat = buildTypes->isFloatDataType(lTy); + bool rIsInteger = buildTypes->isIntegerDataType(rTy); + bool rIsFloat = buildTypes->isFloatDataType(rTy); + if (lIsInteger && rIsFloat || lIsFloat && rIsInteger) { + Node *convert = lIsInteger ? new IntToFloat(lNode, rTy) : new IntToFloat(rNode, lTy); + n.node_children[lIsInteger ? 0 : 1] = convert; + DataType newTy = lIsInteger ? rTy : lTy; + return newTy; + } + + if ((lTy == tchar && rTy == tint8u) || (lTy == tint8u && rTy == tchar)) + return lTy; + else if (lTy == rTy) { + return lTy; + } else { + yyerrorcpp(string_format("FIXME: the pair %s and %s needs a coercion.", + buildTypes->name(lTy), buildTypes->name(rTy)), &n); + assert(returnTy != BuildTypes::undefinedType); + } + + return returnTy; +} + +Node* PropagateTypes::visit(BinaryOp& n) { + propagateChildren(n); + n.dt = coerceArithOrCmp(n, n.lhsn(), n.rhsn()); + return NULL; +} + +Node* PropagateTypes::visit(CmpOp& n) { + propagateChildren(n); + coerceArithOrCmp(n, n.lexpn(), n.rexpn()); + return NULL; +} + +Node* PropagateTypes::visit(FunctionImpl& n) { + currentFunctionDt = n.getDataType(); + propagateChildren(n); + currentFunctionDt = BuildTypes::undefinedType; + return NULL; +} + +Node* PropagateTypes::visit(Return& n) { + if (!n.value()){ + n.dt = tvoid; + return NULL; + } else { + propagateChildren(n); + DataType valueDt = n.value()->getDataType(); + if (currentFunctionDt != valueDt) { + Node *converted = coerceTo(n.node_children[0], currentFunctionDt); + if (converted) { + n.node_children[0] = converted; + n.dt = converted->dt; + } + } else { + if (buildTypes->isComplex(valueDt)) { + // defer the pointer before returning + n.node_children[0] = new DeferPointer(n.value()); + } + n.dt = valueDt; + } + } + return NULL; +} + +Node* PropagateTypes::visit(FunctionCall& fc) { + propagateChildren(fc); + + // if the function name is the name of a primitive or complex type, + // replace the function call node by a more specific one + DataType dt = buildTypes->getType(fc.getName()); + + // if the function name is a UserType, its DataType is not created yet. + // Thus, we call findSymbol and getDataType to create it + if (dt == BuildTypes::undefinedType) { + Identifier typeName(fc.getName(), fc.getLoc()); + Node *symbol = typeName.getSymbol(&fc, false); + if (dynamic_cast(symbol)) + dt = symbol->getDataType(); + } + + if (dt != BuildTypes::undefinedType) { + + // if dt is the name of a primitive type and the call has only one + // argument, replace the function call node to a Cast one + unsigned p = fc.getParameters().size(); + if (buildTypes->isPrimitiveType(dt) && p == 1) { + Node *param = fc.getParameters()[0]; + ForcedCast *cast = new ForcedCast(param, dt); + return cast; + } + + // if dt is the name of a complex type and the call has no argument, + // replace the function call node to a ConstructorCall one + if (buildTypes->isComplex(dt) && p == 0) { + ConstructorCall *constructor = new ConstructorCall(fc.getName(), fc.getLoc()); + constructor->setScope(fc.getScope()); + return constructor; + } + } + + // coerce call arguments + Identifier calledIdent(fc.getName(), fc.getLoc()); + Node *calledSymbol = calledIdent.getSymbol(&fc, false); + FunctionBase *calledFunc = dynamic_cast(calledSymbol); + if (calledFunc && calledFunc->getNumCodedParams() == fc.getParameters().size()) { + auto calledFuncParam = calledFunc->getParameters().getParameters().begin(); + auto passedParam = fc.getParameters().begin(); + while (passedParam != fc.getParameters().end()) { + DataType call_dt = (*passedParam)->getDataType(); + DataType def_dt = (*calledFuncParam)->getDataType(); + if (buildTypes->isPrimitiveType(def_dt) && call_dt != def_dt) { + Node *newParam = coerceTo((*passedParam), def_dt); + *passedParam = newParam; + } + calledFuncParam++; + passedParam++; + } + } + + return NULL; +} + +Node* PropagateTypes::visit(Matrix& n) { + // visit elements to propagate their types + for(MatrixElement *me : n.getElements()) { + for(ArrayElement *k: me->array->getElements()) { + Node *aux = k->value->accept(*this); + if (aux) + k->value = aux; + } + } + + // find the matrix and elements type + n.dt = n.getDataType(); + DataType edt = n.getElementDataType(); + + // visit elements to sext or zext their values + for(MatrixElement *me : n.getElements()) { + for(ArrayElement *k: me->array->getElements()) { + k->value = coerceTo(k->value, edt); + } + } + + return NULL; +} + +Node* PropagateTypes::visit(Array& n) { + // visit elements to propagate their types + for(ArrayElement *ae : n.getElements()) { + Node *aux = ae->value->accept(*this); + if (aux) + ae->value = aux; + } + + // find the array and elements type + n.getDataType(); + DataType edt = n.getElementDataType(); + + // visit elements to sext or zext their values + for(ArrayElement *ae : n.getElements()) { + ae->value = coerceTo(ae->value, edt); + } + + return NULL; +} + +Node* PropagateTypes::visit(UpdateArray& n) { + propagateChildren(n); + // find the array type, based on elements + DataType edt = n.getElementDataType(); + + // visit expr to sext or zext their values + n.setExpr(coerceTo(n.getExpr(), edt)); + + return NULL; +} + +Node* PropagateTypes::visit(UserType& n) { + n.dt = n.getDataType(); + propagateChildren(n); + return NULL; +} + +Node* PropagateTypes::visit(Enum& n) { + n.getDataType(); + //propagateChildren(n); + return NULL; +} diff --git a/src/PropagateTypes.h b/src/PropagateTypes.h new file mode 100644 index 0000000..e15f324 --- /dev/null +++ b/src/PropagateTypes.h @@ -0,0 +1,204 @@ + +#pragma once + +#include "Node.h" +#include "Visitor.h" +#include "UserType.h" +#include "Matrix.h" +#include "Array.h" +#include "UpdateArray.h" +#include "BinaryOp.h" +#include "CmpOp.h" +#include "Return.h" +#include "FunctionImpl.h" +#include "FunctionCall.h" +#include "Enum.h" + +class CoercionBase: public Node { +protected: + Node *node; + +public: + CoercionBase(Node *n, DataType newDt): Node(n->getLoc()) { + node = n; + dt = newDt; + addChild(n); + setScope(n->getScope()); + n->setScope(this, true); + } + + virtual bool isConstExpr() override { + return node->isConstExpr(); + } +}; + +class ExpandFloat: public CoercionBase { +public: + ExpandFloat(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generate(func, block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateFPExt(v, buildTypes->llvmType(dt), "fpext"); + } +}; + +class SExtInt: public CoercionBase { +public: + SExtInt(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generate(func, block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateSExt(v, buildTypes->llvmType(dt), "sext"); + } +}; + +class ZExtInt: public CoercionBase { +public: + ZExtInt(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generate(func, block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateZExt(v, buildTypes->llvmType(dt), "zext"); + } +}; + +class TruncInt: public CoercionBase { +public: + TruncInt(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generate(func, block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateTrunc(v, buildTypes->llvmType(dt), "trunc"); + } +}; + +class ExtendFloat: public CoercionBase { +public: + ExtendFloat(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generate(func, block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateFPExt(v, buildTypes->llvmType(dt), "fpext"); + } +}; + +class TruncFloat: public CoercionBase { +public: + TruncFloat(Node *n, DataType newDt): CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generate(func, block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateFPTrunc(v, buildTypes->llvmType(dt), "trunc"); + } +}; + +class FloatToInt: public CoercionBase { +public: + FloatToInt(Node *n, DataType newDt): + CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generate(func, block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + if (buildTypes->isUnsignedDataType(dt)) + return Builder->CreateFPToUI(v, buildTypes->llvmType(dt), "trunc"); + else + return Builder->CreateFPToSI(v, buildTypes->llvmType(dt), "trunc"); + } +}; + +class IntToFloat: public CoercionBase { +public: + IntToFloat(Node *n, DataType newDt): + CoercionBase(n, newDt) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generate(func, block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + if (buildTypes->isUnsignedDataType(node->getDataType())) + return Builder->CreateUIToFP(v, buildTypes->llvmType(dt), "uitofp"); + else + return Builder->CreateSIToFP(v, buildTypes->llvmType(dt), "sitofp"); + } +}; + +class DeferPointer: public CoercionBase { +public: + DeferPointer(Node *n): + CoercionBase(n, n->getDataType()) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generate(func, block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateLoad(buildTypes->llvmType(dt), v, false, "deref"); + } +}; + +class ForcedCast: public CoercionBase { +public: + ForcedCast(Node *n, DataType newDt): CoercionBase(n, newDt) {} + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; +}; + +class PropagateTypes: public Visitor { +protected: + DataType currentFunctionDt = BuildTypes::undefinedType; + +public: + PropagateTypes() {} + + void propagateChildren(Node& n, std::function lambda = NULL); + + Node *getChild(Node& n, int i) { + return n.node_children[i]; + } + + static bool isUndefined(Node *n) { + if (n->getDataType() == BuildTypes::undefinedType) { + string name = n->getName(); + if (name != "") + yyerrorcpp(string_format("The type of %s is undefined.", name.c_str()), n); + else + yyerrorcpp("The type of the expression is undefined.", n);; + return true; + } + return false; + } + + static Node *coerceTo(Node *n, const DataType destTy, bool warns = true); + DataType coerceArithOrCmp(Node& n, Node *left, Node *right); + + virtual Node* visit(Node& n) override { + propagateChildren(n); + return NULL; + } + + virtual Node* visit(CmpOp& n) override; + virtual Node* visit(BinaryOp& n) override; + + virtual Node* visit(Array& n) override; + virtual Node* visit(Matrix& n) override; + virtual Node* visit(UpdateArray& n) override; + + virtual Node* visit(UserType &n) override; + virtual Node* visit(Enum &n) override; + + virtual Node* visit(Return& n) override; + virtual Node* visit(FunctionImpl& n) override; + virtual Node* visit(FunctionCall& n) override; +}; diff --git a/src/RecursiveVisitor.cpp b/src/RecursiveVisitor.cpp index a09c9c5..4191475 100644 --- a/src/RecursiveVisitor.cpp +++ b/src/RecursiveVisitor.cpp @@ -1,13 +1,14 @@ #include "RecursiveVisitor.h" -void RecursiveVisitor::visit(Node& n) { - if (before(n)) { return; } +Node* RecursiveVisitor::visit(Node& n) { + if (before(n)) { return NULL; } for (auto &c : n.children()) { c->accept(*this); } after(n); + return NULL; } diff --git a/src/RecursiveVisitor.h b/src/RecursiveVisitor.h index 82ccbe8..c2df0ef 100644 --- a/src/RecursiveVisitor.h +++ b/src/RecursiveVisitor.h @@ -6,5 +6,5 @@ class RecursiveVisitor: public Visitor { public: - void visit(Node& n) override; + Node* visit(Node& n) override; }; diff --git a/src/Return.cpp b/src/Return.cpp index 8f47d2f..0725370 100644 --- a/src/Return.cpp +++ b/src/Return.cpp @@ -1,28 +1,13 @@ #include "Return.h" -#include "Coercion.h" #include "FunctionImpl.h" Value *Return::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + Value *retvalue = NULL; + if (value()) { + retvalue = value()->generate(func, block, allocblock); + } RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); - Value *ret = NULL; - if (node) { - ret = node->generate(func, block, allocblock); - if (ret) { - Type *retTy = ret->getType(); - Type *funcTy = func->getLLVMFunction()->getReturnType(); - if (retTy != funcTy) { - DataType sdt = node->getDataType(); - if (buildTypes->isComplex(sdt)) { - // defer the pointer before returning - Type *ty = buildTypes->llvmType(sdt); - ret = Builder->CreateLoad(ty, ret, false, "deref"); - } - - ret = Coercion::Convert(ret, funcTy, block, this); - } - } - } - return Builder->CreateRet(ret); + return Builder->CreateRet(retvalue); } diff --git a/src/Return.h b/src/Return.h index 3e704ba..294b075 100644 --- a/src/Return.h +++ b/src/Return.h @@ -2,19 +2,27 @@ #pragma once #include "Node.h" +#include "Visitor.h" class Return: public Node { -private: - Node *node; public: - Return() { - node = NULL; + Return(location_t loc): Node(loc) { + dt = tvoid; } - Return(Node *n) { + Return(Node *n): Node(n->getLoc()) { addChild(n); - this->node = n; + } + + Node *value() { + if (node_children.empty()) + return NULL; + return node_children[0]; } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + Node* accept(Visitor& v) override { + return v.visit(*this); + } }; diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 5189c65..a611137 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -1,16 +1,16 @@ #include "Scalar.h" -#include "Coercion.h" #include "FunctionImpl.h" #include "BackLLVM.h" #include "Pointer.h" +#include "PropagateTypes.h" Scalar::Scalar(Identifier ident, Node *e) : - Variable(ident.getFullName()), expr(e) { + Variable(ident.getFullName(), ident.getLoc()) { addChild(e); } -Scalar::Scalar(const char* ident, Node *e): Variable(ident), expr(e) { +Scalar::Scalar(const string& ident, Node *e): Variable(ident, e->getLoc()) { addChild(e); } @@ -48,12 +48,12 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc // set the allocated left value to: // - a constructor initializing a user type field // - a load for a new variable - expr->setLeftValue(symbol); + expr()->setLeftValue(symbol); - Value *exprv = expr->generate(func, block, allocblock); + Value *exprv = expr()->generate(func, block, allocblock); if (!exprv) return NULL; - DataType exprv_dt = expr->getDataType(); + DataType exprv_dt = expr()->getDataType(); Builder->SetInsertPoint(block); if (!alloc) @@ -76,7 +76,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc ret = alloc = exprvc; else { Type *gty = buildTypes->llvmType(dt); - if (expr->isPointerToPointer()) + if (expr()->isPointerToPointer()) gty = gty->getPointerTo(); GlobalVariable *gv = new GlobalVariable(*mainmodule, gty, false, GlobalValue::InternalLinkage, exprvc, name); @@ -98,8 +98,6 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Builder->SetInsertPoint(block); ret = Builder->CreateStore(exprv, alloc, symbol->hasQualifier(qvolatile)); - symbols = expr->getSymbols(); - if (debug_info) RobDbgInfo.declareVar(this, alloc, allocblock); } @@ -154,7 +152,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Value *ones = Builder->CreateZExt(allone, req_eq_ty); // Coerce the rvalue to the req size - exprv = Coercion::Convert(exprv, req_eq_ty, block, expr); + exprv = Builder->CreateZExt(exprv, req_eq_ty); exprv = Builder->CreateAnd(exprv, ones, "truncrval"); unsigned fieldStartBit = reg->getFieldStartBit(symbol); @@ -170,7 +168,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc nvalue = Builder->CreateOr(vaftermask, exprv, "setbits"); } else { - nvalue = Coercion::Convert(exprv, currty, block, symbol); + nvalue = exprv; } RobDbgInfo.emitLocation(this); @@ -180,7 +178,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc DataType Scalar::getDataType() { if (dt == BuildTypes::undefinedType) - return dt = expr->getDataType(); + return dt = expr()->getDataType(); else return dt; } diff --git a/src/Scalar.h b/src/Scalar.h index 8b20e88..9fd2dc8 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -2,22 +2,29 @@ #pragma once #include "Variable.h" +#include "Visitor.h" class Scalar: public Variable { -protected: - Node *expr; - public: - Scalar(const char* ident, Node *e); + Scalar(const string& ident, Node *e); Scalar(Identifier ident, Node *e); + Node *expr() { + return node_children[0]; + } + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; virtual bool isConstExpr() override { - return hasQualifier(qconst) && expr->isConstExpr(); + return hasQualifier(qconst) && expr()->isConstExpr(); } virtual DataType getDataType() override; + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } + + friend class SymbolizeTree; }; diff --git a/src/Scanner.cpp b/src/Scanner.cpp index 24ed635..a172951 100644 --- a/src/Scanner.cpp +++ b/src/Scanner.cpp @@ -160,14 +160,6 @@ bool parseUseFile(const string& use, location_t loc) { int MAINget_lineno(yyscan_t yyscanner); int MAINget_column(yyscan_t yyscanner); -int build_filelineno() { - return MAINget_lineno(buildStackScanner[buildStackScanner.size()-1]); -} - -int build_filecolno() { - return MAINget_column(buildStackScanner[buildStackScanner.size()-1]); -} - const filesystem::path* build_file() { return &buildStack[buildStackCurrent]; } diff --git a/src/Scanner.h b/src/Scanner.h index 7590e21..d2cf272 100644 --- a/src/Scanner.h +++ b/src/Scanner.h @@ -25,5 +25,3 @@ bool parseFile(const string &source); bool parseUseFile(const string& use, location_t loc); const filesystem::path* build_file(); -int build_filecolno(); -int build_filelineno(); diff --git a/src/SourceLocation.h b/src/SourceLocation.h index 762f81b..f2e2162 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -19,13 +19,8 @@ class SourceLocation { location_t sloc; const filesystem::path *file; public: - SourceLocation() { + SourceLocation(location_t l) { file = build_file(); - sloc.first_column = build_filecolno(); - sloc.first_line = build_filelineno(); - } - - SourceLocation(location_t l): SourceLocation() { sloc = l; } @@ -45,8 +40,8 @@ class SourceLocation { sloc = s->sloc; } - virtual location_t *getLoct() { - return &sloc; + virtual location_t getLoc() { + return sloc; } virtual const string getFile() const { diff --git a/src/StringConst.h b/src/StringConst.h index 4f8a73e..70d55a0 100644 --- a/src/StringConst.h +++ b/src/StringConst.h @@ -7,6 +7,6 @@ class StringConst: public Node { private: string str; public: - StringConst(const char *s): str(s) {} + StringConst(const char *s, location_t loc): Node(loc), str(s) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); }; diff --git a/src/SymbolizeTree.h b/src/SymbolizeTree.h index 7b0ac54..f2b58c7 100644 --- a/src/SymbolizeTree.h +++ b/src/SymbolizeTree.h @@ -7,15 +7,17 @@ #include "Matrix.h" #include "Array.h" #include "FunctionImpl.h" -#include "Loop.h" -#include "While.h" +#include "Scalar.h" +#include "Load.h" #include "FunctionCall.h" +#include "MemCopy.h" +#include "Enum.h" class SymbolizeTree: public Visitor { public: SymbolizeTree() {} - virtual void visit(Node& n) override { + virtual Node* visit(Node& n) override { for(auto& c : n.children()) { c->setScope(&n); if (c->hasName()) { @@ -26,19 +28,45 @@ class SymbolizeTree: public Visitor { for(auto& c : n.children()) { c->accept(*this); } + return NULL; } - virtual void visit(Array& n) override { + virtual Node* visit(Scalar& n) override { + visit((Node&)n); + if (n.children().size() > 0) + n.symbols = n.children()[0]->getSymbols(); + return NULL; + } + + virtual Node* visit(Load& n) override { + visit((Node&)n); + Node *identSymbol = n.getIdentSymbol(); + if (identSymbol) + n.symbols = identSymbol->getSymbols(); + return NULL; + } + + virtual Node* visit(MemCopy& n) override { + visit((Node&)n); + if (n.children().size() > 0) + n.symbols = n.children()[0]->getSymbols(); + return NULL; + } + + virtual Node* visit(Array& n) override { for(auto& c : n.children()) { if (c->hasName()) { n.addSymbol(dynamic_cast(c)); } } - for(ArrayElement *e : n.getElements()) + for(ArrayElement *e : n.getElements()) { e->value->setScope(&n); + e->value->accept(*this); + } + return NULL; } - virtual void visit(Matrix& n) override { + virtual Node* visit(Matrix& n) override { for(auto& c : n.children()) { if (c->hasName()) { n.addSymbol(dynamic_cast(c)); @@ -47,14 +75,23 @@ class SymbolizeTree: public Visitor { for(MatrixElement *i: n.getElements()) { for(ArrayElement *e: i->array->getElements()) { e->value->setScope(&n); + e->value->accept(*this); } } + return NULL; } - virtual void visit(FunctionCall& n) override { + virtual Node* visit(FunctionCall& n) override { for(Node *p: n.getParameters()) { p->setScope(&n); p->accept(*this); } + return NULL; + } + + virtual Node* visit(Enum &n) override { + visit((Node&)n); + n.getDataType(); + return NULL; } }; diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index d3fc5d6..236b6a6 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -1,15 +1,24 @@ #include "UpdateArray.h" -#include "Coercion.h" #include "FunctionImpl.h" #include "HeaderGlobals.h" -UpdateArray::UpdateArray(const string &i, Node *pos, Node *expr): - BaseArrayOper(i, pos, NULL), expr(expr) { +UpdateArray::UpdateArray(const string &i, Node *pos, Node *expr, location_t loc): + BaseArrayOper(i, pos, NULL, loc) { + this->expr = expr; addChild(pos); addChild(expr); } +DataType UpdateArray::getElementDataType() { + if (element_dt == BuildTypes::undefinedType) { + Node *symbol = ident.getSymbol(getScope()); + if (symbol && buildTypes->isArrayOrMatrix(symbol->getDataType())) + element_dt = buildTypes->getArrayElementType(symbol->getDataType()); + } + return element_dt; +} + Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { Node *symbol = ident.getSymbol(getScope()); @@ -39,7 +48,6 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * Value *val = expr->generate(func, block, allocblock); ArrayType *arrayTy = (ArrayType*)buildTypes->llvmType(symbol->getDataType()); - val = Coercion::Convert(val, arrayTy->getArrayElementType(), block, this); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); diff --git a/src/UpdateArray.h b/src/UpdateArray.h index f7e2237..12b902d 100644 --- a/src/UpdateArray.h +++ b/src/UpdateArray.h @@ -3,12 +3,28 @@ #include "Node.h" #include "LoadArray.h" +#include "Visitor.h" class UpdateArray: public BaseArrayOper { protected: + DataType element_dt = BuildTypes::undefinedType; Node *expr; public: - UpdateArray(const string &i, Node *pos, Node *expr); + UpdateArray(const string &i, Node *pos, Node *expr, location_t loc); virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual DataType getElementDataType(); + + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } + + void setExpr(Node *n) { + expr = n; + } + + Node *getExpr() { + return expr; + } }; diff --git a/src/UpdateMatrix.h b/src/UpdateMatrix.h index f0d05f4..6952c18 100644 --- a/src/UpdateMatrix.h +++ b/src/UpdateMatrix.h @@ -7,7 +7,8 @@ class UpdateMatrix: public UpdateArray { public: - UpdateMatrix(const string &i, Node *p1, Node *p2, Node *expr) : UpdateArray(i, p1, expr) { + UpdateMatrix(const string &i, Node *p1, Node *p2, Node *expr, location_t loc) : + UpdateArray(i, p1, expr, loc) { this->position2 = p2; addChild(p2); } diff --git a/src/UserType.cpp b/src/UserType.cpp index 1a51dfc..a4a12f9 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -5,8 +5,7 @@ #include "FunctionImpl.h" #include "FunctionDecl.h" #include "FunctionParams.h" -#include "FunctionCall.h" -#include "ParamsCall.h" +#include "ConstructorCall.h" #include "Variable.h" #include "Visitor.h" #include "Enum.h" @@ -15,8 +14,8 @@ class ParentScalar: public Scalar { public: - ParentScalar(DataType parentDt) : Scalar("parent", new Load(":parent")) { - expr->setScope(this); + ParentScalar(DataType parentDt, location_t loc) : Scalar("parent", new Load(":parent", loc)) { + expr()->setScope(this); dt = parentDt; pointer = pm_pointer; } @@ -48,7 +47,7 @@ bool UserType::createDataType() { if (UserType *ut = dynamic_cast(child)) { // internal user type: // add a var in the internal type to store a reference to his parent - ParentScalar *s = new ParentScalar(dt); + ParentScalar *s = new ParentScalar(dt, ut->getLoc()); s->setScope(ut); ut->addChild(s); ut->addSymbol(s); @@ -58,9 +57,9 @@ bool UserType::createDataType() { ut->createDataType(); // create a new var in the parent to store the intf implementation - FunctionCall *fc = new FunctionCall(ut->getName(), new ParamsCall()); - v = new Scalar(varname, fc); - fc->setScope(v); + ConstructorCall *cc = new ConstructorCall(ut->getName(), ut->getLoc()); + v = new Scalar(varname, cc); + cc->setScope(v); v->setScope(this); addedVars.push_back(v); @@ -74,11 +73,19 @@ bool UserType::createDataType() { } if (v) { - if (buildTypes->isInterface(v->getDataType())) + if (buildTypes->isInterface(v->getDataType())) { v->setPointer(pm_pointer); - else if (v->getPointerMode() == pm_unknown) + v->setPointerToPointer(true); + } else if (v->getPointerMode() == pm_unknown) v->setPointer(pm_nopointer); + DataType vdt = v->getDataType(); + if (!buildTypes->isDefined(vdt)) { + Node *undeft = Identifier(buildTypes->name(vdt), getLoc()).getSymbol(this); + UserType *undefut = dynamic_cast(undeft); + if (undefut) + undefut->createDataType(); + } Type *llvmType = v->getLLVMType(); assert(llvmType && "Can not construct a type without its LLVM type."); if (!llvmType) @@ -109,7 +116,7 @@ bool UserType::createDataType() { yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); return false; } - + return true; } @@ -152,10 +159,10 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all FunctionParams *fp = new FunctionParams(); FunctionBase *finit; if (declaration) { - finit = new FunctionDecl((DataType)tvoid, "init", fp); + finit = new FunctionDecl((DataType)tvoid, "init", fp, getLoc()); } else { finit = new FunctionImpl((DataType)tvoid, "init", fp, - std::move(fields), *this->getLoct(), true); + std::move(fields), getLoc(), getLoc(), true); } finit->addThisArgument(dt); if (parent) @@ -192,8 +199,8 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all return NULL; } -void UserType::accept(Visitor& v) { - v.visit(*this); +Node* UserType::accept(Visitor& v) { + return v.visit(*this); } unsigned UserType::getFieldStartBit(Node *field) { diff --git a/src/UserType.h b/src/UserType.h index 37a5373..c6d0d39 100644 --- a/src/UserType.h +++ b/src/UserType.h @@ -19,14 +19,15 @@ class UserType: public NamedNode { public: - UserType(const string name, vector &&stmts): NamedNode(name, std::move(stmts)) { } + UserType(const string name, vector &&stmts, location_t loc): + NamedNode(name, std::move(stmts), loc) { } - UserType(const string name, vector &&stmts, vector &&implements): - NamedNode(name, std::move(stmts)), implements(std::move(implements)) { } + UserType(const string name, vector &&stmts, vector &&implements, location_t loc): + NamedNode(name, std::move(stmts), loc), implements(std::move(implements)) { } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - void accept(Visitor& v) override; + Node* accept(Visitor& v) override; unsigned getFieldStartBit(Node *field); diff --git a/src/Variable.h b/src/Variable.h index f51ba38..2f253f6 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -14,9 +14,9 @@ class Variable: public NamedNode { enum PointerMode pointer = pm_unknown; public: - Variable(const string &name): NamedNode(name), ident(name) {} + Variable(const string &name, location_t loc): NamedNode(name, loc), ident(name, loc) {} - Variable(const string &name, DataType dt): NamedNode(name), ident(name) { + Variable(const string &name, DataType dt, location_t loc): NamedNode(name, loc), ident(name, loc) { this->dt = dt; } diff --git a/src/Visitor.h b/src/Visitor.h index df84907..ab4f426 100644 --- a/src/Visitor.h +++ b/src/Visitor.h @@ -4,7 +4,6 @@ #include "Node.h" class BinaryOp; -class Capsule; class CmpOp; class Delay; class Float; @@ -28,36 +27,34 @@ class Return; class Scalar; class StringConst; class Array; +class UpdateArray; class While; class Loop; class UserType; class Variable; class NamedConst; +class MemCopy; +class Enum; #define VISITOR_DECLAREP(T, P) \ - virtual void visit(T& n) { visit((P&)n); } \ + virtual Node *visit(T& n) { return visit((P&)n); } \ virtual void after(T&) {} \ - virtual bool before(T&) { return false; } + virtual bool before(T&) { return false; } \ + virtual Node *needs_replace(T&) { return NULL; } #define VISITOR_DECLARE(T) \ - virtual void visit(T& n) { visit((Node&)n); } \ + virtual Node *visit(T& n) { return visit((Node&)n); } \ virtual void after(T&) {} \ virtual bool before(T&) { return false; } -#define VISITOR_VISIT(T) \ - void T::accept(Visitor& v) {\ - v.visit(*this);\ - } - class Visitor { public: - virtual void visit(Node&) { } + virtual Node *visit(Node&) { return NULL; } virtual void after(Node&) {} virtual bool before(Node&) { return false; } VISITOR_DECLARE(NamedNode) VISITOR_DECLARE(BinaryOp) - VISITOR_DECLARE(Capsule) VISITOR_DECLARE(CmpOp) VISITOR_DECLARE(Delay) VISITOR_DECLARE(Float) @@ -85,6 +82,9 @@ class Visitor { VISITOR_DECLAREP(FunctionImpl, FunctionBase) VISITOR_DECLAREP(Array, Variable) VISITOR_DECLAREP(Matrix, Variable) + VISITOR_DECLARE(MemCopy) + VISITOR_DECLARE(Enum) + VISITOR_DECLARE(UpdateArray) }; diff --git a/src/While.cpp b/src/While.cpp index 0bf481e..2349658 100644 --- a/src/While.cpp +++ b/src/While.cpp @@ -2,13 +2,13 @@ #include "While.h" #include "FunctionImpl.h" -While::While(Node *e) : expr(e) { +While::While(Node *e, location_t loc) : Node(loc), expr(e) { addChild(e); stmts = NULL; } -While::While(Node *e, vector &&ss) : While(e) { - stmts = new Node(std::move(ss)); +While::While(Node *e, vector &&ss, location_t loc) : While(e, loc) { + stmts = new Node(std::move(ss), loc); addChild(stmts); } diff --git a/src/While.h b/src/While.h index 6098ab5..5c33ff5 100644 --- a/src/While.h +++ b/src/While.h @@ -9,8 +9,8 @@ class While: public Node { Node *stmts; public: - While(Node *e); - While(Node *e, vector &&stmts); + While(Node *e, location_t loc); + While(Node *e, vector &&stmts, location_t loc); virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/ZeroInit.h b/src/ZeroInit.h index 8847105..a64f81d 100644 --- a/src/ZeroInit.h +++ b/src/ZeroInit.h @@ -7,7 +7,7 @@ class ZeroInit: public Node { public: - ZeroInit(DataType dt) { + ZeroInit(DataType dt, location_t loc): Node(loc) { this->dt = dt; } diff --git a/src/main.cpp b/src/main.cpp index 618b613..eb767ae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,7 +47,7 @@ int main(int argc, char *argv[]) { if (t > 1) fprintf(stderr, ","); fprintf(stderr, "%s", supportedTargets[t].name); } - fprintf(stderr, "} -I {include_dir} -g -O{1,2,3,s,z} -o output_file -s spec_file input_file\n"); + fprintf(stderr, "} -I {include_dir} -g -O{0,1,2,3,s,z,d} -o output_file -s spec_file input_file\n"); return 1; } diff --git a/test/avr328p/Makefile b/test/avr328p/Makefile index 1aed15a..5d8d1c0 100644 --- a/test/avr328p/Makefile +++ b/test/avr328p/Makefile @@ -1,6 +1,6 @@ ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) -ALL_TT=$(patsubst %.rob,out/%.tt,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/avr328p.o ROBCMP=../../build/robcmp @@ -37,7 +37,7 @@ out/%.o : %.rob out/avr328p.o ${DEPENDS} out/%.ll : %.rob ${DEPENDS} ${ROBCMP} -a avr328p ${OPT} ${INCLUDES} $< > $@ -out/%.tt : %.rob ${DEPENDS} +%.tt : %.rob ${DEPENDS} @-./runtest.sh $< $(patsubst %.rob,out/%,$<) out/itoa : out/itoa.o ${SERIAL_DEPENDS} ${LINK_DEPENDS} @@ -48,5 +48,5 @@ out/% : out/%.o ${LINK_DEPENDS} test: ${ALL_TT} clean: - rm -f ${ALL} ${ALL_LL} ${ALL_OO} ${SERIAL_DEPENDS} + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} ${SERIAL_DEPENDS} diff --git a/test/avr328p/aux/serial.rob b/test/avr328p/aux/serial.rob index ba2afe9..d133034 100644 --- a/test/avr328p/aux/serial.rob +++ b/test/avr328p/aux/serial.rob @@ -41,14 +41,12 @@ register UCSRB UCSR0B at 0xc1; register UCSRC UCSR0C at 0xc2; /* USART0 baud rate register, 12 bits*/ -register int16 UBRR0 at 0xc4; +register uint16 UBRR0 at 0xc4; /* USART0 byte to send/received */ -register int8 UDR0 at 0xc6; +register uint8 UDR0 at 0xc6; type avr5_serial { - const test = 10; - volatile teste2 = int32(0); void start(avr5mcu mcu, int32 baud) { // use 2x @@ -80,12 +78,12 @@ type avr5_serial { UCSR0B.TXEN0 = true; } - void write(int8 c) { + void write(uint8 c) { while UCSR0A.UDRE0 == false; UDR0 = c; } - int8 read() { + uint8 read() { while UCSR0A.RXC0 == false; return UDR0; } diff --git a/test/avr328p/bsscheck.rob b/test/avr328p/bsscheck.rob new file mode 100644 index 0000000..fcc0dc4 --- /dev/null +++ b/test/avr328p/bsscheck.rob @@ -0,0 +1,23 @@ + +/* This test case allocates a zeroed matrix in .bss region. + It tests if the assembly func __do_clear_bss, called + before main, is working properly. + */ + +matrix = {{0u:128}:8}; + +int8 main() { + row = 0u; + while row < matrix.rows { + col = 0u; + while col < matrix.cols { + if matrix[row][col] != 0 { + return 1; + } + col++; + } + row++; + } + return 0; +} + diff --git a/test/avr328p/bssinjcheck.rob b/test/avr328p/bssinjcheck.rob new file mode 100644 index 0000000..22927f4 --- /dev/null +++ b/test/avr328p/bssinjcheck.rob @@ -0,0 +1,45 @@ + +/* This test case allocates a type, with a matrix + inside it, in the .bss region. + */ + +interface intf { + uint8 get(uint8 row, uint8 col); + uint8 rows(); + uint8 cols(); +} + +type container implements intf { + buff = {{0u:128}:8}; + uint8 get(uint8 row, uint8 col) { + return buff[row][col]; + } + uint8 rows() { return buff.rows; } + uint8 cols() { return buff.cols; } +} + +type globals { + c = intf(); +} + +bind container to globals.c singleton; + +int8 main() { + a = globals(); + c = a.c; + + row = 0u; + while row < c.rows() { + col = 0u; + while col < c.cols() { + v = c.get(row, col); + if v != 0 { + return 1; + } + col++; + } + row++; + } + return 0; +} + diff --git a/test/avr328p/itoa.rob b/test/avr328p/itoa.rob index bde67c1..c316a9b 100644 --- a/test/avr328p/itoa.rob +++ b/test/avr328p/itoa.rob @@ -78,9 +78,9 @@ base16 = { {'7', 'f', 'f', 'f', 0 , 0} }; -bool check(int8 id, char[][] expected, char[] result) { +bool check(uint8 id, char[][] expected, char[] result) { ret = true; - i = 0; + i = 0u; while result[i] != 0 and ret { if result[i] != expected[id][i] { ret = false; @@ -106,7 +106,7 @@ int16 main() { result = {'\0':18}; ret = true; - i = 0; + i = 0u; while i < numbers.size and ret { itoa(numbers[i], 10, result); ret = check(i, base10, result); diff --git a/test/avr328p/memcpycheck.rob b/test/avr328p/memcpycheck.rob new file mode 100644 index 0000000..6e96818 --- /dev/null +++ b/test/avr328p/memcpycheck.rob @@ -0,0 +1,42 @@ + +/* This test case allocates a zeroed matrix in .data region. + It checks if the assembly memcpy __xxx___ is working. + */ + +type fillmemory { + a = {{2u:8}:8}; +} + +int8 main() { + x = fillmemory(); + matrix = {{1u:128}:8}; + ma2 = {{0u:32}:8}; + + row = 0u; + while row < matrix.rows { + col = 0u; + while col < matrix.cols { + if matrix[row][col] != 1u { + return 1; + } + col++; + } + row++; + } + + row2 = 0u; + while row2 < ma2.rows { + col2 = 0u; + while col2 < ma2.cols { + v = ma2[row2][col2]; + if v != 0 { + return 2; + } + col2++; + } + row2++; + } + + return 0; +} + diff --git a/test/avr328p/runtest.sh b/test/avr328p/runtest.sh index 503dcd3..daf5c6b 100755 --- a/test/avr328p/runtest.sh +++ b/test/avr328p/runtest.sh @@ -5,7 +5,7 @@ GREEN="\033[0;32m" RED="\033[0;31m" NC="\033[0m" -echo -n " $1" +echo -n " $1 " make -s $2 if [ "$?" -eq 0 ]; then timeout 10s ${CMD} &> /dev/null diff --git a/test/debug/.gitignore b/test/debug/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/test/debug/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/test/debug/README b/test/debug/README new file mode 100644 index 0000000..3e5e354 --- /dev/null +++ b/test/debug/README @@ -0,0 +1,4 @@ +To debug a test, put a link to its .rob file here and open Visual Code. +Ex.: +$ ln -s ../../general/sort.rob +$ code . diff --git a/test/debug/platformio.ini b/test/debug/platformio.ini new file mode 100644 index 0000000..b75fd8c --- /dev/null +++ b/test/debug/platformio.ini @@ -0,0 +1,12 @@ + +[env] +platform = robcmp +board = avr328p +upload_protocol = serial + +[env:release] +build_type = release + +[env:debug] +build_type = debug +debug_tool = robcmp diff --git a/test/debug/src/.empty b/test/debug/src/.empty new file mode 100644 index 0000000..e69de29 diff --git a/test/debug/src/.gitignore b/test/debug/src/.gitignore new file mode 100644 index 0000000..0d1593f --- /dev/null +++ b/test/debug/src/.gitignore @@ -0,0 +1 @@ +*.rob diff --git a/test/general/Makefile b/test/general/Makefile index 60368d6..d649cf1 100644 --- a/test/general/Makefile +++ b/test/general/Makefile @@ -22,7 +22,7 @@ out: mkdir -p out clean: - rm -f ${ALL} ${ALL_LL} ${ALL_OO} + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} .SECONDARY: out/%.o : %.rob ${ROBCMP} Makefile @@ -42,7 +42,7 @@ out/%.ll : %.rob ${ROBCMP} Makefile ifeq ($(OS), Msys) ${LD} -e __main $< -o $@ else ifeq ($(OS), Darwin) - ${CC} $< -o $@ + ${CC} $< -o $@ &> /dev/null else ${CC} -no-pie $< -o $@ endif diff --git a/test/general/Vector_Int_R.rob b/test/general/Vector_Int_R.rob index 4a25bc4..0a22d09 100644 --- a/test/general/Vector_Int_R.rob +++ b/test/general/Vector_Int_R.rob @@ -3,7 +3,7 @@ int16 main(){ vector = {3:3, 2:3, 1:3, 2}; check = {3, 3, 3, 2, 2, 2, 1, 1, 1, 2}; - i = 0; + i = 0u; while i < vector.size { if vector[i] != check[i] { return 1; diff --git a/test/general/abs.rob b/test/general/abs.rob new file mode 100644 index 0000000..1a08664 --- /dev/null +++ b/test/general/abs.rob @@ -0,0 +1,33 @@ + +int16 abs(int16 value) { + if value < 0 { + return - value; + } + return value; +} + +int16 abs_bit(int16 value) { + mask = value >> 15; + return (value + mask) ^ mask; +} + +int16 abs_bit2(int16 value) { + mask = value >> 15; + return (value ^ mask) - mask; +} + +int8 main() { + nvalue = -635; + pvalue = 635; + if pvalue != abs(nvalue) { + return 1; + } + if pvalue != abs_bit(nvalue) { + return 1; + } + if pvalue != abs_bit2(nvalue) { + return 1; + } + return 0; +} + diff --git a/test/general/bellmanford.rob b/test/general/bellmanford.rob index a8a2982..6162bb5 100644 --- a/test/general/bellmanford.rob +++ b/test/general/bellmanford.rob @@ -14,7 +14,7 @@ dise = {0, -1, 2, -2, 1}; // Initialize distance of all vertices. dis = {INT_MAX : 5}; -bool bellmanford(int16 V, int16 src) { +bool bellmanford(uint16 V, int16 src) { // Number of edges E = graph.rows; @@ -26,13 +26,15 @@ bool bellmanford(int16 V, int16 src) { * shortest path from src to any other * vertex can have at-most |V| - 1 edges */ - i = 0; + i = 0u; while(i < (V-1)) { - j = 0; + j = 0u; while(j < E) { - d = dis[graph[j][0]] + graph[j][2]; - if (d < dis[graph[j][1]]) { - dis[graph[j][1]] = dis[graph[j][0]] + graph[j][2]; + x = graph[j][0]; + y = graph[j][1]; + weight = graph[j][2]; + if (dis[x] + weight < dis[y]) { + dis[y] = dis[x] + weight; } j++; } @@ -45,7 +47,7 @@ bool bellmanford(int16 V, int16 src) { * negative weight cycle. If we get a * shorter path, then there is a cycle. */ - i = 0; + i = 0u; while(i < E) { x = graph[i][0]; y = graph[i][1]; @@ -66,10 +68,10 @@ int16 main() { return 1; } - i = 0; + i = 0u; while i < dis.size { if dis[i] != dise[i] { - return 1; + return 2; } i++; } diff --git a/test/general/bitoper.rob b/test/general/bitoper.rob new file mode 100644 index 0000000..8f3eaf0 --- /dev/null +++ b/test/general/bitoper.rob @@ -0,0 +1,58 @@ + +/* this test case simulates a dot crossing + over a screen diagonally, from (0,0) to + (64,64) and next, from (64,0) to (128,64) + */ + +void set_pixel(int8[][] buffer, uint16 row, uint16 col) { + rowb = row/8; + if col < buffer.cols and rowb < buffer.rows { + v = buffer[rowb][col]; + buffer[rowb][col] = v | (1 << int8(row & 7)); + } +} + +void clear_pixel(int8[][] buffer, uint16 row, uint16 col) { + rowb = row/8; + if col < buffer.cols and rowb < buffer.rows { + v = buffer[rowb][col]; + buffer[rowb][col] = v & ~(1 << int8(row & 7)); + } +} + +int8 main() { + + /* the screen with 128 columns and 64 rows + (8 bits in each of the 8 bytes = 64) */ + buff = {{0:128}:8}; + + col = 0u; + row = 0u; + + loop { + + clear_pixel(buff, row, col); + + aux = buff[row/8][col]; + if aux != 0 { + return 1; // clear failed + } + + col++; + row++; + + if col == 128 and row == 64 { + return 0; + } + if row == 64 { + row = 0; + } + + set_pixel(buff, row, col); + + aux = buff[row/8][col]; + if aux == 0 { + return 2; // set failed + } + } +} diff --git a/test/general/bsscheck.rob b/test/general/bsscheck.rob new file mode 120000 index 0000000..845fac6 --- /dev/null +++ b/test/general/bsscheck.rob @@ -0,0 +1 @@ +../avr328p/bsscheck.rob \ No newline at end of file diff --git a/test/general/bssinjcheck.rob b/test/general/bssinjcheck.rob new file mode 120000 index 0000000..924abb9 --- /dev/null +++ b/test/general/bssinjcheck.rob @@ -0,0 +1 @@ +../avr328p/bssinjcheck.rob \ No newline at end of file diff --git a/test/general/byref-array.rob b/test/general/byref-array.rob index ce122f5..5c9d299 100644 --- a/test/general/byref-array.rob +++ b/test/general/byref-array.rob @@ -1,12 +1,12 @@ int32 sum_array(int16[] a); -int8 main() { +int32 main() { x = {int16(0), 1, 2, 3, 4, 5, 6, 7, 8, 9}; // y is a reference to x y = x; - i = 0; + i = 0u; while i < y.size { if y[i] != x[i] { return 1; @@ -16,7 +16,7 @@ int8 main() { // w is a reference to y (same as x) w = y; - i = 0; + i = 0u; while i < w.size { if w[i] != x[i] { return 1; @@ -26,11 +26,11 @@ int8 main() { // z is a copy of y z = copy(y); - i = 0; + i = 0u; while i < z.size { z[i] = z[i] + 1; if z[i] != x[i] + 1 { - return i; + return int32(i); } i++; } @@ -46,12 +46,12 @@ int8 main() { int32 pass_array_pointer(int16[] b) { c = b; d = copy(b); - result = c[9] + d[9] + b.size; + result = c[9] + d[9] + int32(b.size); return result; } int32 sum_array(int16[] a) { - i = 0; + i = 0u; result = int32(0); while i < a.size { result += a[i]; diff --git a/test/general/byref-matrix.rob b/test/general/byref-matrix.rob index 52894a9..7af9629 100644 --- a/test/general/byref-matrix.rob +++ b/test/general/byref-matrix.rob @@ -8,9 +8,9 @@ int32 main() { // y is a reference to x y = x; - i = 0; + i = 0u; while i < y.rows { - j = 0; + j = 0u; while j < y.cols { if y[i][j] != x[i][j] { return 1; @@ -23,9 +23,9 @@ int32 main() { // w is a reference to y (same as x) w = y; - i = 0; + i = 0u; while i < w.rows { - j = 0; + j = 0u; while j < w.cols { if w[i][j] != x[i][j] { return 1; @@ -37,9 +37,9 @@ int32 main() { // z is a copy of y z = copy(y); - i = 0; + i = 0u; while i < z.rows { - j = 0; + j = 0u; while j < z.cols { z[i][j] = z[i][j] + 1; if z[i][j] != x[i][j] + 1 { @@ -61,15 +61,15 @@ int32 main() { int32 pass_matrix_pointer(int16[][] b) { c = b; d = copy(b); - result = c[1][2] + d[2][2] + b.cols + b.rows; + result = c[1][2] + d[2][2] + int32(b.cols) + int32(b.rows); return result; } int32 sum_matrix(int16[][] a) { - i = 0; + i = 0u; result = int32(0); while i < a.rows { - j = 0; + j = 0u; while j < a.cols { result += a[i][j]; j++; diff --git a/test/general/cast.rob b/test/general/cast.rob new file mode 100644 index 0000000..53faeed --- /dev/null +++ b/test/general/cast.rob @@ -0,0 +1,9 @@ + +uint8 test() { + return uint8(130); +} + +int8 main() { + a = test(); + return a != 130U; +} \ No newline at end of file diff --git a/test/general/enum-hex.rob b/test/general/enum-hex.rob new file mode 100644 index 0000000..cd5c3ab --- /dev/null +++ b/test/general/enum-hex.rob @@ -0,0 +1,17 @@ +/* altough simple, this test can catch + bugs in the enum datatype creation, + when the values of enum items are + determined */ + +enum power { ON = 0xAF, SLEEP = 0 } + +int8 main() { + a = power.ON; + b = power.SLEEP; + if uint8(a) != 0xAF or uint8(b) != 0x0 { + return 1; + } else { + return 0; + } +} + diff --git a/test/general/enum-simple.rob b/test/general/enum-simple.rob new file mode 100644 index 0000000..001df15 --- /dev/null +++ b/test/general/enum-simple.rob @@ -0,0 +1,14 @@ + +enum Enum {A, B, C, D, E} + +int16 main() { + a = Enum.B; + b = Enum.C; + + if a == b or b == Enum.E { + return 1; + } else { + return 0; + } +} + diff --git a/test/general/enum.rob b/test/general/enum-types.rob similarity index 100% rename from test/general/enum.rob rename to test/general/enum-types.rob diff --git a/test/general/fibonacci.rob b/test/general/fibonacci.rob index 9f32474..a7a453a 100644 --- a/test/general/fibonacci.rob +++ b/test/general/fibonacci.rob @@ -20,7 +20,7 @@ int8 main() { fibonacci(20) }; - i = 0; + i = 0u; while (i < check.size) { if (result[i] != check[i]) { return 1; diff --git a/test/general/intfscope.rob b/test/general/intfscope.rob index 62c1ee4..29abbd2 100644 --- a/test/general/intfscope.rob +++ b/test/general/intfscope.rob @@ -8,9 +8,9 @@ type somevar { a = int16(0); pa = intf { - a = int8(0); - int16 get() { return a; } - void set(int16 s) { a = s; } + b = int16(0); + int16 get() { return b; } + void set(int16 s) { b = s; } } int16 internaltest() { diff --git a/test/general/itoa.rob b/test/general/itoa.rob index 4ef9c4e..1ce20ff 100644 --- a/test/general/itoa.rob +++ b/test/general/itoa.rob @@ -2,48 +2,47 @@ const chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; void itoa(int16 value, int8 base, char[] result) { - if base < 2 or base > 16 { - result[0] = 0; - return; - } + if base < 2 or base > 16 { + result[0] = 0; + return; + } - negative = false; - if value < 0 { - negative = true; - value = - value; - } - - i = 0; - if value == 0 { - result[i] = '0'; - i++; - } else { - while value != 0 { - temp = value; - value /= base; - result[i] = chars[temp - value * base]; - //result[i] = chars[value % base]; - //value /= base; - i++; - } - } + negative = value < 0; + //abs without branch + mask = value >> 15; + value = (value ^ mask) - mask; + + i = 0; + if value == 0 { + result[i] = '0'; + i++; + } else { + while value != 0 { + temp = value; + value /= base; + result[i] = chars[temp - value * base]; + //result[i] = chars[value % base]; + //value /= base; + i++; + } + if negative { + result[i] = '-'; + i++; + } + } - if negative == true { - result[i] = '-'; - i++; - } - result[i] = 0; - - // reverse result - j = 0; - i--; - while j < i { - temp = result[j]; - result[j] = result[i]; - result[i] = temp; - j++; - i--; - } + result[i] = 0; + + // reverse result + j = 0; + i--; + while j < i { + temp = result[j]; + result[j] = result[i]; + result[i] = temp; + j++; + i--; + } } numbers = {-32123, -15678, -4364, -501, -25, 0, 25, 512, 4364, 15678, 32767}; @@ -76,35 +75,35 @@ base16 = { {'7', 'f', 'f', 'f', 0 , 0} }; -bool check(int8 id, char[][] expected, char[] result) { - ret = true; - i = 0; - while result[i] != 0 and ret { - if result[i] != expected[id][i] { - ret = false; - } - i++; - } - return ret; +bool check(uint8 id, char[][] expected, char[] result) { + ret = true; + i = 0u; + while result[i] != 0 and ret { + if result[i] != expected[id][i] { + ret = false; + } + i++; + } + return ret; } int16 main() { - result = {'\0':18}; - ret = true; - i = 0; - while i < numbers.size and ret { - itoa(numbers[i], 10, result); - ret = check(i, base10, result); - if ret { - itoa(numbers[i], 16, result); - ret = check(i, base16, result); - } - i++; - } - if ret { - return 0; - } else { - return 1; - } + result = {'\0':18}; + ret = true; + i = 0u; + while i < numbers.size and ret { + itoa(numbers[i], 10, result); + ret = check(i, base10, result); + if ret { + itoa(numbers[i], 16, result); + ret = check(i, base16, result); + } + i++; + } + if ret { + return 0; + } else { + return 1; + } } diff --git a/test/general/memcpycheck.rob b/test/general/memcpycheck.rob new file mode 120000 index 0000000..bd74754 --- /dev/null +++ b/test/general/memcpycheck.rob @@ -0,0 +1 @@ +../avr328p/memcpycheck.rob \ No newline at end of file diff --git a/test/general/runtest.sh b/test/general/runtest.sh index 7028b7e..5166d97 100755 --- a/test/general/runtest.sh +++ b/test/general/runtest.sh @@ -3,15 +3,15 @@ GREEN="\033[0;32m" RED="\033[0;31m" NC="\033[0m" -echo -n " ... $1" +echo -n " ... $1 " make -s $2 if [ "$?" -eq 0 ]; then timeout 10s ./$2 &> /dev/null - #./$2 &> /dev/null - if [ "$?" -eq 0 ]; then + STATUS=$? + if [ "${STATUS}" -eq 0 ]; then echo -e \\r${GREEN}[PASS]\\t\\t${NC} else - echo -e \\r${RED}[FAILED]\\t${NC} + echo -e \\r${RED}[FAILED] ${STATUS}\\t${NC} fi else echo -e \\r${RED}[BUILD FAILED]\\t${NC} diff --git a/test/general/sort.rob b/test/general/sort.rob index aeb561e..45c615d 100644 --- a/test/general/sort.rob +++ b/test/general/sort.rob @@ -3,7 +3,7 @@ */ void sort(int16[] a) { - t = int16(0); + t = 0u; while t < a.size - 1 { s = t + 1; while s < a.size { @@ -23,7 +23,7 @@ int16 main() { r = {int16(-9), -5, -3, 0, 6, 6, 11, 12, 12, 17, 22, 22, 34, 44, 56, 100 }; sort(a); - i = 0; + i = 0u; while i < a.size { if a[i] != r[i] { return 1; diff --git a/test/general/unsigned.rob b/test/general/unsigned.rob new file mode 100644 index 0000000..bf35150 --- /dev/null +++ b/test/general/unsigned.rob @@ -0,0 +1,16 @@ + +uint16 func_b(uint16 x, int16 y); + +uint16 func_a(uint16 x) { + return x / 13u; +} + +int16 main() { + b = 130U; + a = func_a(b); + if (a == 10u) { + return 0; + } else { + return 1; + } +} From c7f99798a60d1d42a24343119f76608ee1c98723 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 15 Jun 2024 15:25:18 -0300 Subject: [PATCH 057/117] Improving language: integer/float exponent syntax --- .../vscode-syntax/robcmpsyntax-0.0.1.vsix | Bin 4709 -> 3330 bytes .../syntaxes/rob.tmLanguage.json | 13 +++++++++++-- rob.vim | 4 ++-- src/Language.l | 11 ++++++----- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix b/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix index e2e5f47765088d97ae293371f9e6666cbeeaede7..22e1499a31014744cd64f9834a075963e7966821 100644 GIT binary patch delta 1152 zcmV-`1b_SGB!U_ZP)h>@6aWAS2moYt&#?{g0u5w!&sdy5+lI0L001bH3IiH{b&pF9 z!Y~X(_nacip1QC=2=%i7Zombs)GdL=i5gSN?FsD;!P1^LGj>r=u2&-s(RwcRCd;)V zHomdkmHHv=davthRa{F0U(+yIgFVP#7SxW;84;ybP&+ou_M^#`3{U{ zA(pj#GIUj(sKrMw>O7_O(wp5gqGzp+3;8K4HHOezgOUK4W%z9!qn#YGZ7IrEgwQ0A zPWxwd%`bz);okV?TnO{y)#?qC>jfIK{sYDX16_5`liCbBf7&no+gq%9yMkVu^4&);{>@j3R>z(Z#$U6KN$ z8y_vTF4fI+D)B1Jsa~4IC?ZqAHQ_o;MKLX~)Rarg^QkTv=DEQ+0jttP_AKFVB{-S@ zJI4ia)IUTbe>6?~&!Q+PBhtTXpcSgb8VI-o1PzNwH1BVaHEA7%)GYq`gr9qNXD5`~A z1H!F9+qnJO@G4aev*-IhN=Qz*p)yf9qz7OUQEN)Ze zONzm}&>0$NS5Cd;zG&nlvRolC)M>MHU#6od8%I&-Uc>oU63@p$JeywxALH?8b~pPn z>(X_C!fWdJPZOWceeu`v;b3tae2d4Y(p_b$ab4*uN+zwYB^0NZ&VpYIZG z@0V7(Yd2>P{}`c3)|~pCTzAArsIfE`$o6~B4YXs++<}Bs0Ea}uIna;lSy<3ey=x(^ zZ$uXbQgF1A@2%&;$h0OIYzF@UP)i308;FGvzWM?H0K5nQ08mQ-0zU&3000OG0AzK~ zlM@g@4P@igKWDb)eiyU%@ z*`u6t=&fuyWk`w~N;Zi!Lya=!9B>7}rOkV#l zp0BjY4VvH_bFImQG$ZlX5$`4Bn&i=-MdxJ^gGX{9r4>o@BZt$Y3kKElzQn)d9&0URxxGc~1+fmLgkfE_@R$<}aNbNyTUwle?dNPiq52#+%)#NZ;a(f$NOg9yB@ zLFA?5SX=-R8{lscOu*v|2vK44`R4-F9Mn3sQ-&+NDpwq~J;7PFJy)O%0pno-u?!Mvt-%|YIKw;G+Bz2)OTCxT z=|D$CkSCAp<=2i;*Ac^=3w1BChZWebUI@++=@W-+Z_ZX_Vx0i~}h#OHecM4o(T* z%nZ5!u;Y`;VkOqL$H}rNhHW!^;F49eawyqT{hD}zxJ$wgI5Z=Hk=Z7@Dia5`62X(7 zpO<<-*}Ehct@b2JRs&BlFA9tJST~-*C6^Sel_@ezDk#fL6XZ&=*Xo4l@erpS|xSbxY=SNZ()q4*fw_c6S+FelzfmX$+UmzU_kv+xG%$v=QLw#Dj_W%C$@&NWa<6PRTp>`-DW z;|ux%oqI9y@>d@ZOKgWvS`K2JOujN?yzP0BDW&DL=XH)JoUq7QdT7+4_=}r=YmQ6q z!SLhAoKIABO@1i-^NC&K0I$>2(<`!+F1=rn$L|{=Ps$yDZQ^1 zE}zXD*eStl`OWtqndooGq~16Bq?6lo`-;yC&&RvU(eI0hH-aop7*wy!`>t5uS?`nK zuZfiAi_W3VG`6+uqWaEvcvmNJ$g(4y-2~eD```e;pBn(OwE^Hxy|hMg3lbf!5U<4+ zjmf=&BG=Q)D_<&j(ghy#*q3LOT>aZb9(G);56XMCwrKHQF3_nsFjb*b&5E&zv0{X3 z$(XyL(2{95pPUe%@)7l{=;;8D8BdHZOrCRKV%WugyMlLc&)(@%g;I$zUK43#&mfq% z(q@^QT3?$*C%Br$PWBEY5O) zs3eCzAFA->7E4yti2Hi!%Cwf$7viOb)3g&r=cE0E=Ao1?DrE5aR5#xiuXrV7W zS4Zh84BE0pur7r@Z*hLnp5@${sV0LI6tZz;7pT6xGI#0qFj|asm!(@7#c)G^_wX>% zEb#T7j@NQcf7>sn)=$=e8lFx<_W?d@RDms~oHA}DzpEC8oHU&+r(Eva=~ROqj|r`A z9V}Joy$Qpea=S*%E-}wp4b7#zfXWvmB7-0&o-(gb)ae#24IeAs*FB+K;?*J+vb;xy zD{$Qp@SFApIKCsvX;U zRwKxyqs(#}DS`PAFm^dk4sigLQJTKe;={sy`X(4=nJyNBEKL-z)55d!_sVAlzq%wZ z#es^939(!Sy0T>ewjo~>=}aGkL9qm@)F!GN#`e%U=|Nkhzi{CPX7o~7?%Yh5w!UuS zhq#cyqLyGWVqEySOr5~=r|O-84{wVTvF6ft<3C0RtOwG^^jlBe^3 zTkTH}cC=4TkYL=wHbzO=RSg6Og=K_*EHA3H5#tyaX&U6l_ZlBeBdyh z1PaHH^+^4lRQjoC(8oD$rjbFFaHfC#^R~L3A3E(KjgX_#Lm5rVC3Wj;y&}|bMr#3! zLC^@^Kd&%$cyUL&=KdN}d2N6oIpK_P@9e45h4q}!w0t(04t9t8b@2=$+`5_J#zW{I zqCZ{G-F_r%N)!O#i2rnfh^RI24-x|XL?N1l)RF%|p_5YXBJXJBTW1+LHGW_6@NF?PpQ-c4>x2GTnAR^2qkV!x RWFP" +syn match integerConstants "\<\d\+\([Ee][=+]\?[0-9]\+\)\?[Uu]\?\>" syn match hexConstants "\<0x[0-9a-fA-F]\+\>" -syn match floatConstants "\<\d\+\.\d\+L\?D\?\>" +syn match floatConstants "\<\d\+\.\d\+\([Ee][-+]\?[0-9]\+\)\?L\?D\?\>" syn match charConstants "'\\\?.'" syn match inPortKey "\" syn match outPortKey "\" diff --git a/src/Language.l b/src/Language.l index bf1ac60..391f28e 100644 --- a/src/Language.l +++ b/src/Language.l @@ -18,6 +18,7 @@ void update_loc(location_t *yylloc, int lineno, int leng, char *text); A [a-zA-Z_] D [0-9] ID {A}({A}|{D})* +EXP ([Ee][-+]?[0-9]+)? %% @@ -101,17 +102,17 @@ ID {A}({A}|{D})* return TOK_XIDENTIFIER; } -[0-9]+\.[0-9]+ { char *aux = strndup(yytext, yyleng); +[0-9]+\.[0-9]+{EXP} { char *aux = strndup(yytext, yyleng); yylval->nfloat = strtof(aux, NULL); free(aux); return TOK_FLOAT; } -[0-9]+\.[0-9]+D { char *aux = strndup(yytext, yyleng); +[0-9]+\.[0-9]+{EXP}D { char *aux = strndup(yytext, yyleng); yylval->ndouble = strtod(aux, NULL); free(aux); return TOK_DOUBLE; } -[0-9]+\.[0-9]+LD { char *aux = strndup(yytext, yyleng); +[0-9]+\.[0-9]+{EXP}LD { char *aux = strndup(yytext, yyleng); yylval->nldouble = strtold(aux, NULL); free(aux); return TOK_LDOUBLE; } @@ -126,12 +127,12 @@ ID {A}({A}|{D})* free(aux); return TOK_UINTEGER; } -[0-9]+[Uu] { char *aux = strndup(yytext, yyleng-1); +[0-9]+{EXP}[Uu] { char *aux = strndup(yytext, yyleng-1); yylval->unint = strtoull(aux, NULL, 10); free(aux); return TOK_UINTEGER; } -[0-9]+ { char *aux = strndup(yytext, yyleng); +[0-9]+{EXP} { char *aux = strndup(yytext, yyleng); yylval->nint = strtoll(aux, NULL, 10); free(aux); return TOK_INTEGER; } From aec4b3f3d6605cf6b610d6f533420f1d8c15c564 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 15 Jun 2024 17:02:34 -0300 Subject: [PATCH 058/117] The start of our standard lib - Add a flags (-bdep) to build dependencies - Add a simple dispatch support to interfaces (using switch, not vtable yet) - Expands use syntax to: use x.y.name.rob - Improves error handling - Updates test cases to use code from lib folder - Fixes bugs parsing use files and others --- lib/arch/avr/avr5mcu.rob | 214 ++++++++++++++++++ lib/arch/avr/avr5regs.rob | 171 ++++++++++++++ lib/convert/itoa.rob | 50 ++++ .../ssd1306.rob => lib/display/ssd1306spi.rob | 131 +++++++---- lib/graphic/canvas8.rob | 34 +++ lib/intfs/buffer8.rob | 11 + lib/intfs/databus.rob | 15 ++ lib/intfs/display.rob | 16 ++ .../avr328p-ssd1306/src => lib/intfs}/mcu.rob | 7 +- lib/intfs/ports.rob | 18 ++ lib/math/limits.rob | 27 +++ lib/math/random16.rob | 45 ++++ lib/math/random32.rob | 57 +++++ platformio/examples/avr328p-ssd1306/genll.sh | 11 + .../examples/avr328p-ssd1306/src/avr5mcu.rob | 128 ----------- .../examples/avr328p-ssd1306/src/avr5regs.rob | 67 ------ .../examples/avr328p-ssd1306/src/databus.rob | 9 - .../examples/avr328p-ssd1306/src/main.rob | 89 +++++--- .../examples/avr328p-ssd1306/src/main.spec | 1 + .../examples/avr328p-ssd1306/src/ports.rob | 14 -- platformio/platform/builder/main.py | 18 +- src/BackLLVM.cpp | 3 +- src/BuildTypes.cpp | 16 +- src/BuildTypes.h | 14 +- src/ConstructorCall.h | 10 + src/Dispatch.cpp | 91 ++++++++ src/Dispatch.h | 17 ++ src/FunctionCall.cpp | 36 ++- src/FunctionDecl.cpp | 8 + src/Int8.h | 2 + src/Language.y | 16 +- src/LanguageHeader.y | 1 + src/LanguageUse.y | 26 ++- src/Load.cpp | 4 +- src/Load.h | 2 +- src/LoadArray.cpp | 2 + src/Program.cpp | 15 +- src/Program.h | 9 + src/PropagateTypes.cpp | 77 ++++++- src/PropagateTypes.h | 9 +- src/Scalar.h | 5 + src/Scanner.cpp | 41 +++- src/Scanner.h | 2 - src/SourceLocation.h | 21 +- src/SymbolizeTree.h | 31 +-- src/UserType.cpp | 44 +++- src/Visitor.h | 2 + src/main.cpp | 22 +- test/avr328p/Makefile | 14 +- test/avr328p/aux/avr5mcu.rob | 11 - test/avr328p/aux/serial.rob | 95 -------- test/avr328p/itoa.rob | 58 +---- test/avr328p/robcmp-simavr-debug | 1 + test/avr328p/runtest.sh | 6 +- test/avr328p/uart.rob | 9 +- test/general/Makefile | 8 +- test/general/byref.rob | 2 +- test/general/dispatch.rob | 41 ++++ test/general/intfinternal.rob | 2 +- test/general/intfscope.rob | 2 +- test/general/itoa.rob | 47 +--- test/general/rand16.rob | 17 ++ test/general/simplesubtype.rob | 2 +- 63 files changed, 1343 insertions(+), 631 deletions(-) create mode 100644 lib/arch/avr/avr5mcu.rob create mode 100644 lib/arch/avr/avr5regs.rob create mode 100644 lib/convert/itoa.rob rename platformio/examples/avr328p-ssd1306/src/ssd1306.rob => lib/display/ssd1306spi.rob (61%) create mode 100644 lib/graphic/canvas8.rob create mode 100644 lib/intfs/buffer8.rob create mode 100644 lib/intfs/databus.rob create mode 100644 lib/intfs/display.rob rename {platformio/examples/avr328p-ssd1306/src => lib/intfs}/mcu.rob (50%) create mode 100644 lib/intfs/ports.rob create mode 100644 lib/math/limits.rob create mode 100644 lib/math/random16.rob create mode 100644 lib/math/random32.rob create mode 100755 platformio/examples/avr328p-ssd1306/genll.sh delete mode 100644 platformio/examples/avr328p-ssd1306/src/avr5mcu.rob delete mode 100644 platformio/examples/avr328p-ssd1306/src/avr5regs.rob delete mode 100644 platformio/examples/avr328p-ssd1306/src/databus.rob create mode 100644 platformio/examples/avr328p-ssd1306/src/main.spec delete mode 100644 platformio/examples/avr328p-ssd1306/src/ports.rob create mode 100644 src/Dispatch.cpp create mode 100644 src/Dispatch.h delete mode 100644 test/avr328p/aux/avr5mcu.rob delete mode 100644 test/avr328p/aux/serial.rob create mode 120000 test/avr328p/robcmp-simavr-debug create mode 100644 test/general/dispatch.rob create mode 100644 test/general/rand16.rob diff --git a/lib/arch/avr/avr5mcu.rob b/lib/arch/avr/avr5mcu.rob new file mode 100644 index 0000000..643bca7 --- /dev/null +++ b/lib/arch/avr/avr5mcu.rob @@ -0,0 +1,214 @@ + +use intfs.mcu; +use intfs.ports; +use intfs.databus; + +use avr5regs; + +void __delay_us(); + +type avr5mcu implements mcu { + + uint32 clock() { + return 16E6; + } + + void set_interruptions(bool enabled) { + SREG.I = enabled; + } + + /* implement this idea later! + template digport { + void mode(m port_mode) { port_config = mode; } + void set(bool v) { port = v; } + bool get() { return port; } + } + b0 = digport + */ + + b0 implements digitalport { + void mode(port_mode m) { ddrb.b0 = m; } + void set(bool v) { portb.b0 = v; } + bool get() { return portb.b0; } + } + + b1 implements digitalport { + void mode(port_mode m) { ddrb.b1 = m; } + void set(bool v) { portb.b1 = v; } + bool get() { return portb.b1; } + } + + b2 implements digitalport { + void mode(port_mode m) { ddrb.b2 = m; } + void set(bool v) { portb.b2 = v; } + bool get() { return portb.b2; } + } + + b3 implements digitalport { + void mode(port_mode m) { ddrb.b3 = m; } + void set(bool v) { portb.b3 = v; } + bool get() { return portb.b3; } + } + + b4 implements digitalport { + void mode(port_mode m) { ddrb.b4 = m; } + void set(bool v) { portb.b4 = v; } + bool get() { return portb.b4; } + } + + b5 implements digitalport { + void mode(port_mode m) { ddrb.b5 = m; } + void set(bool v) { portb.b5 = v; } + bool get() { return portb.b5; } + } + + void enable_led() { + b5.mode(port_mode.output); + } + + void set_led(bool s) { + b5.set(s); + } + + void wait_us(int16 us) { + while us > 0 { + __delay_us(); + us--; + } + } + + void wait_ms(int16 ms) { + while ms > 0 { + wait_us(1000); + ms--; + } + } + + spi implements databus { + /* setup hardware SPI at: + b3 = MOSI + b4 = MISO + b5 = SCK */ + void setup(int32 speed) { + b3.mode(port_mode.output); + b4.mode(port_mode.input); + b5.mode(port_mode.output); + SPCR.MSTR = true; // master + + // ignoring speed for now. Set to fsck/4 = 4Mhz + SPSR.SPI2x = false; + SPCR.SPR0 = false; + SPCR.SPR1 = false; + + SPCR.CPOL = false; + SPCR.CPHA = false; + } + + void enable() { + SPCR.SPE = true; + //SPCR.SPIE = true; + } + + void disable() { + SPCR.SPE = false; + //SPCR.SPIE = false; + } + + void write(uint8 b) { + SPDR = b; + while !SPSR.SPIF; + } + + uint8 read() { + //FIXME + while !SPSR.SPIF; + return SPDR; + } + + bool has_data() { + //FIXME + return SPSR.SPIF; + } + + void start_transaction() { return; } + void end_transaction() { return; } + } + + uart0 implements databus { + void setup(int32 baud) { + // use 2x + UCSR0A.U2X0 = false; + + multipl = 16u; + if UCSR0A.U2X0 == true { + multipl = 8u; + } + + div = uint32(baud) * multipl; + velocity = (clock() / div) - 1; + + // set baudrate + UBRR0 = uint16(velocity); + + // 8 bit + UCSR0B.UCSZ02 = false; + UCSR0C.UCSZ0 = 0x3; + + // no parity + UCSR0C.UPM0 = 0x0; + + // 1 stop bit + UCSR0C.USBS0 = false; + } + + void enable() { + // enable tx and rx + UCSR0B.RXEN0 = true; + UCSR0B.TXEN0 = true; + } + + void disable() { + // disable tx and rx + UCSR0B.RXEN0 = false; + UCSR0B.TXEN0 = false; + } + + void write(uint8 b) { + while UCSR0A.UDRE0 == false; + UDR0 = b; + } + + uint8 read() { + while UCSR0A.RXC0 == false; + return UDR0; + } + + bool has_data() { + return UCSR0A.RXC0; + } + + void start_transaction() { return; } + void end_transaction() { return; } + } + + /*i2c implements databus { + void setup(int32 speed) { + + } + + void enable() { + + } + + void disable() { + + } + + void start_transaction() {} + void end_transaction() {} + void write(uint8 b) {} + uint8 read() {} + + bool has_data() {} + }*/ +} diff --git a/lib/arch/avr/avr5regs.rob b/lib/arch/avr/avr5regs.rob new file mode 100644 index 0000000..acb6c2e --- /dev/null +++ b/lib/arch/avr/avr5regs.rob @@ -0,0 +1,171 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* + * Global Registers + */ + +type SREG_t { + C = false; // Carry Flag + Z = false; // Zero Flag + N = false; // Negative Flag + V = false; // Two’s Complement Overflow Flag + S = false; // Sign Bit + H = false; // Half Carry Flag + T = false; // Bit Copy Storage + I = false; // Global Interrupt Enable +} + +register SREG_t SREG at 0x5f; + + +/* + * IO PORTS + */ + +type PORTB_t { + b0 = false; + b1 = false; + b2 = false; + b3 = false; + b4 = false; + b5 = false; + ignore = uint2(0); +} + +register PORTB_t portb at 0x25; +register PORTB_t ddrb at 0x24; + + +/* + * UART + */ + + type UCSRA_t { + MPCM0 = false; + U2X0 = false; + UPE0 = false; + DOR0 = false; + FE0 = false; + UDRE0 = false; + TXC0 = false; + RXC0 = false; +} + +type UCSRB_t { + TXB80 = false; + RXB80 = false; + UCSZ02 = false; + TXEN0 = false; + RXEN0 = false; + UDRIE0 = false; + TXCIE0 = false; + RXCIE0 = false; +} + +type UCSRC_t { + UCPOL0 = false; + UCSZ0 = uint2(0); + USBS0 = false; + UPM0 = uint2(0); + UMSEL0 = uint2(0); +} + +// USART0 control status register A +register UCSRA_t UCSR0A at 0xc0; + +// USART0 control status register B +register UCSRB_t UCSR0B at 0xc1; + +// USART0 control status register C +register UCSRC_t UCSR0C at 0xc2; + +// USART0 baud rate register, 12 bits +register uint16 UBRR0 at 0xc4; + +// USART0 byte to send/received +register uint8 UDR0 at 0xc6; + + +/* + * SPI + */ + +type SPCR_t { + SPR0 = false; // SPI clock rate 0 + SPR1 = false; // SPI clock rate 1 + CPHA = false; // Clock phase + CPOL = false; // Clock polarity + MSTR = false; // Master + DORD = false; // Data order + SPE = false; // SPI enable + SPIE = false; // SPI interruption enable +} + +// SPI Control Register +register SPCR_t SPCR at 0x4c; + +type SPSR_t { + SPI2x = false; // Double SPI speed + _reserved = uint5(0); + WCOL = false; // Write COLision flag + SPIF = false; // SPI interrupt flag +} + +// SPI Status Register +register SPSR_t SPSR at 0x4d; + +// SPI Data Register +register uint8 SPDR at 0x4e; + + +/* + * I2C (TWI) PC5 = SCL, PC4 = SDA + */ + +// TWI Bit Rate Register +register uint8 TWBR at 0xB8; + +type TWCR_t { + TWINT = false; // TWI interrupt + TWEA = false; // Enable ACK + TWSTA = false; // Start Condition + TWSTO = false; // Stop Condition + TWWC = false; // Write Colision + TWEN = false; // TWI Enable + _reserved = false; + TWIE = false; // TWI interrupt enable +} + +// TWI Control Register +register TWCR_t TWCR at 0xBC; + +type TWSR_t { + TWS = uint5(0); + _reserved = false; + TWPS = uint2(0); +} + +// TWI Status Register +register TWSR_t TWSR at 0xB9; + +// TWI Data Register +register uint8 TWDR at 0xBB; + +type TWAR_t { + TWA = uint7(0); + TWGCE = false; +} + +// TWI Slave Address Register +register TWAR_t TWAR at 0xBA; + +type TWAMR_t { + TWAM = uint7(0); + _reserved = false; +} + +//TWI Slave Address Mask Register +register TWAMR_t TWAMR at 0xBD; diff --git a/lib/convert/itoa.rob b/lib/convert/itoa.rob new file mode 100644 index 0000000..a72824f --- /dev/null +++ b/lib/convert/itoa.rob @@ -0,0 +1,50 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +const itoa_chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + +void itoa(int16 value, int8 base, char[] result) { + if base < 2 or base > 16 { + result[0] = 0; + return; + } + + negative = value < 0; + //abs without branch + mask = value >> 15; + value = (value ^ mask) - mask; + + i = 0; + if value == 0 { + result[i] = '0'; + i++; + } else { + while value != 0 { + temp = value; + value /= base; + result[i] = itoa_chars[temp - value * base]; + //result[i] = itoa_chars[value % base]; + //value /= base; + i++; + } + if negative { + result[i] = '-'; + i++; + } + } + + result[i] = 0; + + // reverse result + j = 0; + i--; + while j < i { + temp = result[j]; + result[j] = result[i]; + result[i] = temp; + j++; + i--; + } +} diff --git a/platformio/examples/avr328p-ssd1306/src/ssd1306.rob b/lib/display/ssd1306spi.rob similarity index 61% rename from platformio/examples/avr328p-ssd1306/src/ssd1306.rob rename to lib/display/ssd1306spi.rob index 88aa0bf..2609f99 100644 --- a/platformio/examples/avr328p-ssd1306/src/ssd1306.rob +++ b/lib/display/ssd1306spi.rob @@ -1,15 +1,36 @@ - -use mcu; -use ports; -use databus; - -type ssd1306 { +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +use intfs.mcu; +use intfs.ports; +use intfs.databus; +use intfs.buffer8; +use intfs.display; + +type ssd1306spi implements display { mmcu = mcu(); datacmd = digitalport(); reset = digitalport(); select = digitalport(); spi = databus(); + framebuffer implements buffer8 { + buff = {{0u:128}:8}; + + uint16 height() { return buff.rows; } + uint16 width() { return buff.cols; } + + uint8 get(uint16 row, uint16 col) { + return buff[row][col]; + } + + void set(uint16 row, uint16 col, uint8 v) { + buff[row][col] = v; + } + } + enum powerstate { SLEEP = 0xAE, ON = 0xAF @@ -32,22 +53,21 @@ type ssd1306 { DISPLAY_MODE_NORMAL = 0xA6, DISPLAY_MODE_INVERTED = 0xA7, MEM_ADDRESSING = 0x20, + SET_COLUMN_ADDRESS = 0x21, CHARGE_PUMP_REGULATOR = 0x8D, CHARGE_PUMP_ON = 0x14, - SET_PAGE_START_ADDR = 0xB0, + SET_PAGE_ADDR = 0x22, SET_COL_LO_NIBBLE = 0x00, SET_COL_HI_NIBBLE = 0x10, NOP = 0xE3 } - enum displayorientation {NORMAL, NORMAL_MIRRORED, UPSIDE_DOWN, UPSIDE_DOWN_MIRRORED} - - int8 pages() { - return 64 / 8; + uint16 rows() { + return framebuffer.height()*8; } - int16 columns() { - return 128; + uint16 columns() { + return framebuffer.width(); } void init_display() { @@ -58,6 +78,9 @@ type ssd1306 { reset_display(); write_command(powerstate.SLEEP); + write_command(commands.SET_DISP_CLOCK); + write_command(0x80); + write_command(commands.SET_MULTIPLEX_RATIO); write_command(0x3F); @@ -66,31 +89,33 @@ type ssd1306 { write_command(commands.SET_DISP_START_LINE); - set_display_orientation(displayorientation.NORMAL); + write_command(commands.CHARGE_PUMP_REGULATOR); + write_command(commands.CHARGE_PUMP_ON); + + // Horizontal memory addressing mode + write_command(commands.MEM_ADDRESSING); + write_command(0x00); write_command(commands.SET_WIRING_SCHEME); write_command(0x12); set_contrast(0x7F); + write_command(commands.SET_PRECHARGE_PERIOD); + write_command(0xF1); + + write_command(commands.SET_VCOM_DESELECT_LEVEL); + write_command(0x40); + write_command(commands.RESUME_TO_RAM_CONTENT); - write_command(commands.DISPLAY_MODE_NORMAL); - // Horizontal memory addressing mode - write_command(commands.MEM_ADDRESSING); - write_command(0x00); - - write_command(commands.SET_DISP_CLOCK); - write_command(0x80); - - write_command(commands.CHARGE_PUMP_REGULATOR); - write_command(commands.CHARGE_PUMP_ON); + set_orientation(displayorientation.NORMAL); write_command(powerstate.ON); } - void set_display_orientation(displayorientation o) { + void set_orientation(displayorientation o) { if (o == displayorientation.NORMAL or o == displayorientation.NORMAL_MIRRORED) { write_command(commands.SET_SEG_REMAP_0); @@ -114,43 +139,73 @@ type ssd1306 { } } - void set_contrast(int8 c) { + void set_contrast(uint8 c) { write_command(commands.SET_CONTRAST); write_command(c); } void reset_display() { reset.set(true); - mmcu.wait_us(3); + mmcu.wait_ms(2); reset.set(false); - mmcu.wait_us(3); + mmcu.wait_ms(10); reset.set(true); } - void write_command(unsigned8 c) { + void write_command(uint8 c) { datacmd.set(false); select.set(false); spi.write(c); select.set(true); } - void write_data(int8 d) { + void write_data(uint8 d) { datacmd.set(true); select.set(false); spi.write(d); - select.set(true); + select.set(true); } void reset_cursor() { + // set page update range + write_command(commands.SET_PAGE_ADDR); + write_command(0x0); + write_command(0x7); + // set column update range + write_command(commands.SET_COLUMN_ADDRESS); + write_command(0); + write_command(127); + } + + /*void write_at(uint8 x, uint8 y) { + write_command(commands.SET_COLUMN_ADDRESS); write_command(commands.SET_PAGE_START_ADDR); - write_command(commands.SET_COL_HI_NIBBLE); - write_command(commands.SET_COL_LO_NIBBLE); + }*/ + + void clear() { + reset_cursor(); + i = 0u; + while i < framebuffer.height() { + j = 0u; + while j < framebuffer.width() { + write_data(0); + j++; + } + i++; + } } - void flip_power() { - write_command(powerstate.SLEEP); - mmcu.wait_ms(1000); - write_command(powerstate.ON); - mmcu.wait_ms(1000); + void update_frame() { + reset_cursor(); + row = 0u; + while row < framebuffer.height() { + col = 0u; + while col < framebuffer.width() { + v = framebuffer.get(row, col); + write_data(v); + col++; + } + row++; + } } } diff --git a/lib/graphic/canvas8.rob b/lib/graphic/canvas8.rob new file mode 100644 index 0000000..c6d5f00 --- /dev/null +++ b/lib/graphic/canvas8.rob @@ -0,0 +1,34 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +use intfs.buffer8; + +type canvas8 { + buffer = buffer8(); + + uint16 width() { + return buffer.width(); + } + + uint16 height() { + return buffer.height()*8; + } + + void set_pixel(uint16 row, uint16 col) { + rowb = row/8; + if col < buffer.width() and rowb < buffer.height() { + v = buffer.get(rowb, col); + buffer.set(rowb, col, v | (1 << uint8(row & 7))); + } + } + + void clear_pixel(uint16 row, uint16 col) { + rowb = row/8; + if col < buffer.width() and rowb < buffer.height() { + v = buffer.get(rowb, col); + buffer.set(rowb, col, v & ~(1 << uint8(row & 7))); + } + } +} diff --git a/lib/intfs/buffer8.rob b/lib/intfs/buffer8.rob new file mode 100644 index 0000000..820b474 --- /dev/null +++ b/lib/intfs/buffer8.rob @@ -0,0 +1,11 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +interface buffer8 { + uint16 height(); + uint16 width(); + uint8 get(uint16 row, uint16 col); + void set(uint16 row, uint16 col, uint8 v); +} diff --git a/lib/intfs/databus.rob b/lib/intfs/databus.rob new file mode 100644 index 0000000..e5ebedc --- /dev/null +++ b/lib/intfs/databus.rob @@ -0,0 +1,15 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +interface databus { + void setup(int32 speed); + void enable(); + void disable(); + void write(uint8 b); + uint8 read(); + bool has_data(); + void start_transaction(); + void end_transaction(); +} diff --git a/lib/intfs/display.rob b/lib/intfs/display.rob new file mode 100644 index 0000000..8e4de4a --- /dev/null +++ b/lib/intfs/display.rob @@ -0,0 +1,16 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +enum displayorientation {NORMAL, NORMAL_MIRRORED, UPSIDE_DOWN, UPSIDE_DOWN_MIRRORED} + +interface display { + uint16 rows(); + uint16 columns(); + void init_display(); + void set_orientation(displayorientation o); + void set_contrast(uint8 c); + void update_frame(); + void clear(); +} diff --git a/platformio/examples/avr328p-ssd1306/src/mcu.rob b/lib/intfs/mcu.rob similarity index 50% rename from platformio/examples/avr328p-ssd1306/src/mcu.rob rename to lib/intfs/mcu.rob index acecc8a..7e9e745 100644 --- a/platformio/examples/avr328p-ssd1306/src/mcu.rob +++ b/lib/intfs/mcu.rob @@ -1,8 +1,13 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ interface mcu { void wait_us(int16 us); void wait_ms(int16 ms); void enable_led(); - void set_led(bool s); + void set_led(bool s); void set_interruptions(bool enabled); + uint32 clock(); } diff --git a/lib/intfs/ports.rob b/lib/intfs/ports.rob new file mode 100644 index 0000000..ed81fb6 --- /dev/null +++ b/lib/intfs/ports.rob @@ -0,0 +1,18 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +enum port_mode { input, output } + +interface digitalport { + void mode(port_mode m); + void set(bool v); + bool get(); +} + +interface analogport { + void mode(port_mode m); + void set(int16 v); + int16 get(); +} diff --git a/lib/math/limits.rob b/lib/math/limits.rob new file mode 100644 index 0000000..4c93d77 --- /dev/null +++ b/lib/math/limits.rob @@ -0,0 +1,27 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +const char_max = 255u; + +const uint8_max = 255u; +const uint16_max = 65535u; +const uint32_max = 4294967295u; +const uint64_max = 18446744073709551615u; + +const int8_min = -128; +const int8_max = 127; +const int16_min = -32768; +const int16_max = 32767; +const int32_min = -2147483648; +const int32_max = 2147483647; +const int64_min = -9223372036854775808; +const int64_max = 9223372036854775807; + +const float_min = 1.175494351E-38; +const float_max = 3.402823466E+38; +const double_min = 2.2250738585072014E-308; +const double_max = 1.7976931348623158E+308; +const ldouble_min = 3.36210314311209350626267781732175260E-4932; +const ldouble_max = 6.47517511943802511092443895822764655E-4966; diff --git a/lib/math/random16.rob b/lib/math/random16.rob new file mode 100644 index 0000000..24d02d1 --- /dev/null +++ b/lib/math/random16.rob @@ -0,0 +1,45 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* + * A simple 16 bit pseudo random number generator, based + * on wyhash: https://github.com/wangyi-fudan/wyhash and + * Daniel Lemire, "A fast 16-bit random number generator?", + * 2019, at https://lemire.me/blog/2019/07/03/a-fast-16-bit + */ + +use limits; + +random_seed16 = 0xE7A8; + +void srandom16(uint16 seed) { + random_seed16 = seed; +} + +uint16 random16() { + random_seed16 += 0xfc15; + n = uint32(random_seed16) * 0x2ab; + return uint16((n >> 16) ^ n); +} + +/* + * Based on the work: Fast Random Integer Generation in an Interval + * by Daniel Lemire, 2018. https://arxiv.org/abs/1805.10941. + */ +uint16 random16ub(uint16 upto) { + x = random16(); + m = uint32(x) * upto; + l = uint16(m); + if (l < upto) { + t = (uint16_max - upto + 1) % upto; + while (l < t) { + x = random16(); + m = uint32(x) * upto; + l = uint16(m); + } + } + return uint16(m >> 16); +} + diff --git a/lib/math/random32.rob b/lib/math/random32.rob new file mode 100644 index 0000000..a387f99 --- /dev/null +++ b/lib/math/random32.rob @@ -0,0 +1,57 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* This is a pseudo random number generator based on the article + * "Random number generators: good ones are hard to find", by + * Park and Miller, Communications of the ACM, vol. 31, no. 10, + * October 1988, p. 1195. + */ + +use limits; + +const random_seed32_start = 0x262028EB; +const random_max32 = 0x7FFFFFFF; + +random_seed32 = uint32(random_seed32_start); + +void srandom32(uint32 seed) { + random_seed32 = seed; +} + +uint32 random32() { + x = random_seed32; + /* Can't be zero */ + if (x == 0) { + x = random_seed32_start; + } + hi = x / 127773; + lo = x % 127773; + x = 16807 * lo - 2836 * hi; + if (x < 0) { + x += random_max32; + } + random_seed = x; + return (random_seed % (random_max32 + 1u)); +} + +/* + * Based on the work: Fast Random Integer Generation in an Interval + * by Daniel Lemire, 2018. https://arxiv.org/abs/1805.10941. + */ +uint32 random32ub(uint32 upto) { + x = random32(); + m = uint64(x) * upto; + l = uint32(m); + if (l < upto) { + t = (uint32_max - upto + 1) % upto; + while (l < t) { + x = random32(); + m = uint64(x) * upto; + l = uint32(m); + } + } + return uint32(m >> 32); +} + diff --git a/platformio/examples/avr328p-ssd1306/genll.sh b/platformio/examples/avr328p-ssd1306/genll.sh new file mode 100755 index 0000000..c217ae9 --- /dev/null +++ b/platformio/examples/avr328p-ssd1306/genll.sh @@ -0,0 +1,11 @@ +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ /Users/thborges/.platformio/packages/toolchain-robcmp/lib/avr328p.rob > lls/avr328p.rob.ll +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/main.rob > lls/main.rob.ll +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/avr/avr5mcu.rob > lls/avr5mcu.rob.ll +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/avr/avr5regs.rob > lls/avr5regs.rob.ll +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/display/ssd1306.rob > lls/ssd1306.rob.ll +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/buffer8.rob > lls/buffer8.rob.ll +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/canvas8.rob > lls/canvas8.rob.ll +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/databus.rob > lls/databus.rob.ll +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/display.rob > lls/display.rob.ll +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/mcu.rob > lls/mcu.rob.ll +./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/ports.rob > lls/ports.rob.ll diff --git a/platformio/examples/avr328p-ssd1306/src/avr5mcu.rob b/platformio/examples/avr328p-ssd1306/src/avr5mcu.rob deleted file mode 100644 index 15b68cb..0000000 --- a/platformio/examples/avr328p-ssd1306/src/avr5mcu.rob +++ /dev/null @@ -1,128 +0,0 @@ - -use mcu; -use ports; -use databus; - -use avr5regs; - -void __delay_us(); - -type avr5mcu implements mcu { - - void set_interruptions(bool enabled) { - sreg.I = enabled; - } - - /* implement this idea later! - template digport { - void mode(m port_mode) { port_config = mode; } - void set(bool v) { port = v; } - bool get() { return port; } - } - b0 = digport - */ - - b0 = digitalport { - void mode(port_mode m) { ddrb.b0 = m; } - void set(bool v) { portb.b0 = v; } - bool get() { return portb.b0; } - } - - b1 = digitalport { - void mode(port_mode m) { ddrb.b1 = m; } - void set(bool v) { portb.b1 = v; } - bool get() { return portb.b1; } - } - - b2 = digitalport { - void mode(port_mode m) { ddrb.b2 = m; } - void set(bool v) { portb.b2 = v; } - bool get() { return portb.b2; } - } - - b3 = digitalport { - void mode(port_mode m) { ddrb.b3 = m; } - void set(bool v) { portb.b3 = v; } - bool get() { return portb.b3; } - } - - b4 = digitalport { - void mode(port_mode m) { ddrb.b4 = m; } - void set(bool v) { portb.b4 = v; } - bool get() { return portb.b4; } - } - - b5 = digitalport { - void mode(port_mode m) { ddrb.b5 = m; } - void set(bool v) { portb.b5 = v; } - bool get() { return portb.b5; } - } - - void enable_led() { - b5.mode(port_mode.output); - } - - void set_led(bool s) { - b5.set(s); - } - - void wait_us(int16 us) { - while us > 0 { - __delay_us(); - us--; - } - } - - void wait_ms(int16 ms) { - while ms > 0 { - wait_us(1000); - ms--; - } - } - - spi = databus { - // b3 = MOSI - // b4 = MISO - // b5 = SCK - void setup(int32 speed) { - b3.mode(port_mode.output); - b4.mode(port_mode.input); - b5.mode(port_mode.output); - spcr.MSTR = true; // master - - // ignoring speed for now - //spcr.SPR0 = true; // fck/16 - //spcr.SPR1 = false; - - //spcr.CPOL = true; - //spcr.CPHA = true; - spsr.SPI2x = true; // 2x speed - } - - void enable() { - spcr.SPE = true; - //spcr.SPIE = true; - } - - void disable() { - spcr.SPE = false; - //spcr.SPIE = false; - } - - void write(unsigned8 b) { - spdr = b; - while !spsr.SPIF; - } - - int8 read() { - //FIXME - while !spsr.SPIF; - return spdr; - } - - bool has_data() { - //FIXME - return spsr.SPIF; - } - } -} diff --git a/platformio/examples/avr328p-ssd1306/src/avr5regs.rob b/platformio/examples/avr328p-ssd1306/src/avr5regs.rob deleted file mode 100644 index 07759ca..0000000 --- a/platformio/examples/avr328p-ssd1306/src/avr5regs.rob +++ /dev/null @@ -1,67 +0,0 @@ - -/* - * Global Registers - */ - -type sreg_t { - C = false; // Carry Flag - Z = false; // Zero Flag - N = false; // Negative Flag - V = false; // Two’s Complement Overflow Flag - S = false; // Sign Bit - H = false; // Half Carry Flag - T = false; // Bit Copy Storage - I = false; // Global Interrupt Enable -} - -register sreg_t sreg at 0x5f; - - -/* - * IO PORTS - */ - -type portb_t { - b0 = false; - b1 = false; - b2 = false; - b3 = false; - b4 = false; - b5 = false; - ignore = int2(); -} - -register portb_t portb at 0x25; -register portb_t ddrb at 0x24; - -/* - * SPI stuff - */ - -type spcr_t { - SPR0 = false; // SPI clock rate 0 - SPR1 = false; // SPI clock rate 1 - CPHA = false; // Clock phase - CPOL = false; // Clock polarity - MSTR = false; // Master - DORD = false; // Data order - SPE = false; // SPI enable - SPIE = false; // SPI interruption enable -} - -// SPI Control Register -register spcr_t spcr at 0x4c; - -type spsr_t { - SPI2x = false; // Double SPI speed - _reserved = int5(0); - WCOL = false; // Write COLision flag - SPIF = false; // SPI interrupt flag -} - -// SPI Status Register -register spsr_t spsr at 0x4d; - -// SPI Data Register -register int8 spdr at 0x4e; - diff --git a/platformio/examples/avr328p-ssd1306/src/databus.rob b/platformio/examples/avr328p-ssd1306/src/databus.rob deleted file mode 100644 index 8d8667d..0000000 --- a/platformio/examples/avr328p-ssd1306/src/databus.rob +++ /dev/null @@ -1,9 +0,0 @@ - -interface databus { - void setup(int32 speed); - void enable(); - void disable(); - void write(unsigned8 b); - int8 read(); - bool has_data(); -} diff --git a/platformio/examples/avr328p-ssd1306/src/main.rob b/platformio/examples/avr328p-ssd1306/src/main.rob index 15d933e..4ff33b1 100644 --- a/platformio/examples/avr328p-ssd1306/src/main.rob +++ b/platformio/examples/avr328p-ssd1306/src/main.rob @@ -1,55 +1,78 @@ /* * Robcmp examples: SSD1306 SPI */ -use avr5mcu; -use ssd1306; +use arch.avr.avr5mcu; +use display.ssd1306spi; +use graphic.canvas8; +use math.random16; +use intfs.mcu; +use intfs.display; +use intfs.databus; bind avr5mcu to global_instances.mmcu singleton; bind avr5mcu.spi to global_instances.spi singleton; -bind avr5mcu to ssd1306.mmcu singleton; -bind avr5mcu.b0 to ssd1306.reset singleton; -bind avr5mcu.b1 to ssd1306.datacmd singleton; -bind avr5mcu.b2 to ssd1306.select singleton; -bind avr5mcu.spi to ssd1306.spi singleton; - -// for now, the binding only work inside types. -// this is a type for holding an instance of mcu +bind avr5mcu to ssd1306spi.mmcu singleton; +bind avr5mcu.b0 to ssd1306spi.reset singleton; +bind avr5mcu.b1 to ssd1306spi.datacmd singleton; +bind avr5mcu.b2 to ssd1306spi.select singleton; +bind avr5mcu.spi to ssd1306spi.spi singleton; +bind ssd1306spi to global_instances.oled singleton; +bind ssd1306spi.framebuffer to canvas8.buffer singleton; + +// for now, the binding only works inside a type type global_instances { mmcu = mcu(); spi = databus(); + oled = display(); } int16 main() { gi = global_instances(); mmcu = gi.mmcu; - - // setup and enable SPI spi = gi.spi; + oled = gi.oled; + canvas = canvas8(); + spi.setup(0); spi.enable(); + oled.init_display(); + oled.set_orientation(displayorientation.UPSIDE_DOWN); + + /*ball = {0b00000000, + 0b00011000, + 0b00111100, + 0b01111110, + 0b11111111, + 0b01111110, + 0b00111100, + 0b00011000};*/ + + col = 0u; + row = 0u; - display = ssd1306(); - display.init_display(); - - data = 2; loop { - mmcu.wait_ms(1000); - display.reset_cursor(); - - i = 0; - while i < display.pages() { - j = int16(0); - while j < display.columns() { - display.write_data(data); - j++; - } - i++; - } - - data *= 2; - if data == 0 { - data = 1; - } + canvas.clear_pixel(row, col); + canvas.clear_pixel(row+1, col); + canvas.clear_pixel(row+1, col+1); + canvas.clear_pixel(row, col+1); + + col++; + row++; + + if col == canvas.width()-1 { + col = random16ub(canvas.width()-1); + row = random16ub(canvas.height()-1); + } + if row == canvas.height()-1 { + row = random16ub(canvas.height()-1); + } + + canvas.set_pixel(row, col); + canvas.set_pixel(row+1, col); + canvas.set_pixel(row+1, col+1); + canvas.set_pixel(row, col+1); + + oled.update_frame(); } } diff --git a/platformio/examples/avr328p-ssd1306/src/main.spec b/platformio/examples/avr328p-ssd1306/src/main.spec new file mode 100644 index 0000000..5ba2831 --- /dev/null +++ b/platformio/examples/avr328p-ssd1306/src/main.spec @@ -0,0 +1 @@ +bind avr5mcu to aux.mmcu; \ No newline at end of file diff --git a/platformio/examples/avr328p-ssd1306/src/ports.rob b/platformio/examples/avr328p-ssd1306/src/ports.rob deleted file mode 100644 index f91d241..0000000 --- a/platformio/examples/avr328p-ssd1306/src/ports.rob +++ /dev/null @@ -1,14 +0,0 @@ - -enum port_mode { input, output } - -interface digitalport { - void mode(port_mode m); - void set(bool v); - bool get(); -} - -interface analogport { - void mode(port_mode m); - void set(int16 v); - int16 get(); -} diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index deb89f6..85b6e01 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -10,6 +10,7 @@ env = DefaultEnvironment() platform = env.PioPlatform() ldscripts_folder = join(platform.get_package_dir("toolchain-robcmp"), "lib") +stdlib_folder = join(platform.get_package_dir("toolchain-robcmp"), "stdlib") os.environ['LD_LIBRARY_PATH'] = ldscripts_folder @@ -34,13 +35,17 @@ env.Exit(1) build_type = env.subst("$BUILD_TYPE") -robcmp_args = ["robcmp", "-a", board, "-o", "$TARGET"] +robcmp_args = ["robcmp", "-bdep", "-a", board, "-o", "$TARGET"] if build_type == "debug": robcmp_args.append("-g") robcmp_args.append("-O0") elif build_type == "release": - robcmp_args.append("-Oz") - ldflags.append("--gc-sections") + robcmp_args.append("-O3") +ldflags.append("--gc-sections") +ldflags.append("--lto=thin") + +robcmp_args.append("-I") +robcmp_args.append(stdlib_folder) robcmp_args.append("$SOURCE") if board.startswith("avr"): @@ -58,6 +63,7 @@ ), Linker=Builder( action = ' '.join(["ld.lld", "$SOURCES", ' '.join(ldflags), "-o", "$TARGET"]), + #action = ' '.join(["avr-ld", "$SOURCES", ' '.join(ldflags), "-o", "$TARGET"]), suffix=".elf" ), Rob=Builder( @@ -68,8 +74,8 @@ ) ) -sources += Glob(env.subst(join("$PROJECT_DIR/src/", "*.rob"))) -#source_fnames = [join("$PROJECT_DIR/src/", f.name) for f in sources] +sources += Glob(env.subst(join("$PROJECT_DIR/src/", "main.rob"))) +#sources += Glob(env.subst(join("$PROJECT_DIR/src/**/", "*.rob"))) #print("SOURCES: ", source_fnames) target_objs = [] @@ -99,7 +105,7 @@ avrdude_cfg = join(platform.get_package_dir("tool-avrdude"), "avrdude.conf") env.Replace( UPLOADER=avrdude_bin, - UPLOADERFLAGS=["-C", avrdude_cfg, "-v", "-V", "-c", "arduino", "-p", "m328p", "-U"], + UPLOADERFLAGS=["-C", avrdude_cfg, "-v", "-V", "-c", "arduino", "-p", "m328p", "-b", "57600", "-U"], UPLOADCMD='$UPLOADER $UPLOADERFLAGS flash:w:${SOURCE}:i -P $UPLOAD_PORT' ) diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 5575439..db85434 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -160,7 +160,8 @@ void print_llvm_ir(char opt_level) { if (ol == OptimizationLevel::O0) modulePassManager = passBuilder.buildO0DefaultPipeline(ol); else - modulePassManager = passBuilder.buildPerModuleDefaultPipeline(ol); + //modulePassManager = passBuilder.buildPerModuleDefaultPipeline(ol); + modulePassManager = passBuilder.buildThinLTODefaultPipeline(ol, nullptr); modulePassManager.run(*mainmodule, moduleAnalysisManager); diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index b4f5e43..2116345 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -10,23 +10,23 @@ BuildTypes::BuildTypes(DataType targetPointerType) { tinfo[tvoid] = {"void", 0, Type::getVoidTy(global_context), dwarf::DW_ATE_address}; tinfo[tbool] = {"bool", 1, Type::getInt1Ty(global_context), dwarf::DW_ATE_boolean}; tinfo[tchar] = {"char", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned_char}; - tinfo[tint2] = {"int2", 2, Type::getIntNTy(global_context, 2), dwarf::DW_ATE_signed}; - tinfo[tint3] = {"int3", 3, Type::getIntNTy(global_context, 3), dwarf::DW_ATE_signed}; - tinfo[tint4] = {"int4", 4, Type::getIntNTy(global_context, 4), dwarf::DW_ATE_signed}; - tinfo[tint5] = {"int5", 5, Type::getIntNTy(global_context, 5), dwarf::DW_ATE_signed}; - tinfo[tint6] = {"int6", 6, Type::getIntNTy(global_context, 6), dwarf::DW_ATE_signed}; - tinfo[tint7] = {"int7", 7, Type::getIntNTy(global_context, 7), dwarf::DW_ATE_signed}; tinfo[tint8] = {"int8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_signed}; tinfo[tint16] = {"int16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_signed}; tinfo[tint32] = {"int32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_signed}; tinfo[tint64] = {"int64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_signed}; + tinfo[tint2u] = {"uint2", 2, Type::getIntNTy(global_context, 2), dwarf::DW_ATE_unsigned}; + tinfo[tint3u] = {"uint3", 3, Type::getIntNTy(global_context, 3), dwarf::DW_ATE_unsigned}; + tinfo[tint4u] = {"uint4", 4, Type::getIntNTy(global_context, 4), dwarf::DW_ATE_unsigned}; + tinfo[tint5u] = {"uint5", 5, Type::getIntNTy(global_context, 5), dwarf::DW_ATE_unsigned}; + tinfo[tint6u] = {"uint6", 6, Type::getIntNTy(global_context, 6), dwarf::DW_ATE_unsigned}; + tinfo[tint7u] = {"uint7", 7, Type::getIntNTy(global_context, 7), dwarf::DW_ATE_unsigned}; tinfo[tint8u] = {"uint8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tint16u] = {"uint16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tint32u] = {"uint32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tint64u] = {"uint64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tfloat] = {"float", 32, Type::getFloatTy(global_context), dwarf::DW_ATE_float}; tinfo[tdouble] = {"double", 64, Type::getDoubleTy(global_context), dwarf::DW_ATE_float}; - tinfo[tldouble] = {"long double", 128, Type::getFP128Ty(global_context), dwarf::DW_ATE_float}; + tinfo[tldouble] = {"ldouble", 128, Type::getFP128Ty(global_context), dwarf::DW_ATE_float}; unsigned pts = tinfo[targetPointerType].bitWidth; @@ -97,7 +97,7 @@ DataType BuildTypes::getType(const string& name, bool createUndefined) { dti.isComplex = true; return addDataType(dti); } - } else /*if (tinfo[ut->second].isDefined || createUndefined)*/ { + } else { return ut->second; } return undefinedType; diff --git a/src/BuildTypes.h b/src/BuildTypes.h index f1c7388..179debb 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -10,8 +10,10 @@ typedef int DataType; /* Don't change the order of these types without updating the code below accordingly. In another words, don't change it. */ -enum BasicDataType {tvoid, tbool, tchar, tint2, tint3, tint4, tint5, tint6, tint7, - tint8, tint16, tint32, tint64, tint8u, tint16u, tint32u, tint64u, +enum BasicDataType {tvoid, tbool, tchar, + tint8, tint16, tint32, tint64, + tint2u, tint3u, tint4u, tint5u, tint6u, tint7u, + tint8u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, /* new types here! */ __bdt_last}; @@ -90,6 +92,10 @@ class BuildTypes { return tinfo[tid].name.c_str(); } + void updateName(DataType tid, const string& name) { + tinfo[tid].name = name; + } + const unsigned bitWidth(DataType tid) { assert(tid != -1 && "Undefined type"); return tinfo[tid].bitWidth; @@ -129,7 +135,7 @@ class BuildTypes { } bool isUnsignedDataType(DataType tid) const { - return (tid >= tint8u && tid <= tint64u) || (tid == tchar); + return (tid >= tint2u && tid <= tint64u) || (tid == tchar); } bool isFloatDataType(DataType tid) const { @@ -195,6 +201,8 @@ class BuildTypes { assert(isUnsignedDataType(tid)); if (tid == tchar) return tint8; + else if (tid >= tint2u && tid <= tint7u) + return tint8; else return tid - (tint64u - tint64); } diff --git a/src/ConstructorCall.h b/src/ConstructorCall.h index 6cb7aa3..55ce111 100644 --- a/src/ConstructorCall.h +++ b/src/ConstructorCall.h @@ -23,4 +23,14 @@ class ConstructorCall: public Node { dt = buildTypes->getType(name); return dt; } + + virtual map const& getSymbols() override { + getDataType(); + if (dt != BuildTypes::undefinedType) { + auto symbol = findSymbol(name); + if (symbol) + return symbol->getSymbols(); + } + return symbols; + } }; diff --git a/src/Dispatch.cpp b/src/Dispatch.cpp new file mode 100644 index 0000000..5a2e60c --- /dev/null +++ b/src/Dispatch.cpp @@ -0,0 +1,91 @@ + +#include "Dispatch.h" +#include "Identifier.h" +#include "Interface.h" +#include "FunctionImpl.h" +#include "BackLLVM.h" + +void Dispatch::addDataTypeImplementation(DataType base, DataType impl) { + set& impls = dispatchHash[base]; + impls.insert(impl); +} + +void Dispatch::generateDispatchFunctions(Node *scope) { + + /* for each base type, generates a function: + void base_type.method(this) { + switch (this.id) { + case x: xtype->method(this); + case y: ytype->method(this); + ... + } + } + */ + + for(auto& [baseType, impls] : dispatchHash) { + string baseTypeName = buildTypes->name(baseType); + Identifier baseTypeId(baseTypeName, scope->getLoc()); + Node *baseTypeNode = baseTypeId.getSymbol(scope); + Interface *baseTypeTy = dynamic_cast(baseTypeNode); + + for(const auto & [method, function] : baseTypeTy->getSymbols()) { + if (FunctionDecl *functionDecl = dynamic_cast(function)) { + + // if the function is declared in this module, FunctionCall already create it + string dispatchFuncName = baseTypeName + ":" + method; + Function *dispatchFunc = mainmodule->getFunction(dispatchFuncName); + if (!dispatchFunc) { + dispatchFunc = Function::Create(functionDecl->getLLVMFunction()->getFunctionType(), + Function::ExternalLinkage, codeAddrSpace, dispatchFuncName, mainmodule); + dispatchFunc->setDSOLocal(true); + dispatchFunc->setCallingConv(CallingConv::C); + if (impls.size() == 1) + dispatchFunc->addFnAttr(Attribute::AlwaysInline); + } + + auto fblock = BasicBlock::Create(global_context, "", dispatchFunc); + Builder->SetInsertPoint(fblock); + + // the first field of arg this is the object type id + Type *thisTy = buildTypes->llvmType(functionDecl->getThisArgDt()); + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); + Value *indexList[2] = {zero, zero}; + Type *idType = Type::getInt8Ty(global_context); + Value *idValue = Builder->CreateLoad(idType, functionDecl->getThisArg(), "typeid"); + + SwitchInst *switchi = Builder->CreateSwitch(idValue, NULL, impls.size()); + + int caseid = 0; + for(DataType implDt : impls) { + auto implDtBlock = BasicBlock::Create(global_context, "", dispatchFunc); + Builder->SetInsertPoint(implDtBlock); + + vector args; + for(auto& arg : dispatchFunc->args()) { + args.push_back(&arg); + } + + string destTypeName = buildTypes->name(implDt); + string destFuncName = destTypeName + ":" + method; + Function *destFunc = mainmodule->getFunction(destFuncName); + + Value *call = Builder->CreateCall(destFunc, args); + if (call->getType()->isVoidTy()) + Builder->CreateRetVoid(); + else + Builder->CreateRet(call); + + // add switch case + Builder->SetInsertPoint(fblock); + if (caseid == 0) + switchi->setDefaultDest(implDtBlock); + else { + ConstantInt *implDtId = ConstantInt::get(Type::getInt8Ty(global_context), implDt, true); // TODO: provide better ids, per baseType + switchi->addCase(implDtId, implDtBlock); + } + caseid++; + } + } + } + } +} \ No newline at end of file diff --git a/src/Dispatch.h b/src/Dispatch.h new file mode 100644 index 0000000..d23baf5 --- /dev/null +++ b/src/Dispatch.h @@ -0,0 +1,17 @@ + +#pragma once + +#include +#include +#include "BuildTypes.h" + +//using namespace std; + +class Dispatch { +protected: + map> dispatchHash; + +public: + void addDataTypeImplementation(DataType base, DataType impl); + void generateDispatchFunctions(Node *scope); +}; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index f495c2a..24d1857 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -89,26 +89,37 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock Node *param = parameters->getParamElement(i); DataType call_dt = param->getDataType(); DataType def_dt = fsymbol->getParameters().getParamType(i); + string argName = fsymbol->getParameters().getParamName(i); Value *valor = param->generate(func, block, allocblock); - if (!valor) + if (!valor) { + yyerrorcpp(string_format("The value for argument %s is undefined.", argName.c_str()), param); return NULL; + } if (buildTypes->isInterface(call_dt)) { valor = Builder->CreateLoad(valor->getType()->getPointerTo(), valor, "defer"); } else if (buildTypes->isComplex(call_dt)) { //we don't support cohercion between user types yet if (call_dt != def_dt) { - yyerrorcpp(string_format("Argument %s expects '%s' but '%s' was provided.", - fsymbol->getParameters().getParamName(i).c_str(), - buildTypes->name(def_dt), - buildTypes->name(call_dt)), this); - yywarncpp("The function declaration is here.", fsymbol); + Node *utnode = findSymbol(buildTypes->name(call_dt)); + UserType *ut = dynamic_cast(utnode); + + if (ut && ut->implementsInterface(buildTypes->name(def_dt))) { + program->getDispatcher()->addDataTypeImplementation(def_dt, call_dt); + + } else if (!ut || !ut->implementsInterface(buildTypes->name(def_dt))) { + yyerrorcpp(string_format("Argument %s expects '%s' but '%s' was provided.", + argName.c_str(), + buildTypes->name(def_dt), + buildTypes->name(call_dt)), this); + yywarncpp("The function declaration is here.", fsymbol); + } } } else if (buildTypes->isArrayOrMatrix(call_dt)) { if (call_dt != def_dt) { yyerrorcpp(string_format("Argument %s expects '%s' but '%s' was provided.", - fsymbol->getParameters().getParamName(i).c_str(), + argName.c_str(), buildTypes->name(def_dt), buildTypes->name(call_dt)), this); } @@ -178,14 +189,19 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock if (stemSymbol && buildTypes->isInterface(stemSymbol->getDataType())) { string inject_name; - if (UserType *ut = dynamic_cast(stemSymbol->getScope())) - inject_name = stemSymbol->getScope()->getName() + ":"; + if (UserType *ut = dynamic_cast(stemSymbol->getScope())) { + inject_name = stemSymbol->getScope()->getName(); + inject_name.append(":" + stemSymbol->getName() + ":"); + } else if (buildTypes->isUserType(stemSymbol->getScope()->getDataType())) { inject_name = buildTypes->name(stemSymbol->getScope()->getDataType()); + inject_name.append(":" + stemSymbol->getName() + ":"); + } + else if (buildTypes->isInterface(stemSymbol->getDataType())) { + inject_name = buildTypes->name(stemSymbol->getDataType()); inject_name.append(":"); } - inject_name.append(stemSymbol->getName() + ":"); inject_name.append(ident.getLastName()); Function *intf_cfunc = mainmodule->getFunction(inject_name); if (!intf_cfunc) { diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 020375b..971770c 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -112,6 +112,14 @@ Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocbloc if (buildTypes->isUnsignedDataType(ptype)) Arg.addAttr(Attribute::ZExt); + + const string& argname = fp->getName(); + if (argname == ":this") { + thisArg = &Arg; + } else if (argname == ":parent") { + parentArg = &Arg; + } + Idx++; } diff --git a/src/Int8.h b/src/Int8.h index f2a556c..46f06dd 100644 --- a/src/Int8.h +++ b/src/Int8.h @@ -13,6 +13,7 @@ class Int8: public Node { } int8_t getNumber() const { return number; } + void setNumber(int8_t n) { number = n; } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; @@ -31,6 +32,7 @@ class UInt8: public Node { } uint8_t getNumber() const { return number; } + void setNumber(uint8_t n) { number = n; } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; diff --git a/src/Language.y b/src/Language.y index 2bbd4af..7694e7e 100644 --- a/src/Language.y +++ b/src/Language.y @@ -30,7 +30,8 @@ %type paramscall %type TOK_IDENTIFIER TOK_XIDENTIFIER ident_or_xident -%type TOK_INTEGER TOK_CHAR qualifier bind_scope +%type TOK_CHAR +%type TOK_INTEGER qualifier bind_scope %type TOK_UINTEGER %type TOK_FLOAT %type TOK_DOUBLE @@ -39,13 +40,10 @@ %% -programa : globals { +programa : globals { for(auto stmt : *($globals)) { program->addChild(stmt); } - - if (errorsfound == 0) - program->generate(); }; globals : globals global { @@ -190,8 +188,7 @@ interface_decls : function_decl { $$->push_back($function_decl); } -//FIXME: Interface only allows function_decls! -interface_impl : TOK_IDENTIFIER[id] '=' TOK_IDENTIFIER[intfname] '{' type_stmts '}' { +interface_impl : TOK_IDENTIFIER[id] TOK_IMPL TOK_IDENTIFIER[intfname] '{' type_stmts '}' { vector intf; intf.push_back($intfname); UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(intf), @id); @@ -419,14 +416,13 @@ factor : '(' expr ')' { $$ = $2; } ident_or_xident: TOK_IDENTIFIER | TOK_XIDENTIFIER -unary : '-' factor { $$ = new BinaryOp($2, '*', getNodeForIntConst(-1, @factor)); } - | '~' factor { $$ = new FlipOp($2); } +unary : '-' factor { $$ = new BinaryOp($factor, '*', getNodeForIntConst(-1, @factor)); } + | '~' factor { $$ = new FlipOp($factor); } ; call_or_cast : ident_or_xident[id] '(' paramscall ')' { if (strncmp("copy", $id, 4) == 0 && $paramscall->getNumParams() == 1) $$ = new MemCopy($paramscall->getParamElement(0)); - //else if buildTypes->get($id) && complex, call constructor else { $$ = new FunctionCall($id, $paramscall, @id); } diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index 19b925e..9e9eea8 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -38,6 +38,7 @@ %union { char *ident; char *str; + char ch; int64_t nint; uint64_t unint; float nfloat; diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 1642745..b64464a 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -16,7 +16,7 @@ %type stmts %type global register interface type type_stmt use %type function function_decl function_impl -%type enum enum_item const_expr expr interface_impl +%type enum enum_item const_expr expr unary interface_impl %type simplevar_decl cast constructor %type ignore_stmt ignore_param ignore %type type_impls @@ -32,6 +32,10 @@ %type TOK_IDENTIFIER TOK_XIDENTIFIER %type TOK_INTEGER qualifier %type TOK_UINTEGER +%type TOK_FLOAT +%type TOK_DOUBLE +%type TOK_LDOUBLE +%type TOK_CHAR %printer { fprintf(yyo, "'%s'", $$); } %printer { fprintf(yyo, "'%s'", $$ ? $$->getName().c_str() : ""); } @@ -65,7 +69,13 @@ global : use | function | enum | simplevar_decl ';' { $$ = NULL; } // don't export global vars - | qualifier simplevar_decl ';' { $$ = NULL; } + +global : qualifier simplevar_decl ';' { + if ($qualifier == qconst) + $$ = $simplevar_decl; + else + $$ = NULL; +} use : TOK_USE TOK_IDENTIFIER ';' { parseUseFile($2, @TOK_USE); @@ -179,8 +189,7 @@ interface_decls : function_decl { $$->push_back($function_decl); } -//FIXME: Interface only allows function_decls! -interface_impl : TOK_IDENTIFIER[id] '=' TOK_IDENTIFIER[intfname] '{' type_stmts '}' { +interface_impl : TOK_IDENTIFIER[id] TOK_IMPL TOK_IDENTIFIER[intfname] '{' type_stmts '}' { vector intf; intf.push_back($intfname); UserType *ut = new UserType($id, std::move(*$type_stmts), std::move(intf), @id); @@ -260,10 +269,19 @@ element : expr ':' TOK_INTEGER { $$ = new ArrayElement($1, (unsigned)$3); } const_expr : TOK_INTEGER { $$ = getNodeForIntConst($1, @1); } | TOK_UINTEGER { $$ = getNodeForUIntConst($1, @1); } + | TOK_CHAR { $$ = new Char($1, @1); } | TOK_TRUE { $$ = new Int1(1, @1); } | TOK_FALSE { $$ = new Int1(0, @1); } + | TOK_FLOAT { $$ = new Float($1, @1); } + | TOK_DOUBLE { $$ = new Double($1, @1); } + | TOK_LDOUBLE { $$ = new Float128($1, @1); } + | unary { $$ = $1; } //TODO: Add other constant nodes here! +unary : '-' const_expr { $$ = new BinaryOp($const_expr, '*', getNodeForIntConst(-1, @const_expr)); } + | '~' const_expr { $$ = new FlipOp($const_expr); } + ; + expr : const_expr | cast | constructor diff --git a/src/Load.cpp b/src/Load.cpp index f4a3952..afe7684 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -5,11 +5,11 @@ #include "Variable.h" #include "Pointer.h" -Node* Load::getIdentSymbol() { +Node* Load::getIdentSymbol(bool showError) { if (!identSymbol) { identSymbol = ident.getSymbol(getScope(), false); } - if (!identSymbol) + if (!identSymbol && showError) yyerrorcpp("Symbol " + ident.getFullName() + " not found.", this); return identSymbol; } diff --git a/src/Load.h b/src/Load.h index 030c62c..c86907e 100644 --- a/src/Load.h +++ b/src/Load.h @@ -33,7 +33,7 @@ class Load: public Node { return v.visit(*this); } - Node* getIdentSymbol(); + Node* getIdentSymbol(bool showError = true); friend class SymbolizeTree; }; diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index f7e8c54..d7e4ece 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -13,6 +13,8 @@ DataType LoadArray::getDataType() { Node *symbol = ident.getSymbol(getScope()); if (symbol && buildTypes->isArrayOrMatrix(symbol->getDataType())) dt = buildTypes->getArrayElementType(symbol->getDataType()); + else + setSemanticError(); } return dt; } diff --git a/src/Program.cpp b/src/Program.cpp index 6931880..1081802 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -30,6 +30,13 @@ Program::Program() : Node({0,0,0,0}) { buildTypes = make_unique(currentTarget().pointerType); global_alloc = BasicBlock::Create(global_context, "global"); + + dispatch = new Dispatch(); +} + +Program::~Program() { + delete dispatch; + delete mainmodule; } void Program::declara_auxiliary_c_funcs() { @@ -270,7 +277,7 @@ void Program::generateInjectionSetup(SourceLocation *sl) { extern bool parseIsCompleted; -void Program::generate() { +void Program::doSemanticAnalysis() { parseIsCompleted = true; // instrumentation passes @@ -284,10 +291,12 @@ void Program::generate() { fs.open("ast", std::fstream::out); PrintAstVisitor(fs).visit(*this); fs.close();*/ +} + +void Program::generate() { Node *mainFunc = NULL; - // generate the program! for(auto n: children()) { if (FunctionImpl *func = dynamic_cast(n)) { if (func->getName() == "main" || func->getName() == "__main") { @@ -311,6 +320,8 @@ void Program::generate() { if (mainFunc) mainFunc->generate(NULL, NULL, global_alloc); + dispatch->generateDispatchFunctions(program); + if (debug_info) DBuilder->finalize(); } diff --git a/src/Program.h b/src/Program.h index bb1082c..015d41e 100644 --- a/src/Program.h +++ b/src/Program.h @@ -2,16 +2,25 @@ #pragma once #include "Node.h" +#include "Dispatch.h" class Program : public Node { +protected: + Dispatch *dispatch; public: Program(); + ~Program(); void declara_auxiliary_c_funcs(); Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); void generate(); void generateInjectionSetup(SourceLocation *sl); + void doSemanticAnalysis(); + + Dispatch* getDispatcher() { + return dispatch; + } }; extern Program* program; diff --git a/src/PropagateTypes.cpp b/src/PropagateTypes.cpp index 77e7b80..f1bbdc6 100644 --- a/src/PropagateTypes.cpp +++ b/src/PropagateTypes.cpp @@ -49,9 +49,9 @@ Node* PropagateTypes::coerceTo(Node *n, const DataType destTy, bool warns) { if (name == "") name = "Value"; if (destUnsigned) - yywarncpp(string_format("%s has been returned as unsigned.", name.c_str()), n); + yywarncpp(string_format("%s has been used as unsigned.", name.c_str()), n); else - yywarncpp(string_format("%s has been returned as signed.", name.c_str()), n); + yywarncpp(string_format("%s has been used as signed.", name.c_str()), n); } } } @@ -70,8 +70,8 @@ Node* PropagateTypes::coerceTo(Node *n, const DataType destTy, bool warns) { string name = n->getName(); if (name == "") name = "Value"; - yywarncpp(string_format("%s has been truncated to %s.", name.c_str(), - buildTypes->name(destTy)), n); + yywarncpp(string_format("%s (%s) has been truncated to fit %s.", name.c_str(), + buildTypes->name(valueTy), buildTypes->name(destTy)), n); } return new TruncInt(n, destTy); } @@ -119,8 +119,10 @@ Value *ForcedCast::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *a DataType PropagateTypes::coerceArithOrCmp(Node &n, Node *lNode, Node *rNode) { DataType returnTy = BuildTypes::undefinedType; - if (isUndefined(lNode) || isUndefined(rNode)) + if (isUndefined(lNode) || isUndefined(rNode)) { + n.setSemanticError(); return returnTy; + } DataType lTy = lNode->getDataType(); DataType rTy = rNode->getDataType(); @@ -388,3 +390,68 @@ Node* PropagateTypes::visit(Enum& n) { //propagateChildren(n); return NULL; } + +Node* PropagateTypes::visit(Variable& n) { + + propagateChildren(n); + + Node *firstDecl = n.getScope()->findSymbol(n.getName()); + DataType sameNameDt = buildTypes->getType(n.getName()); + if (sameNameDt != BuildTypes::undefinedType) { + yyerrorcpp(string_format("The name %s is already used to define a type.", n.getName().c_str()), &n); + if (firstDecl) + yywarncpp(string_format("The type %s was defined here.", n.getName().c_str()), firstDecl); + + } else if (firstDecl && firstDecl != &n) { + DataType ndt = n.getDataType(); + DataType fdt = firstDecl->getDataType(); + if (ndt != BuildTypes::undefinedType && + fdt != BuildTypes::undefinedType && + ndt != fdt) { + // the var was first defined as fdt. + // we coherce the right hand side to match it + Node *result = NULL; + if (Scalar *sc = dynamic_cast(&n)) { + result = coerceTo(sc->expr(), fdt); + sc->setExpr(result); + } + if (!result) + yywarncpp(string_format("The symbol %s was first defined here.", n.getName().c_str()), firstDecl); + } + } + return NULL; +} + +Node* PropagateTypes::visit(Scalar& n) { + + Node *result = visit((Variable&)n); + + // although this should be done on SymbolizeTree, + // some type propagarion in the tree change symbols + // for scalars (e.g. FunctionCall -> ConstructorCall) + auto& exprSymbols = n.expr()->getSymbols(); + if (exprSymbols.size() > 0) + n.symbols = exprSymbols; + return NULL; +} + +Node* PropagateTypes::visit(Load& n) { + // although this should be done on SymbolizeTree, + // some type propagarion in the tree change symbols + // for scalars (e.g. FunctionCall -> ConstructorCall) + visit((Node&)n); + Node *identSymbol = n.getIdentSymbol(false); + if (identSymbol) + n.symbols = identSymbol->getSymbols(); + return NULL; +} + +Node* PropagateTypes::visit(MemCopy& n) { + // although this should be done on SymbolizeTree, + // some type propagarion in the tree change symbols + // for scalars (e.g. FunctionCall -> ConstructorCall) + visit((Node&)n); + if (n.children().size() > 0) + n.symbols = n.children()[0]->getSymbols(); + return NULL; +} diff --git a/src/PropagateTypes.h b/src/PropagateTypes.h index e15f324..7ab61b7 100644 --- a/src/PropagateTypes.h +++ b/src/PropagateTypes.h @@ -13,6 +13,8 @@ #include "FunctionImpl.h" #include "FunctionCall.h" #include "Enum.h" +#include "Load.h" +#include "MemCopy.h" class CoercionBase: public Node { protected: @@ -174,7 +176,7 @@ class PropagateTypes: public Visitor { if (name != "") yyerrorcpp(string_format("The type of %s is undefined.", name.c_str()), n); else - yyerrorcpp("The type of the expression is undefined.", n);; + yyerrorcpp("The type of the expression is undefined.", n); return true; } return false; @@ -191,6 +193,11 @@ class PropagateTypes: public Visitor { virtual Node* visit(CmpOp& n) override; virtual Node* visit(BinaryOp& n) override; + virtual Node* visit(Variable& n) override; + virtual Node* visit(Scalar& n) override; + virtual Node* visit(Load& n) override; + virtual Node* visit(MemCopy& n) override; + virtual Node* visit(Array& n) override; virtual Node* visit(Matrix& n) override; virtual Node* visit(UpdateArray& n) override; diff --git a/src/Scalar.h b/src/Scalar.h index 9fd2dc8..4076c31 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -14,6 +14,11 @@ class Scalar: public Variable { return node_children[0]; } + void setExpr(Node *expr) { + node_children[0] = expr; + dt = expr->getDataType(); + } + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; virtual bool isConstExpr() override { diff --git a/src/Scanner.cpp b/src/Scanner.cpp index a172951..39b233f 100644 --- a/src/Scanner.cpp +++ b/src/Scanner.cpp @@ -5,15 +5,17 @@ #include "FlexDependencies.h" #include "Language_gen_y.hpp" -Program *program; +extern Program *program; int errorsfound = 0; -char *build_outputfilename; vector includeDirs; vector buildStack; +stack useStack; vector buildStackScanner; int buildStackCurrent; +bool parseIsCompleted = false; +extern bool build_dependencies; int USElex(YYSTYPE *yylval_param, location_t *yylloc_param, yyscan_t yyscanner) { return MAINlex(yylval_param, yylloc_param, yyscanner); @@ -41,6 +43,9 @@ void MAINerror(location_t *loc, yyscan_t scanner, const char *s) { } void yyerrorcpp(const string& s, SourceLocation *n, bool semantic) { + if (n->hasSemanticError()) + return; + string e; if (semantic) e = COLOR_RED "semantic error: " COLOR_RESET + s; @@ -51,6 +56,7 @@ void yyerrorcpp(const string& s, SourceLocation *n, bool semantic) { fprintf(stderr, "%s:%d:%d: %s\n", n->getFile().c_str(), n->getLineNo(), n->getColNo(), e.c_str()); errorsfound++; + n->setSemanticError(); } void yywarncpp(const string& s, SourceLocation *n) { @@ -93,22 +99,33 @@ bool parseFile(const string& source) { FILE *findFile(string file_name, filesystem::path& file_path) { FILE *f = NULL; + + // include the dir of the current file + if (useStack.size() > 0) + includeDirs.push_back(useStack.top().parent_path()); + for(auto dirit = rbegin(includeDirs); dirit != rend(includeDirs); ++dirit) { filesystem::path test_path(*dirit); test_path /= file_name; - FILE *f = fopen(test_path.string().c_str(), "r"); + f = fopen(test_path.string().c_str(), "r"); if (f) { file_path = test_path; - return f; + break; } } + + if (useStack.size() > 0) + includeDirs.pop_back(); + return f; } bool parseUseFile(const string& use, location_t loc) { // search for and open {use}.rob file - string file_name = use + ".rob"; + const string sep{filesystem::path::preferred_separator}; + string use_file = regex_replace(use, regex("\\."), sep); + string file_name = use_file + ".rob"; filesystem::path file_path; FILE *f = findFile(file_name, file_path); @@ -135,8 +152,9 @@ bool parseUseFile(const string& use, location_t loc) { return true; } - static int buildStackBackup = buildStackCurrent; + int buildStackBackup = buildStackCurrent; buildStack.push_back(file_path); + useStack.push(file_path); buildStackCurrent = buildStack.size()-1; yyscan_t scanner; @@ -146,20 +164,21 @@ bool parseUseFile(const string& use, location_t loc) { MAINset_in(f, scanner); //extern int USEdebug; //USEdebug = 1; - USEparse(scanner); + if (build_dependencies) + MAINparse(scanner); + else + USEparse(scanner); + MAINlex_destroy(scanner); fclose(f); buildStackCurrent = buildStackBackup; buildStackScanner.pop_back(); //buildStack.pop_back(); + useStack.pop(); return true; } int MAINget_lineno(yyscan_t yyscanner); int MAINget_column(yyscan_t yyscanner); - -const filesystem::path* build_file() { - return &buildStack[buildStackCurrent]; -} diff --git a/src/Scanner.h b/src/Scanner.h index d2cf272..25ac814 100644 --- a/src/Scanner.h +++ b/src/Scanner.h @@ -23,5 +23,3 @@ void yywarncpp(const string& s, SourceLocation *n); bool parseFile(const string &source); bool parseUseFile(const string& use, location_t loc); - -const filesystem::path* build_file(); diff --git a/src/SourceLocation.h b/src/SourceLocation.h index f2e2162..03b38ec 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -10,17 +10,18 @@ typedef struct { int last_column; } location_t; -extern const filesystem::path* build_file(); -extern int build_filecolno(); -extern int build_filelineno(); +extern int buildStackCurrent; +extern vector buildStack; class SourceLocation { protected: location_t sloc; - const filesystem::path *file; + int fileNo; + bool semanticError = false; + public: SourceLocation(location_t l) { - file = build_file(); + fileNo = buildStackCurrent; sloc = l; } @@ -45,6 +46,14 @@ class SourceLocation { } virtual const string getFile() const { - return file->string(); + return buildStack[fileNo]; + } + + bool hasSemanticError() { + return semanticError; + } + + void setSemanticError() { + semanticError = true; } }; diff --git a/src/SymbolizeTree.h b/src/SymbolizeTree.h index f2b58c7..883f5f2 100644 --- a/src/SymbolizeTree.h +++ b/src/SymbolizeTree.h @@ -10,6 +10,7 @@ #include "Scalar.h" #include "Load.h" #include "FunctionCall.h" +#include "ConstructorCall.h" #include "MemCopy.h" #include "Enum.h" @@ -18,43 +19,21 @@ class SymbolizeTree: public Visitor { SymbolizeTree() {} virtual Node* visit(Node& n) override { - for(auto& c : n.children()) { + for(auto* c : n.children()) { c->setScope(&n); if (c->hasName()) { //fprintf(stderr, "%s\n", c->getName().c_str()); n.addSymbol(dynamic_cast(c)); } } - for(auto& c : n.children()) { + for(auto* c : n.children()) { c->accept(*this); } return NULL; } - virtual Node* visit(Scalar& n) override { - visit((Node&)n); - if (n.children().size() > 0) - n.symbols = n.children()[0]->getSymbols(); - return NULL; - } - - virtual Node* visit(Load& n) override { - visit((Node&)n); - Node *identSymbol = n.getIdentSymbol(); - if (identSymbol) - n.symbols = identSymbol->getSymbols(); - return NULL; - } - - virtual Node* visit(MemCopy& n) override { - visit((Node&)n); - if (n.children().size() > 0) - n.symbols = n.children()[0]->getSymbols(); - return NULL; - } - virtual Node* visit(Array& n) override { - for(auto& c : n.children()) { + for(auto* c : n.children()) { if (c->hasName()) { n.addSymbol(dynamic_cast(c)); } @@ -67,7 +46,7 @@ class SymbolizeTree: public Visitor { } virtual Node* visit(Matrix& n) override { - for(auto& c : n.children()) { + for(auto* c : n.children()) { if (c->hasName()) { n.addSymbol(dynamic_cast(c)); } diff --git a/src/UserType.cpp b/src/UserType.cpp index a4a12f9..29000ba 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -11,10 +11,11 @@ #include "Enum.h" #include "Load.h" #include "BackLLVM.h" +#include "Int8.h" class ParentScalar: public Scalar { public: - ParentScalar(DataType parentDt, location_t loc) : Scalar("parent", new Load(":parent", loc)) { + ParentScalar(DataType parentDt, location_t loc) : Scalar("parent", new Load("parent", loc)) { expr()->setScope(this); dt = parentDt; pointer = pm_pointer; @@ -29,18 +30,32 @@ class ParentScalar: public Scalar { bool UserType::createDataType() { - if (dt != BuildTypes::undefinedType) + if (dt != BuildTypes::undefinedType) { + // internal types can be created during symbolization, + // while the parent is not set. + if (buildTypes->name(dt) != getName()) + buildTypes->updateName(dt, getName()); return true; - else { - // create an undefined type to use in recursive subtypes - dt = buildTypes->getType(getName(), true); - } - + } + + // create an undefined type to use in recursive subtypes + dt = buildTypes->getType(getName(), true); std::vector elements; int idx = 0; unsigned startBit = 0; vector addedVars; + + // if needed, add typeid as the first field + UInt8 *typeId = NULL; + if (implements.size() > 0) { + typeId = new UInt8(0, getLoc()); // zero is changed below + Scalar *sc = new Scalar("typeid", typeId); + sc->setScope(this); + addChild(sc); + addSymbol(sc); + } + for(auto child : this->children()) { Variable *v = NULL; @@ -59,13 +74,14 @@ bool UserType::createDataType() { // create a new var in the parent to store the intf implementation ConstructorCall *cc = new ConstructorCall(ut->getName(), ut->getLoc()); v = new Scalar(varname, cc); + v->dt = ut->getDataType(); cc->setScope(v); v->setScope(this); addedVars.push_back(v); // fix the symbol table due to the renaming getScope()->addSymbol(ut); - symbols[ut->getName()] = ut; + symbols[ut->getName()] = ut; // init symbols[v->getName()] = v; } else { @@ -73,13 +89,15 @@ bool UserType::createDataType() { } if (v) { - if (buildTypes->isInterface(v->getDataType())) { + DataType vdt = v->getDataType(); + if (vdt == BuildTypes::undefinedType) { + return false; + } else if (buildTypes->isInterface(vdt)) { v->setPointer(pm_pointer); v->setPointerToPointer(true); } else if (v->getPointerMode() == pm_unknown) v->setPointer(pm_nopointer); - DataType vdt = v->getDataType(); if (!buildTypes->isDefined(vdt)) { Node *undeft = Identifier(buildTypes->name(vdt), getLoc()).getSymbol(this); UserType *undefut = dynamic_cast(undeft); @@ -117,6 +135,9 @@ bool UserType::createDataType() { return false; } + if (typeId) + typeId->setNumber(dt); + return true; } @@ -215,6 +236,7 @@ const string UserType::getName() const { } void UserType::addSymbol(NamedNode *nm) { - // overrided here as UserType has its own scope + // addSymbol is overrided here because UserType has its + // own scope and shouldn't call findSymbol recursivelly symbols[nm->getName()] = nm; } diff --git a/src/Visitor.h b/src/Visitor.h index ab4f426..2dc7476 100644 --- a/src/Visitor.h +++ b/src/Visitor.h @@ -8,6 +8,7 @@ class CmpOp; class Delay; class Float; class FunctionCall; +class ConstructorCall; class FunctionDecl; class FunctionImpl; class FunctionBase; @@ -59,6 +60,7 @@ class Visitor { VISITOR_DECLARE(Delay) VISITOR_DECLARE(Float) VISITOR_DECLARE(FunctionCall) + VISITOR_DECLARE(ConstructorCall) VISITOR_DECLARE(If) VISITOR_DECLARE(InPort) VISITOR_DECLARE(Int16) diff --git a/src/main.cpp b/src/main.cpp index eb767ae..3fb51f3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -6,9 +5,12 @@ #include "Scanner.h" #include "Program.h" +Program *program; + void print_llvm_ir(char opt_level); bool debug_info; -extern char *build_outputfilename; +bool build_dependencies; +char *build_outputfilename; char *spec_filename; FILE *specin = NULL; @@ -40,6 +42,7 @@ int main(int argc, char *argv[]) { const char *targetarch = ""; build_outputfilename = NULL; debug_info = false; + build_dependencies = false; if (argc <= 1) { fprintf(stderr, "Syntax: %s -a {", argv[0]); @@ -47,7 +50,7 @@ int main(int argc, char *argv[]) { if (t > 1) fprintf(stderr, ","); fprintf(stderr, "%s", supportedTargets[t].name); } - fprintf(stderr, "} -I {include_dir} -g -O{0,1,2,3,s,z,d} -o output_file -s spec_file input_file\n"); + fprintf(stderr, "} -I {include_dir} -bdep -g -O{0,1,2,3,s,z,d} -o output.o -s in.spec input.rob\n"); return 1; } @@ -66,6 +69,9 @@ int main(int argc, char *argv[]) { else if (strncmp(argv[i], "-g", 2) == 0) { // debug debug_info = true; } + else if (strncmp(argv[i], "-bdep", 5) == 0) { + build_dependencies = true; + } else if (strncmp(argv[i], "-o", 2) == 0) { // output if (i+1 < argc) build_outputfilename = argv[++i]; @@ -103,13 +109,17 @@ int main(int argc, char *argv[]) { if (!parseFile(buildFileName)) exit(1); + program->doSemanticAnalysis(); + if (errorsfound > 0) { fprintf(stderr, "%d error(s) found.\n", errorsfound); - return errorsfound; + } else { + program->generate(); } - print_llvm_ir(optimization); + if (errorsfound <= 0) + print_llvm_ir(optimization); - return 0; + return errorsfound; } diff --git a/test/avr328p/Makefile b/test/avr328p/Makefile index 5d8d1c0..6c5bb5d 100644 --- a/test/avr328p/Makefile +++ b/test/avr328p/Makefile @@ -4,7 +4,7 @@ ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/avr328p.o ROBCMP=../../build/robcmp -INCLUDES=-I aux +INCLUDES=-I ../../lib ifndef OPT #OPT=-g -O0 @@ -14,15 +14,15 @@ endif LD_FLAGS=-nostdlib -entry=main -L../../lib -Tavr328p.ld ../../lib/avr5.o LD_FLAGS+=-Bstatic LD_FLAGS+=--gc-sections +LD_FLAGS+=--lto=thin DEPENDS=${ROBCMP} Makefile LINK_DEPENDS=out/avr328p.o -SERIAL_DEPENDS=out/aux/serial.o out/aux/avr5mcu.o all: out test out: - mkdir -p out/aux + mkdir -p out out/avr328p.o : ../../lib/avr328p.rob ${DEPENDS} ${ROBCMP} -a avr328p ${OPT} -o $@ $< @@ -32,21 +32,19 @@ out/avr328p.ll : ../../lib/avr328p.rob ${DEPENDS} .SECONDARY: out/%.o : %.rob out/avr328p.o ${DEPENDS} - ${ROBCMP} -a avr328p ${OPT} ${INCLUDES} -o $@ $< + ${ROBCMP} -bdep -a avr328p ${OPT} ${INCLUDES} -o $@ $< out/%.ll : %.rob ${DEPENDS} - ${ROBCMP} -a avr328p ${OPT} ${INCLUDES} $< > $@ + ${ROBCMP} -bdep -a avr328p ${OPT} ${INCLUDES} $< > $@ %.tt : %.rob ${DEPENDS} @-./runtest.sh $< $(patsubst %.rob,out/%,$<) -out/itoa : out/itoa.o ${SERIAL_DEPENDS} ${LINK_DEPENDS} -out/uart : out/uart.o ${SERIAL_DEPENDS} ${LINK_DEPENDS} out/% : out/%.o ${LINK_DEPENDS} ld.lld ${LD_FLAGS} $^ -o $@ test: ${ALL_TT} clean: - @rm -f ${ALL} ${ALL_LL} ${ALL_OO} ${SERIAL_DEPENDS} + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} diff --git a/test/avr328p/aux/avr5mcu.rob b/test/avr328p/aux/avr5mcu.rob deleted file mode 100644 index 8692f62..0000000 --- a/test/avr328p/aux/avr5mcu.rob +++ /dev/null @@ -1,11 +0,0 @@ - -type avr5mcu { - - int32 clock() { - return 16000000; - } - - void sleep() { - asm "sleep"; - } -} diff --git a/test/avr328p/aux/serial.rob b/test/avr328p/aux/serial.rob deleted file mode 100644 index d133034..0000000 --- a/test/avr328p/aux/serial.rob +++ /dev/null @@ -1,95 +0,0 @@ - -use avr5mcu; - -type UCSRA { - MPCM0 = false; - U2X0 = false; - UPE0 = false; - DOR0 = false; - FE0 = false; - UDRE0 = false; - TXC0 = false; - RXC0 = false; -} - -type UCSRB { - TXB80 = false; - RXB80 = false; - UCSZ02 = false; - TXEN0 = false; - RXEN0 = false; - UDRIE0 = false; - TXCIE0 = false; - RXCIE0 = false; -} - -type UCSRC { - UCPOL0 = false; - UCSZ0 = int2(0); - USBS0 = false; - UPM0 = int2(0); - UMSEL0 = int2(0); -} - -/* USART0 control status register A */ -register UCSRA UCSR0A at 0xc0; - -/* USART0 control status register B */ -register UCSRB UCSR0B at 0xc1; - -/* USART0 control status register C */ -register UCSRC UCSR0C at 0xc2; - -/* USART0 baud rate register, 12 bits*/ -register uint16 UBRR0 at 0xc4; - -/* USART0 byte to send/received */ -register uint8 UDR0 at 0xc6; - -type avr5_serial { - - void start(avr5mcu mcu, int32 baud) { - // use 2x - UCSR0A.U2X0 = false; - - multipl = 16; - if UCSR0A.U2X0 == true { - multipl = 8; - } - - div = int32(multipl) * baud; - velocity = (mcu.clock() / div) - 1; - - // set baudrate - UBRR0 = int16(velocity); - - // 8 bit - UCSR0B.UCSZ02 = false; - UCSR0C.UCSZ0 = 0x3; - - // no parity - UCSR0C.UPM0 = 0x0; - - // 1 stop bit - UCSR0C.USBS0 = false; - - // enable tx and rx - UCSR0B.RXEN0 = true; - UCSR0B.TXEN0 = true; - } - - void write(uint8 c) { - while UCSR0A.UDRE0 == false; - UDR0 = c; - } - - uint8 read() { - while UCSR0A.RXC0 == false; - return UDR0; - } - - bool has_data() { - return UCSR0A.RXC0; - } - -} diff --git a/test/avr328p/itoa.rob b/test/avr328p/itoa.rob index c316a9b..4ea607a 100644 --- a/test/avr328p/itoa.rob +++ b/test/avr328p/itoa.rob @@ -1,52 +1,6 @@ -use serial; - -chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - -void itoa(int16 value, int8 base, char[] result) { - if base < 2 or base > 16 { - result[0] = 0; - return; - } - - negative = false; - if value < 0 { - negative = true; - value = - value; - } - - i = 0; - if value == 0 { - result[i] = '0'; - i++; - } else { - while value != 0 { - temp = value; - value /= base; - result[i] = chars[temp - value * base]; - //result[i] = chars[value % base]; - //value /= base; - i++; - } - } - - if negative == true { - result[i] = '-'; - i++; - } - result[i] = 0; - - // reverse result - j = 0; - i--; - while j < i { - temp = result[j]; - result[j] = result[i]; - result[i] = temp; - j++; - i--; - } -} +use arch.avr.avr5mcu; +use convert.itoa; numbers = {-32123, -15678, -4364, -501, -25, 0, 25, 512, 4364, 15678, 32767}; @@ -90,7 +44,7 @@ bool check(uint8 id, char[][] expected, char[] result) { return ret; } -void print_result(avr5_serial s, char[] result) { +void print_result(databus s, char[] result) { i = 0; while result[i] != 0 { s.write(result[i]); @@ -100,9 +54,9 @@ void print_result(avr5_serial s, char[] result) { } int16 main() { - mcu = avr5mcu(); - serial = avr5_serial(); - serial.start(mcu, 9600); + mmcu = avr5mcu(); + serial = mmcu.uart0; + serial.setup(9600); result = {'\0':18}; ret = true; diff --git a/test/avr328p/robcmp-simavr-debug b/test/avr328p/robcmp-simavr-debug new file mode 120000 index 0000000..d508ef4 --- /dev/null +++ b/test/avr328p/robcmp-simavr-debug @@ -0,0 +1 @@ +../../platformio/toolchain-robcmp/bin/robcmp-simavr-debug \ No newline at end of file diff --git a/test/avr328p/runtest.sh b/test/avr328p/runtest.sh index daf5c6b..3bf0af9 100755 --- a/test/avr328p/runtest.sh +++ b/test/avr328p/runtest.sh @@ -8,7 +8,11 @@ NC="\033[0m" echo -n " $1 " make -s $2 if [ "$?" -eq 0 ]; then - timeout 10s ${CMD} &> /dev/null + if [ "$V" = "1" ]; then + ${CMD} + else + timeout 10s ${CMD} &> /dev/null + fi #./$2 &> /dev/null if [ "$?" -eq 0 ]; then echo -e \\r${GREEN}[PASS]\\t\\t${NC} diff --git a/test/avr328p/uart.rob b/test/avr328p/uart.rob index efadbad..782b596 100644 --- a/test/avr328p/uart.rob +++ b/test/avr328p/uart.rob @@ -1,11 +1,10 @@ -use serial; +use arch.avr.avr5mcu; int16 main() { - mcu = avr5mcu(); - - serial = avr5_serial(); - serial.start(mcu, 9600); + mmcu = avr5mcu(); + serial = mmcu.uart0; + serial.setup(9600); serial.write('A'); serial.write('B'); diff --git a/test/general/Makefile b/test/general/Makefile index d649cf1..0c396a2 100644 --- a/test/general/Makefile +++ b/test/general/Makefile @@ -28,12 +28,12 @@ clean: out/%.o : %.rob ${ROBCMP} Makefile @touch temp.spec && truncate -s 0 temp.spec @[ -f $(patsubst %.rob,%.spec,$<) ] && cp $(patsubst %.rob,%.spec,$<) temp.spec || true - ${ROBCMP} ${OPT} -s temp.spec -o $@ $< + ${ROBCMP} ${OPT} -I ../../lib -bdep -s temp.spec -o $@ $< out/%.ll : %.rob ${ROBCMP} Makefile @touch temp.spec && truncate -s 0 temp.spec @[ -f $(patsubst %.rob,%.spec,$<) ] && cp $(patsubst %.rob,%.spec,$<) temp.spec || true - ${ROBCMP} ${OPT} -s temp.spec $< > $@ + ${ROBCMP} ${OPT} -I ../../lib -bdep -s temp.spec $< > $@ %.tt : %.rob @-./runtest.sh $< $(patsubst %.rob,out/%,$<) @@ -42,9 +42,9 @@ out/%.ll : %.rob ${ROBCMP} Makefile ifeq ($(OS), Msys) ${LD} -e __main $< -o $@ else ifeq ($(OS), Darwin) - ${CC} $< -o $@ &> /dev/null + ${CC} -Wl,-dead_strip $< -o $@ else - ${CC} -no-pie $< -o $@ + ${CC} -Wl,--gc-sections -no-pie $< -o $@ endif test: ${ALL_TT} diff --git a/test/general/byref.rob b/test/general/byref.rob index 102ca86..4e6b72b 100644 --- a/test/general/byref.rob +++ b/test/general/byref.rob @@ -15,7 +15,7 @@ type main_t { ss = copy(v); } - ii = intf { + ii implements intf { void print(int8 v) { return; } diff --git a/test/general/dispatch.rob b/test/general/dispatch.rob new file mode 100644 index 0000000..65d675d --- /dev/null +++ b/test/general/dispatch.rob @@ -0,0 +1,41 @@ + +interface animal { + int8 sound(); +} + +type cat implements animal { + int8 sound() { + return 0; + } +} + +type dog implements animal { + int8 sound() { + return 1; + } +} + +type bird implements animal { + int8 sound() { + return 2; + } +} + +int8 produce_sound(animal a) { + return a.sound(); +} + +int8 main() { + c = cat(); + d = dog(); + b = bird(); + cs = produce_sound(c); + ds = produce_sound(d); + bs = produce_sound(b); + if cs != 0 or ds != 1 or bs != 2 { + return 1; + } else { + return 0; + } +} + diff --git a/test/general/intfinternal.rob b/test/general/intfinternal.rob index 595e29e..815c444 100644 --- a/test/general/intfinternal.rob +++ b/test/general/intfinternal.rob @@ -6,7 +6,7 @@ interface bus { type mcu { - spi = bus { + spi implements bus { speed = int32(0); lastb = 0; diff --git a/test/general/intfscope.rob b/test/general/intfscope.rob index 29abbd2..c01cf35 100644 --- a/test/general/intfscope.rob +++ b/test/general/intfscope.rob @@ -7,7 +7,7 @@ interface intf { type somevar { a = int16(0); - pa = intf { + pa implements intf { b = int16(0); int16 get() { return b; } void set(int16 s) { b = s; } diff --git a/test/general/itoa.rob b/test/general/itoa.rob index 1ce20ff..6a53422 100644 --- a/test/general/itoa.rob +++ b/test/general/itoa.rob @@ -1,49 +1,5 @@ -const chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - -void itoa(int16 value, int8 base, char[] result) { - if base < 2 or base > 16 { - result[0] = 0; - return; - } - - negative = value < 0; - //abs without branch - mask = value >> 15; - value = (value ^ mask) - mask; - - i = 0; - if value == 0 { - result[i] = '0'; - i++; - } else { - while value != 0 { - temp = value; - value /= base; - result[i] = chars[temp - value * base]; - //result[i] = chars[value % base]; - //value /= base; - i++; - } - if negative { - result[i] = '-'; - i++; - } - } - - result[i] = 0; - - // reverse result - j = 0; - i--; - while j < i { - temp = result[j]; - result[j] = result[i]; - result[i] = temp; - j++; - i--; - } -} +use convert.itoa; numbers = {-32123, -15678, -4364, -501, -25, 0, 25, 512, 4364, 15678, 32767}; @@ -106,4 +62,3 @@ int16 main() { return 1; } } - diff --git a/test/general/rand16.rob b/test/general/rand16.rob new file mode 100644 index 0000000..22d4a92 --- /dev/null +++ b/test/general/rand16.rob @@ -0,0 +1,17 @@ + +use math.random16; + +int16 main() { + result = 0; + i = 0u; + while i < 200 { + aux = random16ub(100); + if aux > 100 { + result = 1; + } + + i++; + } + return result; +} + diff --git a/test/general/simplesubtype.rob b/test/general/simplesubtype.rob index ab547de..036c0fe 100644 --- a/test/general/simplesubtype.rob +++ b/test/general/simplesubtype.rob @@ -4,7 +4,7 @@ interface a { } type b { - x = a { + x implements a { void print() { return; } From e2ad2af32815038ce3d6b76d75199e4c28553178 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Fri, 21 Jun 2024 19:32:52 -0300 Subject: [PATCH 059/117] Fixes and improves stm32 support. --- CMakeLists.txt | 10 +- lib/Makefile | 11 +- lib/arch/avr/avr5mcu.rob | 154 +++- lib/arch/avr/avr5regs.rob | 26 +- lib/arch/stm32/stm32f1.rob | 244 ++++++ lib/arch/stm32/stm32f1regs.rob | 440 +++++++++++ lib/avr328p.rob | 2 +- lib/avr5.ld | 31 +- lib/display/ssd1306.rob | 247 ++++++ lib/display/ssd1306spi.rob | 211 ----- lib/graphic/canvas8.rob | 8 +- lib/intfs/buffer8.rob | 1 + lib/intfs/databus.rob | 8 +- lib/intfs/display.rob | 1 + lib/intfs/mcu.rob | 6 +- lib/intfs/ports.rob | 18 +- lib/math/random16.rob | 1 - lib/math/random32.rob | 4 +- lib/stm32f1.ld | 49 +- lib/stm32f1.rob | 171 ++++ .../examples/avr328p-ssd1306/platformio.ini | 13 - .../examples/avr328p-ssd1306/src/main.rob | 78 -- .../examples/avr328p-ssd1306/src/main.spec | 1 - .../{avr328p-blink => blink}/.gitignore | 0 platformio/examples/blink/platformio.ini | 30 + platformio/examples/blink/specs/avr.spec | 5 + platformio/examples/blink/specs/stm32.spec | 5 + platformio/examples/blink/src/main.rob | 26 + .../avr328p-blink}/.gitignore | 0 .../{ => old}/avr328p-blink/platformio.ini | 0 .../{ => old}/avr328p-blink/src/main.rob | 0 .../{ => old}/avr328p-blink/src/wait.rob | 0 .../avr328p-ssd1306}/.gitignore | 0 .../{ => old}/avr328p-ssd1306/genll.sh | 0 .../old/avr328p-ssd1306/platformio.ini | 39 + .../old/avr328p-ssd1306/specs/avr-i2c.spec | 18 + .../old/avr328p-ssd1306/specs/avr-spi.spec | 18 + .../avr328p-ssd1306/specs/stm32f1-i2c.spec | 19 + .../examples/old/avr328p-ssd1306/src/main.rob | 113 +++ .../examples/old/stm32f1-blink/.gitignore | 5 + .../examples/old/stm32f1-blink/platformio.ini | 7 + .../old/stm32f1-blink/src/hardware.spec | 0 .../examples/old/stm32f1-blink/src/main.rob | 21 + platformio/examples/ssd1306/.gitignore | 5 + platformio/examples/ssd1306/elf_reader.py | 643 +++++++++++++++ platformio/examples/ssd1306/platformio.ini | 30 + platformio/examples/ssd1306/sections.txt | 31 + platformio/examples/ssd1306/specs/avr.spec | 4 + platformio/examples/ssd1306/specs/stm32.spec | 23 + platformio/examples/ssd1306/src/main.rob | 72 ++ platformio/examples/ssd1306/teste | Bin 0 -> 23192 bytes .../examples/stm32f1-blink/platformio.ini | 5 - .../examples/stm32f1-blink/src/main.rob | 53 -- .../examples/stm32f1-blink/src/newmain.rob | 106 --- platformio/examples/stm32f1-blink/src/two.rob | 7 - platformio/platform/boards/stm32f1.json | 12 +- platformio/platform/builder/main.py | 61 +- platformio/platform/platform.py | 32 +- platformio/toolchain-robcmp/Makefile | 12 +- platformio/toolchain-robcmp/stdlib | 1 + .../vscode-syntax/robcmpsyntax-0.0.1.vsix | Bin 3330 -> 3340 bytes src/2018arm/AccelStepper.cpp | 652 ---------------- src/2018arm/AccelStepper.h | 730 ------------------ src/2018arm/Makefile | 23 - src/2018arm/Servo.cpp | 323 -------- src/2018arm/Servo.h | 119 --- src/2018arm/ServoTimers.h | 59 -- src/2018arm/nodeh_ext.h | 67 -- src/2018arm/stepper_aux.cpp | 51 -- src/2018arm/stepper_aux.h | 19 - src/Array.cpp | 2 - src/ArrayElements.cpp | 5 +- src/BackLLVM.cpp | 59 +- src/BuildTypes.cpp | 5 +- src/BuildTypes.h | 43 +- src/ConstructorCall.cpp | 2 +- src/DebugInfo.cpp | 14 +- src/Dispatch.cpp | 1 - src/FlexDependencies.h | 3 +- src/FunctionAttributes.h | 29 + src/FunctionCall.cpp | 1 - src/FunctionDecl.cpp | 36 +- src/FunctionDecl.h | 29 +- src/FunctionImpl.cpp | 35 +- src/Header.h | 3 - src/HeaderGlobals.h | 4 +- src/Interface.cpp | 12 +- src/Language.l | 12 +- src/Language.y | 36 +- src/LanguageHeader.y | 4 + src/LanguageUse.y | 35 +- src/Load.cpp | 2 +- src/Matrix.cpp | 2 - src/MemCopy.cpp | 3 +- src/Pointer.cpp | 6 + src/Program.cpp | 95 +-- src/PropagateTypes.cpp | 63 +- src/Scalar.cpp | 32 +- src/Scalar.h | 6 +- src/Scanner.cpp | 45 +- src/Scanner.h | 2 +- src/Spec.l | 53 -- src/Spec.y | 128 --- src/UpdateArray.cpp | 1 + src/UserType.cpp | 64 +- src/Variable.cpp | 3 +- src/Variable.h | 5 + src/main.cpp | 30 +- test/avr328p/bitstruct-field-i5.rob | 18 + test/avr328p/bsscheck.rob | 9 + test/avr328p/datacheck.rob | 20 + test/avr328p/globaldata.rob | 12 + test/avr328p/uartdata.rob | 33 + test/debug/platformio.ini | 2 +- test/general/bind.spec | 2 +- test/general/function_attribs.rob | 10 + 116 files changed, 3068 insertions(+), 3129 deletions(-) create mode 100644 lib/arch/stm32/stm32f1.rob create mode 100644 lib/arch/stm32/stm32f1regs.rob create mode 100644 lib/display/ssd1306.rob delete mode 100644 lib/display/ssd1306spi.rob create mode 100644 lib/stm32f1.rob delete mode 100644 platformio/examples/avr328p-ssd1306/platformio.ini delete mode 100644 platformio/examples/avr328p-ssd1306/src/main.rob delete mode 100644 platformio/examples/avr328p-ssd1306/src/main.spec rename platformio/examples/{avr328p-blink => blink}/.gitignore (100%) create mode 100644 platformio/examples/blink/platformio.ini create mode 100644 platformio/examples/blink/specs/avr.spec create mode 100644 platformio/examples/blink/specs/stm32.spec create mode 100644 platformio/examples/blink/src/main.rob rename platformio/examples/{avr328p-ssd1306 => old/avr328p-blink}/.gitignore (100%) rename platformio/examples/{ => old}/avr328p-blink/platformio.ini (100%) rename platformio/examples/{ => old}/avr328p-blink/src/main.rob (100%) rename platformio/examples/{ => old}/avr328p-blink/src/wait.rob (100%) rename platformio/examples/{stm32f1-blink => old/avr328p-ssd1306}/.gitignore (100%) rename platformio/examples/{ => old}/avr328p-ssd1306/genll.sh (100%) create mode 100644 platformio/examples/old/avr328p-ssd1306/platformio.ini create mode 100644 platformio/examples/old/avr328p-ssd1306/specs/avr-i2c.spec create mode 100644 platformio/examples/old/avr328p-ssd1306/specs/avr-spi.spec create mode 100644 platformio/examples/old/avr328p-ssd1306/specs/stm32f1-i2c.spec create mode 100644 platformio/examples/old/avr328p-ssd1306/src/main.rob create mode 100644 platformio/examples/old/stm32f1-blink/.gitignore create mode 100644 platformio/examples/old/stm32f1-blink/platformio.ini create mode 100644 platformio/examples/old/stm32f1-blink/src/hardware.spec create mode 100644 platformio/examples/old/stm32f1-blink/src/main.rob create mode 100644 platformio/examples/ssd1306/.gitignore create mode 100755 platformio/examples/ssd1306/elf_reader.py create mode 100644 platformio/examples/ssd1306/platformio.ini create mode 100644 platformio/examples/ssd1306/sections.txt create mode 100644 platformio/examples/ssd1306/specs/avr.spec create mode 100644 platformio/examples/ssd1306/specs/stm32.spec create mode 100644 platformio/examples/ssd1306/src/main.rob create mode 100644 platformio/examples/ssd1306/teste delete mode 100644 platformio/examples/stm32f1-blink/platformio.ini delete mode 100644 platformio/examples/stm32f1-blink/src/main.rob delete mode 100644 platformio/examples/stm32f1-blink/src/newmain.rob delete mode 100644 platformio/examples/stm32f1-blink/src/two.rob create mode 120000 platformio/toolchain-robcmp/stdlib delete mode 100644 src/2018arm/AccelStepper.cpp delete mode 100644 src/2018arm/AccelStepper.h delete mode 100644 src/2018arm/Makefile delete mode 100644 src/2018arm/Servo.cpp delete mode 100644 src/2018arm/Servo.h delete mode 100644 src/2018arm/ServoTimers.h delete mode 100644 src/2018arm/nodeh_ext.h delete mode 100644 src/2018arm/stepper_aux.cpp delete mode 100644 src/2018arm/stepper_aux.h create mode 100644 src/FunctionAttributes.h delete mode 100644 src/Spec.l delete mode 100644 src/Spec.y create mode 100644 test/avr328p/bitstruct-field-i5.rob create mode 100644 test/avr328p/datacheck.rob create mode 100644 test/avr328p/globaldata.rob create mode 100644 test/avr328p/uartdata.rob create mode 100644 test/general/function_attribs.rob diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d6be1f..dc27b9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,6 @@ file(GLOB robcmp_SRC CONFIGURE_DEPENDS ) flex_target(lexer "${CMAKE_CURRENT_SOURCE_DIR}/src/Language.l" "${CMAKE_BINARY_DIR}/Language_l.cpp") -flex_target(lexer_spec "${CMAKE_CURRENT_SOURCE_DIR}/src/Spec.l" "${CMAKE_BINARY_DIR}/Spec_l.cpp") bison_target(scanner_main "${CMAKE_BINARY_DIR}/Language_gen.y" @@ -38,10 +37,6 @@ bison_target(scanner_use "${CMAKE_BINARY_DIR}/LanguageUse_gen.y" "${CMAKE_BINARY_DIR}/LanguageUse_gen.cpp" COMPILE_FLAGS "-Wall -Wno-deprecated") -bison_target(scanner_spec - "${CMAKE_CURRENT_SOURCE_DIR}/src/Spec.y" - "${CMAKE_BINARY_DIR}/Spec_y.cpp" - COMPILE_FLAGS "-Wall -Wno-deprecated") # Language_gen.y add_custom_command( @@ -59,13 +54,12 @@ add_custom_target(parsers DEPENDS ${CMAKE_BINARY_DIR}/Language_gen.y ${CMAKE_BINARY_DIR}/LanguageUse_gen.y) add_executable(robcmp - ${FLEX_lexer_OUTPUTS} ${FLEX_lexer_spec_OUTPUTS} - ${BISON_scanner_main_OUTPUTS} ${BISON_scanner_use_OUTPUTS} ${BISON_scanner_spec_OUTPUTS} + ${FLEX_lexer_OUTPUTS} + ${BISON_scanner_main_OUTPUTS} ${BISON_scanner_use_OUTPUTS} ${robcmp_SRC}) add_flex_bison_dependency(lexer scanner_main) add_flex_bison_dependency(lexer scanner_use) -add_flex_bison_dependency(lexer_spec scanner_spec) add_dependencies(robcmp parsers) llvm_map_components_to_libnames(llvm_libs support core irreader passes diff --git a/lib/Makefile b/lib/Makefile index 82da0c3..3ace01d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,10 +1,11 @@ -all: avr5.o +GEN=avr5.o -avr5.o: avr5.s - @#here we are interested in the fastest possible code, intead of size - avr-gcc -mmcu=avr5 -O3 -c avr5.S +all: ${GEN} +avr5.o: avr5.S + @#here we are interested in the fastest possible code, intead of size + avr-gcc -mmcu=avr5 -O3 -c $< clean: - rm -f avr5.o + rm -f ${GEN} diff --git a/lib/arch/avr/avr5mcu.rob b/lib/arch/avr/avr5mcu.rob index 643bca7..7f4b530 100644 --- a/lib/arch/avr/avr5mcu.rob +++ b/lib/arch/avr/avr5mcu.rob @@ -9,7 +9,7 @@ void __delay_us(); type avr5mcu implements mcu { - uint32 clock() { + uint32 clock() inline { return 16E6; } @@ -27,39 +27,39 @@ type avr5mcu implements mcu { */ b0 implements digitalport { - void mode(port_mode m) { ddrb.b0 = m; } - void set(bool v) { portb.b0 = v; } - bool get() { return portb.b0; } + void mode(port_mode m) inline { ddrb.b0 = m; } + void set(bool v) inline { portb.b0 = v; } + bool get() inline { return portb.b0; } } b1 implements digitalport { - void mode(port_mode m) { ddrb.b1 = m; } - void set(bool v) { portb.b1 = v; } - bool get() { return portb.b1; } + void mode(port_mode m) inline { ddrb.b1 = m; } + void set(bool v) inline { portb.b1 = v; } + bool get() inline { return portb.b1; } } b2 implements digitalport { - void mode(port_mode m) { ddrb.b2 = m; } - void set(bool v) { portb.b2 = v; } - bool get() { return portb.b2; } + void mode(port_mode m) inline { ddrb.b2 = m; } + void set(bool v) inline { portb.b2 = v; } + bool get() inline { return portb.b2; } } b3 implements digitalport { - void mode(port_mode m) { ddrb.b3 = m; } - void set(bool v) { portb.b3 = v; } - bool get() { return portb.b3; } + void mode(port_mode m) inline { ddrb.b3 = m; } + void set(bool v) inline { portb.b3 = v; } + bool get() inline { return portb.b3; } } b4 implements digitalport { - void mode(port_mode m) { ddrb.b4 = m; } - void set(bool v) { portb.b4 = v; } - bool get() { return portb.b4; } + void mode(port_mode m) inline { ddrb.b4 = m; } + void set(bool v) inline { portb.b4 = v; } + bool get() inline { return portb.b4; } } b5 implements digitalport { - void mode(port_mode m) { ddrb.b5 = m; } - void set(bool v) { portb.b5 = v; } - bool get() { return portb.b5; } + void mode(port_mode m) inline { ddrb.b5 = m; } + void set(bool v) inline { portb.b5 = v; } + bool get() inline { return portb.b5; } } void enable_led() { @@ -70,14 +70,14 @@ type avr5mcu implements mcu { b5.set(s); } - void wait_us(int16 us) { + void wait_us(uint16 us) { while us > 0 { __delay_us(); us--; } } - void wait_ms(int16 ms) { + void wait_ms(uint16 ms) { while ms > 0 { wait_us(1000); ms--; @@ -89,13 +89,13 @@ type avr5mcu implements mcu { b3 = MOSI b4 = MISO b5 = SCK */ - void setup(int32 speed) { + void setup(uint32 speed) { b3.mode(port_mode.output); b4.mode(port_mode.input); b5.mode(port_mode.output); SPCR.MSTR = true; // master - // ignoring speed for now. Set to fsck/4 = 4Mhz + //TODO: ignoring speed for now. Set to fsck/4 = 4Mhz SPSR.SPI2x = false; SPCR.SPR0 = false; SPCR.SPR1 = false; @@ -106,12 +106,10 @@ type avr5mcu implements mcu { void enable() { SPCR.SPE = true; - //SPCR.SPIE = true; } void disable() { SPCR.SPE = false; - //SPCR.SPIE = false; } void write(uint8 b) { @@ -119,23 +117,36 @@ type avr5mcu implements mcu { while !SPSR.SPIF; } + void write_array(int8[] data) { + i = 0u; + while i < data.size { + SPDR = uint8(data[i]); + while !SPSR.SPIF; + i++; + } + } + uint8 read() { - //FIXME + //TODO: Verify correctness while !SPSR.SPIF; return SPDR; } bool has_data() { - //FIXME + //TODO: Verify correctness return SPSR.SPIF; } - void start_transaction() { return; } + bool start_transaction(uint16 address) { return true; } void end_transaction() { return; } + + databus_protocol get_protocol() { + return databus_protocol.SPI; + } } uart0 implements databus { - void setup(int32 baud) { + void setup(uint32 baud) { // use 2x UCSR0A.U2X0 = false; @@ -175,7 +186,16 @@ type avr5mcu implements mcu { void write(uint8 b) { while UCSR0A.UDRE0 == false; - UDR0 = b; + UDR0 = b; + } + + void write_array(int8[] data) { + i = 0u; + while i < data.size { + while UCSR0A.UDRE0 == false; + UDR0 = uint8(data[i]); + i++; + } } uint8 read() { @@ -187,28 +207,78 @@ type avr5mcu implements mcu { return UCSR0A.RXC0; } - void start_transaction() { return; } + bool start_transaction(uint16 address) { return true; } void end_transaction() { return; } + + databus_protocol get_protocol() { + return databus_protocol.UART; + } } - /*i2c implements databus { - void setup(int32 speed) { + i2c implements databus { + enum STATUS {START_OK = 0x1, MT_SLA_ACK_OK = 0x3} + + void setup(uint32 speed) { + TWSR.TWS = 0; + TWSR.TWPS = 0; + TWBR = uint8(((clock() / speed) - 16) / 2); } - void enable() { + void enable() { return; } + + void disable() { return; } + + bool start_transaction(uint16 addr) { + // write START condition + TWCR = ETWCR.TWSTA | ETWCR.TWEN | ETWCR.TWINT; + while TWCR & ETWCR.TWINT == 0; + + if TWSR.TWS != STATUS.START_OK { + return false; + } + + // write SLA addr + TWDR = uint8(addr); + TWCR = ETWCR.TWEN | ETWCR.TWINT; + while TWCR & ETWCR.TWINT == 0; + + if TWSR.TWS != STATUS.MT_SLA_ACK_OK { + return false; + } + return true; } - - void disable() { + void end_transaction() { + // send STOP condition + TWCR = ETWCR.TWSTO | ETWCR.TWEN | ETWCR.TWINT; + } + + void write(uint8 b) { + TWDR = b; + TWCR = ETWCR.TWINT | ETWCR.TWEN; + while TWCR & ETWCR.TWINT == 0; + } + + void write_array(int8[] data) { + i = 0u; + while (i < data.size) { + TWDR = uint8(data[i]); + TWCR = ETWCR.TWEN | ETWCR.TWINT; + while TWCR & ETWCR.TWINT == 0; + // check if TWSR.TWS != 0x5 // 0x28 >> 3 + // data transmited and ack received + i++; + } } - void start_transaction() {} - void end_transaction() {} - void write(uint8 b) {} - uint8 read() {} + uint8 read() { return 0; } - bool has_data() {} - }*/ + bool has_data() { return false; } + + databus_protocol get_protocol() { + return databus_protocol.I2C; + } + } } diff --git a/lib/arch/avr/avr5regs.rob b/lib/arch/avr/avr5regs.rob index acb6c2e..a2546dd 100644 --- a/lib/arch/avr/avr5regs.rob +++ b/lib/arch/avr/avr5regs.rob @@ -122,30 +122,22 @@ register uint8 SPDR at 0x4e; /* - * I2C (TWI) PC5 = SCL, PC4 = SDA + * I2C (TWI) + * In atmega328p, PC5 = SCL, and PC4 = SDA. */ // TWI Bit Rate Register register uint8 TWBR at 0xB8; -type TWCR_t { - TWINT = false; // TWI interrupt - TWEA = false; // Enable ACK - TWSTA = false; // Start Condition - TWSTO = false; // Stop Condition - TWWC = false; // Write Colision - TWEN = false; // TWI Enable - _reserved = false; - TWIE = false; // TWI interrupt enable -} - // TWI Control Register -register TWCR_t TWCR at 0xBC; +// all fields of TWCR must be set at once, so we are not using a register type for it +enum ETWCR {TWIE = 1, TWEN = 4, TWWC = 8, TWSTO = 16, TWSTA = 32, TWEA = 64, TWINT = 128} +register uint8 TWCR at 0xBC; type TWSR_t { - TWS = uint5(0); - _reserved = false; TWPS = uint2(0); + _reserved = false; + TWS = uint5(0); } // TWI Status Register @@ -155,16 +147,16 @@ register TWSR_t TWSR at 0xB9; register uint8 TWDR at 0xBB; type TWAR_t { - TWA = uint7(0); TWGCE = false; + TWA = uint7(0); } // TWI Slave Address Register register TWAR_t TWAR at 0xBA; type TWAMR_t { - TWAM = uint7(0); _reserved = false; + TWAM = uint7(0); } //TWI Slave Address Mask Register diff --git a/lib/arch/stm32/stm32f1.rob b/lib/arch/stm32/stm32f1.rob new file mode 100644 index 0000000..1557257 --- /dev/null +++ b/lib/arch/stm32/stm32f1.rob @@ -0,0 +1,244 @@ + +use intfs.mcu; +use intfs.ports; +use intfs.databus; + +use stm32f1regs; + +type stm32f1 implements mcu { + + uint32 clock() inline { + // TODO: provide 25Mhz and 72Mhz selection + return 8E6; + } + + void set_interruptions(bool enabled) { + return; + } + + c13 implements digitalport { + void mode(port_mode m) { + APB2EN.iopc = true; + if (m == port_mode.input) { + GPIOC_CRH.mode13 = PIN_MODE.INPUT; + GPIOC_CRH.cnf13 = INPUT_MODE.PULLUPDOWN; + } else { + GPIOC_CRH.mode13 = PIN_MODE.OUTPUT50MHz; + GPIOC_CRH.cnf13 = OUTPUT_MODE.PUSHPULL; + } + } + void set(bool v) inline { GPIOC_ODR.odr13 = v; } + bool get() inline { return GPIOC_IDR.idr13; } + } + + b6 implements digitalport { + void mode_input(PIN_MODE mode, INPUT_MODE cnf) { + GPIOB_CRL.mode6 = mode; + GPIOB_CRL.cnf6 = cnf; + } + void mode_output(PIN_MODE mode, OUTPUT_MODE cnf) { + GPIOB_CRL.mode6 = mode; + GPIOB_CRL.cnf6 = cnf; + } + void mode(port_mode m) { + APB2EN.iopb = true; + if (m == port_mode.input) { + mode_input(PIN_MODE.INPUT, INPUT_MODE.PULLUPDOWN); + } else { + mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.PUSHPULL); + } + } + void set(bool v) inline { GPIOB_ODR.odr6 = v; } + bool get() inline { return GPIOB_IDR.idr6; } + } + + b7 implements digitalport { + void mode_input(PIN_MODE mode, INPUT_MODE cnf) { + GPIOB_CRL.mode7 = mode; + GPIOB_CRL.cnf7 = cnf; + } + void mode_output(PIN_MODE mode, OUTPUT_MODE cnf) { + GPIOB_CRL.mode7 = mode; + GPIOB_CRL.cnf7 = cnf; + } + void mode(port_mode m) { + APB2EN.iopb = true; + if (m == port_mode.input) { + mode_input(PIN_MODE.INPUT, INPUT_MODE.PULLUPDOWN); + } else { + mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.PUSHPULL); + } + } + void set(bool v) inline { GPIOB_ODR.odr7 = v; } + bool get() inline { return GPIOB_IDR.idr7; } + } + + void wait_us(uint16 us) { + ticks = clock()/1E6 * us; + start_tick = SYSTICK_VAL; + while start_tick - SYSTICK_VAL < ticks; + } + + void wait_ms(uint16 ms) { + while ms > 0 { + wait_us(1000); + ms--; + } + } + + spi implements databus { + /* setup hardware SPI at: + xx = MOSI + xx = MISO + xx = SCK */ + void setup(uint32 speed) { + return; + } + + void enable() { + return; + } + + void disable() { + return; + } + + void write(uint8 b) { + return; + } + + void write_array(int8[] data) { + return; + } + + uint8 read() { + return 0; + } + + bool has_data() { + return false; + } + + bool start_transaction(uint16 address) { return true; } + void end_transaction() { return; } + + databus_protocol get_protocol() { + return databus_protocol.SPI; + } + } + + uart0 implements databus { + void setup(uint32 baud) { + return; + } + + void enable() { + return; + } + + void disable() { + return; + } + + void write(uint8 b) { + return; + } + + void write_array(int8[] data) { + return; + } + + uint8 read() { + return 0; + } + + bool has_data() { + return false; + } + + bool start_transaction(uint16 address) { return true; } + void end_transaction() { return; } + + databus_protocol get_protocol() { + return databus_protocol.UART; + } + } + + i2c1 implements databus { + /* + * Supports I2C on pins PB6 and PB7 + */ + + void setup(uint32 speed) { + APB1EN.i2c1 = true; // enable I2C clock + AHBENR.sdio = true; // enable SDIO clock + APB2EN.afio = true; // enable alternate function I/O clock + APB2EN.iopb = true; // port b clock + + // set ports B6 and B7 as alternate function I2C + b6.mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.AOPENDRAIN); + b7.mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.AOPENDRAIN); + + // disable peripheral to configure + I2C1_CR1.pe = false; + + // asuming 8Mhz clock + // FIX: should compute based on mcu/peripheral clock + I2C1_CCR.fs = true; + I2C1_CCR.duty = true; + I2C1_CR2.freq = 0x8; + I2C1_CCR.ccr = 0x1; + I2C1_TRISE = 0x1e; + } + + void enable() { + I2C1_CR1.pe = true; + } + + void disable() { + APB1EN.i2c1 = false; + I2C1_CR1.pe = false; + } + + bool start_transaction(uint16 addr) { + // send start condition + I2C1_CR1.start = true; + while !I2C1_SR1.sb and !I2C1_SR2.msl and !I2C1_SR2.busy; // wait for start + + // send address + I2C1_DR = addr; + while !I2C1_SR1.addr; // wait addr send + + // clear ADDR condition + temp = I2C1_SR2.msl; + + return true; + } + + void end_transaction() { + I2C1_CR1.stop = true; + } + + void write(uint8 b) inline { + I2C1_DR = b; + while !I2C1_SR1.btf; + } + + void write_array(int8[] data) { + i = 0u; + while (i < data.size) { + I2C1_DR = uint8(data[i]); + while !I2C1_SR1.btf; + i++; + } + } + + uint8 read() { return 0; } + + bool has_data() { return false; } + + databus_protocol get_protocol() { + return databus_protocol.I2C; + } + } +} diff --git a/lib/arch/stm32/stm32f1regs.rob b/lib/arch/stm32/stm32f1regs.rob new file mode 100644 index 0000000..8d9928b --- /dev/null +++ b/lib/arch/stm32/stm32f1regs.rob @@ -0,0 +1,440 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* + * Global Registers + */ + +type SYSTICK_CTRL_t { + enable = false; + tickint = false; + clksource = false; + _res1 = uint5(0); + _res2 = uint8(0); + countflag = uint16(0); +} + +const SCS_BASE = 0xE000E000; + +//register SYSTICK_t SYSTICK at 0xE000E010; +register SYSTICK_CTRL_t SYSTICK_CTRL at 0xE000E010; +register uint32 SYSTICK_LOAD at 0xE000E014; +register uint32 SYSTICK_VAL at 0xE000E018; +register uint32 SYSTICK_CALIB at 0xE000E01C; + + +type AHBENR_t { + dma1 = false; // DMA1 clock enable + dma2 = false; // DMA2 clock enable + sram = false; // SRAM interface clock enable + _res1 = false; + flitf = false; // FLITF clock enable + _res2 = false; + crc = false; // CRC clock enable + _res3 = false; + fsmc = false; // FSMC clock enable + _res4 = false; + sdio = false; // SDIO clock enable + _res5 = uint5(0); + _res6 = uint16(0); +} + +type APB2EN_t { + afio = false; // Alternate function I/O clock enable + _res1 = false; + iopa = false; // I/O port A clock enable + iopb = false; // I/O port B clock enable + iopc = false; // I/O port C clock enable + iopd = false; // I/O port D clock enable + iope = false; // I/O port E clock enable + iopf = false; // I/O port F clock enable + iopg = false; // I/O port G clock enable + adc1 = false; // ADC1 interface clock enable + adc2 = false; // ADC2 interface clock enable + tim1 = false; // TIM1 Timer clock enable + spi1 = false; // SPI1 clock enable + tim8 = false; // TIM8 Timer clock enable + usart1 = false; // USART1 clock enable + adc3 = false; // ADC3 interface clock enable + _res2 = uint16(0); +} + +type APB1EN_t { + tim2 = false; // Timer 2 clock enable + tim3 = false; // Timer 3 clock enable + tim4 = false; // Timer 4 clock enable + tim5 = false; // Timer 5 clock enable + tim6 = false; // Timer 6 clock enable + tim7 = false; // Timer 7 clock enable + _res1 = uint5(0); + wwdg = false; // Window watchdog clock enable + _res2 = uint2(0); + spi2 = false; // SPI2 clock enable + spi3 = false; // SPI3 clock enable + _res3 = false; + usart2 = false; // USART 2 clock enable + usart3 = false; // USART 3 clock enable + usart4 = false; // USART 4 clock enable + usart5 = false; // USART 5 clock enable + i2c1 = false; // I2C 1 clock enable + i2c2 = false; // I2C 2 clock enable + usb = false; // USB clock enable + _res4 = false; + can = false; // CAN clock enable + _res5 = false; + bkp = false; // Backup interface clock enable + pwr = false; // Power interface clock enable + dac = false; // DAC interface clock enable + _res6 = uint2(0); +} + +// AHB peripheral clock enable register +register AHBENR_t AHBENR at 0x40021014; +// APB1 peripheral clock enable register +register APB1EN_t APB1EN at 0x4002101C; +// APB2 peripheral clock enable register +register APB2EN_t APB2EN at 0x40021018; + + +// APB1 peripheral reset register +type APB1RSTR_t { + tim2rst = false; + tim3rst = false; + tim4rst = false; + tim5rst = false; + tim6rst = false; + tim7rst = false; + _res1 = uint5(0); + wwdgrst = false; + _res2 = uint2(0); + spi2rst = false; + spi3rst = false; + _res3 = false; + usart2rst = false; + usart3rst = false; + uart4rst = false; + uart5rst = false; + i2c1rst = false; + i2c2rst = false; + usbrst = false; + _res4 = false; + canrst = false; + _res5 = false; + bkprst = false; + pwrrst = false; + dacrst = false; + _res6 = uint2(0); +} +register APB1RSTR_t APB1RSTR at 0x40021010; + +/*type GPIO_t { + uint32_t CRL; // GPIO port configuration register low, Address offset: 0x00 + uint32_t CRH; // GPIO port configuration register high, Address offset: 0x04 + uint32_t IDR; // GPIO port input data register, Address offset: 0x08 + uint32_t ODR; // GPIO port output data register, Address offset: 0x0C + uint32_t BSRR; // GPIO port bit set/reset register, Address offset: 0x10 + uint32_t BRR; // GPIO port bit reset register, Address offset: 0x14 + uint32_t LCKR; // GPIO port configuration lock register, Address offset: 0x18 +}*/ + +type RCC_t { + cr = uint32(0); // RCC clock control register, Address offset: 0x00 + cfgr = uint32(0); // RCC clock configuration register, Address offset: 0x04 + cir = uint32(0); // RCC clock interrupt register, Address offset: 0x08 + apb2rstr = uint32(0); // RCC APB2 peripheral reset register, Address offset: 0x0C + apb1rstr = uint32(0); // RCC APB1 peripheral reset register, Address offset: 0x10 + ahbenr = uint32(0); // RCC AHB peripheral clock enable register, Address offset: 0x14 + apb2enr = uint32(0); // RCC APB2 peripheral clock enable register, Address offset: 0x18 + apb1enr = uint32(0); // RCC APB1 peripheral clock enable register, Address offset: 0x1C + bdcr = uint32(0); // RCC backup domain control register, Address offset: 0x20 + csr = uint32(0); // RCC control/status register, Address offset: 0x24 + ahbrstr = uint32(0); // RCC AHB peripheral clock reset register, Address offset: 0x28 + cfgr2 = uint32(0); // RCC clock configuration register2, Address offset: 0x2C +} + +type RCC_CR_t { + hsi_on = false; + hsi_rdy = false; + _res1 = false; + hsi_trim = uint5(0); + hsi_call = uint8(0); + hse_on = false; + hse_rdy = false; + hse_byp = false; + css_on = false; + _res2 = uint4(0); + pll_on = false; + pll_rdy = false; + _res3 = uint6(0); +} + +type RCC_CFGR_t { + sw = uint2(0); // System clock switch + sws = uint2(0); + hpre = uint4(0); + ppre1 = uint3(0); + ppre2 = uint3(0); + adc_pre = uint2(0); + pll_src = false; + pll_xtpre = false; + pll_mul = uint4(0); + usb_pre = false; + _res1 = false; + mco = uint3(0); + _res2 = uint5(0); +} + +// +register RCC_t RCC at 0x40021000; +// Clock control register +register RCC_CR_t RCC_CR at 0x40021000; +// Clock configuration register +register RCC_CFGR_t RCC_CFGR at 0x40021004; + + +type FLASH_t { + acr = uint32(0); + keyr = uint32(0); + optkeyr = uint32(0); + sr = uint32(0); + cr = uint32(0); + ar = uint32(0); + _res = uint32(0); + obr = uint32(0); + wrpr = uint32(0); +} + +register FLASH_t FLASH at 0x40022000; + +/* + * PORT registers + */ + +// PORT x Control Register Low (x=A..G) +type GPIOx_CRL_t { + mode0 = uint2(0); + cnf0 = uint2(0); + mode1 = uint2(0); + cnf1 = uint2(0); + mode2 = uint2(0); + cnf2 = uint2(0); + mode3 = uint2(0); + cnf3 = uint2(0); + mode4 = uint2(0); + cnf4 = uint2(0); + mode5 = uint2(0); + cnf5 = uint2(0); + mode6 = uint2(0); + cnf6 = uint2(0); + mode7 = uint2(0); + cnf7 = uint2(0); +} + +// PORT x Control Register High (x=A..G) +type GPIOx_CRH_t { + mode8 = uint2(0); + cnf8 = uint2(0); + mode9 = uint2(0); + cnf9 = uint2(0); + mode10 = uint2(0); + cnf10 = uint2(0); + mode11 = uint2(0); + cnf11 = uint2(0); + mode12 = uint2(0); + cnf12 = uint2(0); + mode13 = uint2(0); + cnf13 = uint2(0); + mode14 = uint2(0); + cnf14 = uint2(0); + mode15 = uint2(0); + cnf15 = uint2(0); +} + +// Port x output data register (x=A..G) +type GPIOx_ODR_t { + odr0 = false; + odr1 = false; + odr2 = false; + odr3 = false; + odr4 = false; + odr5 = false; + odr6 = false; + odr7 = false; + odr8 = false; + odr9 = false; + odr10 = false; + odr11 = false; + odr12 = false; + odr13 = false; + odr14 = false; + odr15 = false; + _res = uint16(0); +} + +// Port x input data register (x=A..G) +type GPIOx_IDR_t { + idr0 = false; + idr1 = false; + idr2 = false; + idr3 = false; + idr4 = false; + idr5 = false; + idr6 = false; + idr7 = false; + idr8 = false; + idr9 = false; + idr10 = false; + idr11 = false; + idr12 = false; + idr13 = false; + idr14 = false; + idr15 = false; + _res = uint16(0); +} + + +// GPIO PORT A base address +const GPIO_PORTA_BASE = 0x40010800; +// PORT A Control Register Low +register GPIOx_CRL_t GPIOA_CRL at 0x40010800; +// PORT A Control Register High +register GPIOx_CRH_t GPIOA_CRH at 0x40010804; +// PORT A Input Data Register +register GPIOx_IDR_t GPIOA_IDR at 0x40010808; +// PORT A Output Data Register +register GPIOx_ODR_t GPIOA_ODR at 0x4001080C; + + +// GPIO PORT B base address +const GPIO_PORTB_BASE = 0x40010C00; +// PORT B Control Register Low +register GPIOx_CRL_t GPIOB_CRL at 0x40010C00; +// PORT B Control Register High +register GPIOx_CRH_t GPIOB_CRH at 0x40010C04; +// PORT B Input Data Register +register GPIOx_IDR_t GPIOB_IDR at 0x40010C08; +// PORT B Output Data Register +register GPIOx_ODR_t GPIOB_ODR at 0x40010C0C; + + +// GPIO PORT C base address +const GPIO_PORTC_BASE = 0x40011000; +// PORT C Control Register Low +register GPIOx_CRL_t GPIOC_CRL at 0x40011000; +// PORT C Control Register High +register GPIOx_CRH_t GPIOC_CRH at 0x40011004; +// PORT C Input Data Register +register GPIOx_IDR_t GPIOC_IDR at 0x40011008; +// PORT C Output Data Register +register GPIOx_ODR_t GPIOC_ODR at 0x4001100C; + + +enum PIN_MODE {INPUT = 0x0, OUTPUT10MHz = 0x1, OUTPUT2MHz = 0x2, OUTPUT50MHz = 0x3 } +enum INPUT_MODE {ANALOG = 0x0, FLOATING = 0x1, PULLUPDOWN = 0x2 } +enum OUTPUT_MODE {PUSHPULL = 0x0, OPENDRAIN = 0x1, APUSH_PULL = 0x2, AOPENDRAIN = 0x3 } + + +/* + * I2C Registers + */ + +type I2C_CR1_t { + pe = false; // peripheral enable + smbus = false; // true = SMBus mode = true, false = I2C + _res1 = false; + smbtype = false; // false = SMBus device, SMBus Host + enarp = false; // ARP enable + enpec = false; // PEC enable + engc = false; // General call enable + nostretch = false; // Clock stretching disable (0=enabled) + start = false; // Start generation + stop = false; // Stop generation + ack = false; // Acknowledge enable + pos = false; // Acknowledge/PEC Position (for data reception) + pec = false; // Packet error checking + alert = false; // SMBus alert + _res2 = false; + swrst = false; // Software reset +} + +type I2C_CR2_t { + freq = uint6(0); // Peripheral clock frequency (in Mhz, from 2 to 36) + _res1 = uint2(0); + iterren = false; // Error interrupt enable + itevten = false; // Event interrupt enable + itbufen = false; // Buffer interrupt enable + dmaen = false; // DMA requests enable + last = false; // DMA last transfer + _res2 = uint3(0); +} + +type I2C_SR1_t { + sb = false; // Start bit (Master mode) + addr = false; // Address sent (mastermode) / matched (slave mode) + btf = false; // Byte transfer finished + add10 = false; // 10-bit header sent (Master mode) + stopf = false; // Stop detection (slavemode) + _res1 = false; + rxne = false; // Data register not empty (receivers) + txe = false; // Data register empty (transmitters) + berr = false; // Bus error + arlo = false; // Arbitration lost (master mode) + af = false; // Acknowledge failure + ovr = false; // Overrun/Underrun + pecerr = false; // PEC Error in reception + _res2 = false; + timeout = false; // Timeout or Tlow error + smbalert = false; // SMBus alert +} + +type I2C_SR2_t { + msl = false; // Master/slave + busy = false; // Bus busy + tra = false; // Transmitter/receiver false=data bytes received, true=data bytes transmited + _res = false; + gencall = false; // General call address (Slave mode) + smbdefault = false; // SMBus device default address (Slave mode) + smbhost = false; // SMBus host header (Slave mode) + dualf = false; // Dual flag (Slave mode) + pec = uint8(0); // Packet error checking register +} + +type I2C_CCR_t { + ccr = uint12(0); // Clock control register in Fast/Standard mode (Master mode) + _res = uint2(0); + duty = false; // Fast mode duty cycle + fs = false; // I2C master mode selection false=Standard, true=Fast +} + + +// I2C 1 Control 1 Register +register I2C_CR1_t I2C1_CR1 at 0x40005400; +// I2C 1 Control 2 Register +register I2C_CR2_t I2C1_CR2 at 0x40005404; +// I2C 1 Data Register (8 bits) +register uint16 I2C1_DR at 0x40005410; +// I2C 1 Status 1 Register +register I2C_SR1_t I2C1_SR1 at 0x40005414; +// I2C 1 Status 2 Register +register I2C_SR2_t I2C1_SR2 at 0x40005418; +// I2C 1 Clock control register +register I2C_CCR_t I2C1_CCR at 0x4000541C; +// I2C 1 T RISE register +register uint16 I2C1_TRISE at 0x40005420; + +// I2C 2 Control 1 Register +register I2C_CR1_t I2C2_CR1 at 0x40005800; +// I2C 2 Control 2 Register +register I2C_CR2_t I2C2_CR2 at 0x40005804; +// I2C 2 Data Register (8 bits) +register uint16 I2C2_DR at 0x40005810; +// I2C 2 Status 1 Register +register I2C_SR1_t I2C2_SR1 at 0x40005814; +// I2C 2 Status 2 Register +register I2C_SR2_t I2C2_SR2 at 0x40005818; +// I2C 2 Clock control register +register I2C_CCR_t I2C2_CCR at 0x4000581C; +// I2C 2 T RISE register +register uint16 I2C2_TRISE at 0x40005820; diff --git a/lib/avr328p.rob b/lib/avr328p.rob index f393772..6f8e8d1 100644 --- a/lib/avr328p.rob +++ b/lib/avr328p.rob @@ -16,7 +16,7 @@ asm "nop"; } - void __vectors() { + void __vectors() section __isr { /* FIXME: provide proper interrupt functions instead of __vectors * after implementing "weak" attribute for functions */ diff --git a/lib/avr5.ld b/lib/avr5.ld index 951550a..71018e2 100644 --- a/lib/avr5.ld +++ b/lib/avr5.ld @@ -8,50 +8,53 @@ OUTPUT_ARCH(avr:5) SECTIONS { .text : { - _start__vectors = .; - KEEP(*(.vectors)) + KEEP(*(__isr)) . = ALIGN(2); - _end_vectors = .; - _stext = .; + __text_start = .; *(.progmem*) . = ALIGN(2); *(.text) . = ALIGN(2); *(.text.*) . = ALIGN(2); - _etext = . ; + __text_end = . ; } > text .data : { - PROVIDE (__data_start = .) ; + __data_start = .; *(.data) *(.data*) + . = ALIGN(16); *(.rodata) /* We need to include .rodata here if gcc is used */ *(.rodata*) /* with -fdata-sections. */ . = ALIGN(2); - PROVIDE (__data_end = .) ; + __data_end = .; } > data AT> text .bss ADDR(.data) + SIZEOF(.data) : AT (ADDR (.bss)) { - PROVIDE (__bss_start = .) ; + __bss_start = .; *(.bss) + . = ALIGN(2); + KEEP(*(.bss)) *(.bss*) + . = ALIGN(2); + KEEP(*(.bss*)) *(COMMON) - PROVIDE (__bss_end = .) ; + . = ALIGN(2); + KEEP(*(COMMON)) + __bss_end = .; } > data __data_load_start = LOADADDR(.data); - __data_load_end = __data_load_start + SIZEOF(.data); /* will robcmp emits .noinit data? i.e., global vars uninitialized. this also provides __heap_start, for when we implement malloc. */ .noinit ADDR(.bss) + SIZEOF(.bss) : AT (ADDR (.noinit)) { - PROVIDE (__noinit_start = .) ; + __noinit_start = .; *(.noinit*) - PROVIDE (__noinit_end = .) ; - _end = . ; - PROVIDE (__heap_start = .) ; + __noinit_end = .; + __heap_start = .; } > data /* Global data not cleared after reset. */ diff --git a/lib/display/ssd1306.rob b/lib/display/ssd1306.rob new file mode 100644 index 0000000..7af4925 --- /dev/null +++ b/lib/display/ssd1306.rob @@ -0,0 +1,247 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +use intfs.mcu; +use intfs.ports; +use intfs.databus; +use intfs.buffer8; +use intfs.display; + +type ssd1306 implements display { + mmcu = mcu(); + + // ports used by the SPI display + datacmd = digitalport(); + reset = digitalport(); + select = digitalport(); + + // SPI or I2C bus + dbus = databus(); + + // display address for I2C + address = 0u; + + framebuffer implements buffer8 { + buff = {{0u:128}:8}; + + uint16 height() inline { return buff.rows; } + uint16 width() inline { return buff.cols; } + + void clear() { + row = 0u; + while row < buff.rows { + col = 0u; + while col < buff.cols { + buff[row][col] = 0; + col++; + } + row++; + } + } + + uint8 get(uint16 row, uint16 col) inline { + return buff[row][col]; + } + + void set(uint16 row, uint16 col, uint8 v) inline { + buff[row][col] = v; + } + } + + enum powerstate { + SLEEP = 0xAE, + ON = 0xAF + } + + enum i2c_control { + CMD_STREAM = 0x0, + DATA_STREAM = 0x40 + } + + enum commands { + SET_DISP_START_LINE = 0x40, + SET_SEG_REMAP_0 = 0xA0, + SET_SEG_REMAP_127 = 0xA1, + SET_MULTIPLEX_RATIO = 0xA8, + SET_COM_SCAN_NORMAL = 0xC0, + SET_COM_SCAN_INVERTED = 0xC8, + SET_VERTICAL_OFFSET = 0xD3, + SET_WIRING_SCHEME = 0xDA, + SET_DISP_CLOCK = 0xD5, + SET_PRECHARGE_PERIOD = 0xD9, + SET_VCOM_DESELECT_LEVEL = 0xDB, + SET_CONTRAST = 0x81, + RESUME_TO_RAM_CONTENT = 0xA4, + DISPLAY_MODE_NORMAL = 0xA6, + DISPLAY_MODE_INVERTED = 0xA7, + MEM_ADDRESSING = 0x20, + SET_COLUMN_ADDRESS = 0x21, + CHARGE_PUMP_REGULATOR = 0x8D, + CHARGE_PUMP_ON = 0x14, + SET_PAGE_ADDR = 0x22, + SET_COL_LO_NIBBLE = 0x00, + SET_COL_HI_NIBBLE = 0x10, + DEACTIVATE_SCROLL = 0x2E, + NOP = 0xE3 + } + + uint16 rows() { + return framebuffer.height()*8; + } + + uint16 columns() { + return framebuffer.width(); + } + + void set_address(uint8 a) { + address = a; + } + + void init_display() { + datacmd.mode(port_mode.output); + reset.mode(port_mode.output); + select.mode(port_mode.output); + + reset_display(); + + init_commands = { + powerstate.SLEEP, + commands.SET_DISP_CLOCK, 0x80, + commands.SET_MULTIPLEX_RATIO, 0x3F, + commands.SET_VERTICAL_OFFSET, 0x00, + commands.SET_DISP_START_LINE, + commands.CHARGE_PUMP_REGULATOR, + commands.CHARGE_PUMP_ON, + commands.MEM_ADDRESSING, 0x00, // Horizontal memory addressing mode + commands.SET_SEG_REMAP_0, + commands.SET_COM_SCAN_INVERTED, + commands.SET_WIRING_SCHEME, 0x12, + commands.SET_CONTRAST, 0x8F, + commands.SET_PRECHARGE_PERIOD, 0xF1, + commands.SET_VCOM_DESELECT_LEVEL, 0x40, + commands.RESUME_TO_RAM_CONTENT, + commands.DISPLAY_MODE_NORMAL, + commands.DEACTIVATE_SCROLL, + powerstate.ON + }; + + write_commands(init_commands); + } + + void set_orientation(displayorientation o) { + cmds = {0:2}; + + if (o == displayorientation.NORMAL or + o == displayorientation.NORMAL_MIRRORED) { + cmds[0] = commands.SET_SEG_REMAP_0; + } else { + cmds[0] = commands.SET_SEG_REMAP_127; + } + + if (o == displayorientation.NORMAL_MIRRORED or + o == displayorientation.UPSIDE_DOWN) { + cmds[1] = commands.SET_COM_SCAN_INVERTED; + } else { + cmds[1] = commands.SET_COM_SCAN_NORMAL; + } + + write_commands(cmds); + } + + void set_display_mode(bool inverted) { + cmds = {0}; + if inverted { + cmds[0] = commands.DISPLAY_MODE_INVERTED; + } else { + cmds[0] = commands.DISPLAY_MODE_NORMAL; + } + write_commands(cmds); + } + + void set_contrast(uint8 c) { + cmds = {commands.SET_CONTRAST, int8(c)}; + write_commands(cmds); + } + + void reset_display() { + reset.set(true); + mmcu.wait_ms(10); + reset.set(false); + mmcu.wait_ms(10); + reset.set(true); + } + + void write_commands(int8[] cmds) { + datacmd.set(false); + select.set(false); + + dbus.start_transaction(address); + if (dbus.get_protocol() == databus_protocol.I2C) { + dbus.write(i2c_control.CMD_STREAM); + } + + dbus.write_array(cmds); + + dbus.end_transaction(); + select.set(true); + } + + void reset_cursor() { + cmds = { + // set page update range + commands.SET_PAGE_ADDR, 0x0, 0x7, + // set column update range + commands.SET_COLUMN_ADDRESS, 0x0, 127 + }; + write_commands(cmds); + } + + void clear() { + reset_cursor(); + + datacmd.set(true); + select.set(false); + zero_data = {0:128}; + + dbus.start_transaction(address); + if (dbus.get_protocol() == databus_protocol.I2C) { + dbus.write(i2c_control.DATA_STREAM); + } + + i = 0u; + while i < framebuffer.height() { + dbus.write_array(zero_data); + i++; + } + + dbus.end_transaction(); + select.set(true); + } + + void update_frame() { + reset_cursor(); + + datacmd.set(true); + select.set(false); + dbus.start_transaction(address); + if (dbus.get_protocol() == databus_protocol.I2C) { + dbus.write(i2c_control.DATA_STREAM); + } + + row = 0u; + while row < framebuffer.height() { + col = 0u; + while col < framebuffer.width() { + v = framebuffer.get(row, col); + dbus.write(v); + col++; + } + row++; + } + + dbus.end_transaction(); + select.set(true); + } +} diff --git a/lib/display/ssd1306spi.rob b/lib/display/ssd1306spi.rob deleted file mode 100644 index 2609f99..0000000 --- a/lib/display/ssd1306spi.rob +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Part of the Robotics Language Standard Library, under the - * Apache License v2.0. - */ - -use intfs.mcu; -use intfs.ports; -use intfs.databus; -use intfs.buffer8; -use intfs.display; - -type ssd1306spi implements display { - mmcu = mcu(); - datacmd = digitalport(); - reset = digitalport(); - select = digitalport(); - spi = databus(); - - framebuffer implements buffer8 { - buff = {{0u:128}:8}; - - uint16 height() { return buff.rows; } - uint16 width() { return buff.cols; } - - uint8 get(uint16 row, uint16 col) { - return buff[row][col]; - } - - void set(uint16 row, uint16 col, uint8 v) { - buff[row][col] = v; - } - } - - enum powerstate { - SLEEP = 0xAE, - ON = 0xAF - } - - enum commands { - SET_DISP_START_LINE = 0x40, - SET_SEG_REMAP_0 = 0xA0, - SET_SEG_REMAP_127 = 0xA1, - SET_MULTIPLEX_RATIO = 0xA8, - SET_COM_SCAN_NORMAL = 0xC0, - SET_COM_SCAN_INVERTED = 0xC8, - SET_VERTICAL_OFFSET = 0xD3, - SET_WIRING_SCHEME = 0xDA, - SET_DISP_CLOCK = 0xD5, - SET_PRECHARGE_PERIOD = 0xD9, - SET_VCOM_DESELECT_LEVEL = 0xDB, - SET_CONTRAST = 0x81, - RESUME_TO_RAM_CONTENT = 0xA4, - DISPLAY_MODE_NORMAL = 0xA6, - DISPLAY_MODE_INVERTED = 0xA7, - MEM_ADDRESSING = 0x20, - SET_COLUMN_ADDRESS = 0x21, - CHARGE_PUMP_REGULATOR = 0x8D, - CHARGE_PUMP_ON = 0x14, - SET_PAGE_ADDR = 0x22, - SET_COL_LO_NIBBLE = 0x00, - SET_COL_HI_NIBBLE = 0x10, - NOP = 0xE3 - } - - uint16 rows() { - return framebuffer.height()*8; - } - - uint16 columns() { - return framebuffer.width(); - } - - void init_display() { - datacmd.mode(port_mode.output); - reset.mode(port_mode.output); - select.mode(port_mode.output); - - reset_display(); - write_command(powerstate.SLEEP); - - write_command(commands.SET_DISP_CLOCK); - write_command(0x80); - - write_command(commands.SET_MULTIPLEX_RATIO); - write_command(0x3F); - - write_command(commands.SET_VERTICAL_OFFSET); - write_command(0x00); - - write_command(commands.SET_DISP_START_LINE); - - write_command(commands.CHARGE_PUMP_REGULATOR); - write_command(commands.CHARGE_PUMP_ON); - - // Horizontal memory addressing mode - write_command(commands.MEM_ADDRESSING); - write_command(0x00); - - write_command(commands.SET_WIRING_SCHEME); - write_command(0x12); - - set_contrast(0x7F); - - write_command(commands.SET_PRECHARGE_PERIOD); - write_command(0xF1); - - write_command(commands.SET_VCOM_DESELECT_LEVEL); - write_command(0x40); - - write_command(commands.RESUME_TO_RAM_CONTENT); - write_command(commands.DISPLAY_MODE_NORMAL); - - set_orientation(displayorientation.NORMAL); - - write_command(powerstate.ON); - } - - void set_orientation(displayorientation o) { - if (o == displayorientation.NORMAL or - o == displayorientation.NORMAL_MIRRORED) { - write_command(commands.SET_SEG_REMAP_0); - } else { - write_command(commands.SET_SEG_REMAP_127); - } - - if (o == displayorientation.NORMAL_MIRRORED or - o == displayorientation.UPSIDE_DOWN) { - write_command(commands.SET_COM_SCAN_INVERTED); - } else { - write_command(commands.SET_COM_SCAN_NORMAL); - } - } - - void set_display_mode(bool inverted) { - if inverted { - write_command(commands.DISPLAY_MODE_INVERTED); - } else { - write_command(commands.DISPLAY_MODE_NORMAL); - } - } - - void set_contrast(uint8 c) { - write_command(commands.SET_CONTRAST); - write_command(c); - } - - void reset_display() { - reset.set(true); - mmcu.wait_ms(2); - reset.set(false); - mmcu.wait_ms(10); - reset.set(true); - } - - void write_command(uint8 c) { - datacmd.set(false); - select.set(false); - spi.write(c); - select.set(true); - } - - void write_data(uint8 d) { - datacmd.set(true); - select.set(false); - spi.write(d); - select.set(true); - } - - void reset_cursor() { - // set page update range - write_command(commands.SET_PAGE_ADDR); - write_command(0x0); - write_command(0x7); - // set column update range - write_command(commands.SET_COLUMN_ADDRESS); - write_command(0); - write_command(127); - } - - /*void write_at(uint8 x, uint8 y) { - write_command(commands.SET_COLUMN_ADDRESS); - write_command(commands.SET_PAGE_START_ADDR); - }*/ - - void clear() { - reset_cursor(); - i = 0u; - while i < framebuffer.height() { - j = 0u; - while j < framebuffer.width() { - write_data(0); - j++; - } - i++; - } - } - - void update_frame() { - reset_cursor(); - row = 0u; - while row < framebuffer.height() { - col = 0u; - while col < framebuffer.width() { - v = framebuffer.get(row, col); - write_data(v); - col++; - } - row++; - } - } -} diff --git a/lib/graphic/canvas8.rob b/lib/graphic/canvas8.rob index c6d5f00..fc777f1 100644 --- a/lib/graphic/canvas8.rob +++ b/lib/graphic/canvas8.rob @@ -8,14 +8,18 @@ use intfs.buffer8; type canvas8 { buffer = buffer8(); - uint16 width() { + uint16 width() inline { return buffer.width(); } - uint16 height() { + uint16 height() inline { return buffer.height()*8; } + void clear() inline { + buffer.clear(); + } + void set_pixel(uint16 row, uint16 col) { rowb = row/8; if col < buffer.width() and rowb < buffer.height() { diff --git a/lib/intfs/buffer8.rob b/lib/intfs/buffer8.rob index 820b474..cbcaaa6 100644 --- a/lib/intfs/buffer8.rob +++ b/lib/intfs/buffer8.rob @@ -6,6 +6,7 @@ interface buffer8 { uint16 height(); uint16 width(); + void clear(); uint8 get(uint16 row, uint16 col); void set(uint16 row, uint16 col, uint8 v); } diff --git a/lib/intfs/databus.rob b/lib/intfs/databus.rob index e5ebedc..c1bfd78 100644 --- a/lib/intfs/databus.rob +++ b/lib/intfs/databus.rob @@ -3,13 +3,17 @@ * Apache License v2.0. */ +enum databus_protocol {SPI, I2C, UART, CAN} + interface databus { - void setup(int32 speed); + void setup(uint32 speed); void enable(); void disable(); void write(uint8 b); + void write_array(int8[] data); uint8 read(); bool has_data(); - void start_transaction(); + bool start_transaction(uint16 addr); void end_transaction(); + databus_protocol get_protocol(); } diff --git a/lib/intfs/display.rob b/lib/intfs/display.rob index 8e4de4a..51ab678 100644 --- a/lib/intfs/display.rob +++ b/lib/intfs/display.rob @@ -13,4 +13,5 @@ interface display { void set_contrast(uint8 c); void update_frame(); void clear(); + void set_address(uint8 a); } diff --git a/lib/intfs/mcu.rob b/lib/intfs/mcu.rob index 7e9e745..0e2b1f4 100644 --- a/lib/intfs/mcu.rob +++ b/lib/intfs/mcu.rob @@ -4,10 +4,8 @@ */ interface mcu { - void wait_us(int16 us); - void wait_ms(int16 ms); - void enable_led(); - void set_led(bool s); + void wait_us(uint16 us); + void wait_ms(uint16 ms); void set_interruptions(bool enabled); uint32 clock(); } diff --git a/lib/intfs/ports.rob b/lib/intfs/ports.rob index ed81fb6..8ee2757 100644 --- a/lib/intfs/ports.rob +++ b/lib/intfs/ports.rob @@ -3,7 +3,7 @@ * Apache License v2.0. */ -enum port_mode { input, output } +enum port_mode { input = 0, output = 1} interface digitalport { void mode(port_mode m); @@ -13,6 +13,18 @@ interface digitalport { interface analogport { void mode(port_mode m); - void set(int16 v); - int16 get(); + void set(uint16 v); + uint16 get(); +} + +type null_digitalport implements digitalport { + void mode(port_mode m) inline { return; } + void set(bool v) inline { return; } + bool get() inline { return false; } +} + +type null_analogport implements analogport { + void mode(port_mode m) inline { return; } + void set(uint16 v) inline { return; } + uint16 get() inline { return 0; } } diff --git a/lib/math/random16.rob b/lib/math/random16.rob index 24d02d1..99a2077 100644 --- a/lib/math/random16.rob +++ b/lib/math/random16.rob @@ -42,4 +42,3 @@ uint16 random16ub(uint16 upto) { } return uint16(m >> 16); } - diff --git a/lib/math/random32.rob b/lib/math/random32.rob index a387f99..576dc27 100644 --- a/lib/math/random32.rob +++ b/lib/math/random32.rob @@ -32,8 +32,8 @@ uint32 random32() { if (x < 0) { x += random_max32; } - random_seed = x; - return (random_seed % (random_max32 + 1u)); + random_seed32 = x; + return (random_seed32 % (random_max32 + 1u)); } /* diff --git a/lib/stm32f1.ld b/lib/stm32f1.ld index 685dc93..02532f4 100644 --- a/lib/stm32f1.ld +++ b/lib/stm32f1.ld @@ -8,15 +8,42 @@ __reset_stack_pointer = ORIGIN(RAM) + LENGTH(RAM); SECTIONS { - .text 0x0 : { - . = 0; - /* Set the initial address to 0 */ - LONG(__reset_stack_pointer); - LONG(main | 1); - /* The whole interrupt table is 332 bytes long. Advance to that position. */ - . = 332; - /* And here comes the rest of the code */ - *(.text*) - } > FLASH /* Put this in the flash memory region */ -} + .isr_vector : { + LONG(__reset_stack_pointer); + LONG(__isr_reset | 1); + LONG(__isr_nmi | 1); + /* The interrupt table is 332 bytes long. Advance to that position. */ + . = ORIGIN(FLASH) + 332; + } > FLASH + + .text : { + . = ALIGN(4); + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + . = ALIGN(4); + } > FLASH + + __data_init = LOADADDR(.data); + .data : { + __data_start = .; + *(.data) + *(.data.*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH + + .bss : + { + __bss_start = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/lib/stm32f1.rob b/lib/stm32f1.rob new file mode 100644 index 0000000..710a90f --- /dev/null +++ b/lib/stm32f1.rob @@ -0,0 +1,171 @@ +/* + * Robcmp interruptions vector for stm32f1 + */ + +use arch.stm32.stm32f1regs; +use math.limits; + +int8 main(); + +/*void __set_system_clock_to_72Mhz() { + // Necessary wait states for Flash for high speeds + FLASH->ACR = 0x12; + // Enable HSE + RCC->CR |= (1 << 16); + // Wait untill HSE settles down + while (!(RCC->CR & (1 << 17))); + // Set PREDIV2 division factor to 5 + RCC->CFGR2 |= (0b0100 << 4); + // Set PLL2 multiplication factor to 8 + RCC->CFGR2 |= (0b0110 << 8); + // Enable PLL2 + RCC->CR |= (1 << 26); + // Wait untill PLL2 settles down + while (!(RCC->CR & (1 << 27))); + // Set PLL2 as PREDIV1 clock source + RCC->CFGR2 |= (1 << 16); + // Set PREDIV1 division factor to 5 + RCC->CFGR2 |= (0b0100 << 0); + // Select Prediv1 as PLL source + RCC->CFGR |= (1 << 16); + // Set PLL1 multiplication factor to 9 + RCC->CFGR |= (0b0111 << 18); + // Set APB1 to 36MHz + RCC->CFGR |= 1 << 10; + // Enable PLL + RCC->CR |= (1 << 24); + // Wait untill PLL settles down + while (!(RCC->CR & (1 << 25))); + // Finally, choose PLL as the system clock + RCC->CFGR |= (0b10 << 0); +} +*/ + +//const HSE_Value = 25E6; // External oscillator in Hz +//const HSI_Value = 8E6; // Internal oscillator in Hz + +void __set_system_clock_to_25Mhz() { + // Enable HSE and waits it to settle down + RCC_CR.hse_on = true; + while !RCC_CR.hse_rdy; + // Set HSE as the system clock + RCC_CFGR.sw = uint2(0x01); +} + +void __system_clock_config() { + //__set_system_clock_to_25Mhz(); + SYSTICK_LOAD = 0xFFFFFF; //24 bits + SYSTICK_CTRL.enable = true; + SYSTICK_CTRL.clksource = true; // processor clock +} + +void __error_handler() { + loop { + asm "wfi"; + } +} + +void memset() noinline { +// reference signature: +// void *memset(void *dst, int val, size_t count) +// r0 ↑ r1 ↑ r2 ↑ +asm + "cmp r2, #0 + it eq + bxeq lr /* return if r2/count==0 */ + mov r12, r0 + tst r0, #3 /* is 4-bytes aligned? */ + beq __memset_aligned + + __memset_unaligned: + strb r1, [r12], #1 + subs r2, r2, #1 + it eq + bxeq lr /* return if r2/count==0 */ + tst r12, #13 /* is 4-bytes aligned now? */ + bne __memset_unaligned + + __memset_aligned: + bfi r1, r1, #8, #8 + bfi r1, r1, #16, #16 + mov r3, r1 + cmp r2, #16 + blo __memset_less16 + push {r4, lr} + mov r4, r1 + mov lr, r1 + cmp r2, #32 + blo __memset_less32 + + __memset_write32: + stmia r12!, {r1, r3, r4, lr} /* write 32 bytes */ + stmia r12!, {r1, r3, r4, lr} + subs r2, r2, #32 + it eq + popeq {r4, pc} + cmp r2, #32 + bhs __memset_write32 + + __memset_less32: + cmp r2, #16 + it hs + stmiahs r12!, {r1, r3, r4, lr} + it eq + popeq {r4, pc} + pop {r4, lr} + + __memset_less16: + lsls r2, r2, #29 + it cs + stmiacs r12!, {r1, r3} + it eq + bxeq lr + it mi + strmi r1, [r12], #4 + lsls r2, r2, #1 + it mi + strhmi r1, [r12], #2 + it ne + strbne r1, [r12] + "; +} + +void __do_copy_data() noinline { +asm + "movs r1, #0 + b __do_copy_data_start + __do_copy_data_loop: + ldr r3, =__data_init + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + __do_copy_data_start: + ldr r0, =__data_start + ldr r3, =__data_end + adds r2, r0, r1 + cmp r2, r3 + bcc __do_copy_data_loop + ldr r2, =__bss_start + ldr r3, =__bss_end + movs r1, #0 + b __do_clear_bss_start + __do_clear_bss_loop: + str r1, [r2], #4 + __do_clear_bss_start: + cmp r2, r3 + bcc __do_clear_bss_loop"; +} + +void __isr_reset() { + + __do_copy_data(); + __system_clock_config(); + + main(); + + __error_handler(); +} + +void __isr_nmi() { + asm "nop"; +} diff --git a/platformio/examples/avr328p-ssd1306/platformio.ini b/platformio/examples/avr328p-ssd1306/platformio.ini deleted file mode 100644 index 41a6d29..0000000 --- a/platformio/examples/avr328p-ssd1306/platformio.ini +++ /dev/null @@ -1,13 +0,0 @@ - -[env] -platform = robcmp -board = avr328p -upload_protocol = serial - -[env:release] -build_type = release -debug_tool = robcmp-ssd1306 - -[env:debug] -build_type = debug -debug_tool = robcmp-ssd1306 diff --git a/platformio/examples/avr328p-ssd1306/src/main.rob b/platformio/examples/avr328p-ssd1306/src/main.rob deleted file mode 100644 index 4ff33b1..0000000 --- a/platformio/examples/avr328p-ssd1306/src/main.rob +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Robcmp examples: SSD1306 SPI - */ -use arch.avr.avr5mcu; -use display.ssd1306spi; -use graphic.canvas8; -use math.random16; -use intfs.mcu; -use intfs.display; -use intfs.databus; - -bind avr5mcu to global_instances.mmcu singleton; -bind avr5mcu.spi to global_instances.spi singleton; -bind avr5mcu to ssd1306spi.mmcu singleton; -bind avr5mcu.b0 to ssd1306spi.reset singleton; -bind avr5mcu.b1 to ssd1306spi.datacmd singleton; -bind avr5mcu.b2 to ssd1306spi.select singleton; -bind avr5mcu.spi to ssd1306spi.spi singleton; -bind ssd1306spi to global_instances.oled singleton; -bind ssd1306spi.framebuffer to canvas8.buffer singleton; - -// for now, the binding only works inside a type -type global_instances { - mmcu = mcu(); - spi = databus(); - oled = display(); -} - -int16 main() { - - gi = global_instances(); - mmcu = gi.mmcu; - spi = gi.spi; - oled = gi.oled; - canvas = canvas8(); - - spi.setup(0); - spi.enable(); - oled.init_display(); - oled.set_orientation(displayorientation.UPSIDE_DOWN); - - /*ball = {0b00000000, - 0b00011000, - 0b00111100, - 0b01111110, - 0b11111111, - 0b01111110, - 0b00111100, - 0b00011000};*/ - - col = 0u; - row = 0u; - - loop { - canvas.clear_pixel(row, col); - canvas.clear_pixel(row+1, col); - canvas.clear_pixel(row+1, col+1); - canvas.clear_pixel(row, col+1); - - col++; - row++; - - if col == canvas.width()-1 { - col = random16ub(canvas.width()-1); - row = random16ub(canvas.height()-1); - } - if row == canvas.height()-1 { - row = random16ub(canvas.height()-1); - } - - canvas.set_pixel(row, col); - canvas.set_pixel(row+1, col); - canvas.set_pixel(row+1, col+1); - canvas.set_pixel(row, col+1); - - oled.update_frame(); - } -} diff --git a/platformio/examples/avr328p-ssd1306/src/main.spec b/platformio/examples/avr328p-ssd1306/src/main.spec deleted file mode 100644 index 5ba2831..0000000 --- a/platformio/examples/avr328p-ssd1306/src/main.spec +++ /dev/null @@ -1 +0,0 @@ -bind avr5mcu to aux.mmcu; \ No newline at end of file diff --git a/platformio/examples/avr328p-blink/.gitignore b/platformio/examples/blink/.gitignore similarity index 100% rename from platformio/examples/avr328p-blink/.gitignore rename to platformio/examples/blink/.gitignore diff --git a/platformio/examples/blink/platformio.ini b/platformio/examples/blink/platformio.ini new file mode 100644 index 0000000..a72c72a --- /dev/null +++ b/platformio/examples/blink/platformio.ini @@ -0,0 +1,30 @@ + +[avr] +platform = robcmp +board = avr328p +upload_protocol = serial +board_hardware_spec = specs/avr.spec + +[env:avr-release] +extends = avr +build_type = release + +[env:avr-debug] +extends = avr +build_type = debug +debug_tool = robcmp-led + + + +[stm32] +platform = robcmp +board = stm32f1 +upload_protocol = stlink +board_hardware_spec = specs/stm32.spec + +[env:stm32-release] +extends = stm32 + +[env:stm32-debug] +extends = stm32 +build_type = debug diff --git a/platformio/examples/blink/specs/avr.spec b/platformio/examples/blink/specs/avr.spec new file mode 100644 index 0000000..8e55299 --- /dev/null +++ b/platformio/examples/blink/specs/avr.spec @@ -0,0 +1,5 @@ + +use arch.avr.avr5mcu; + +bind avr5mcu to globals.mmcu singleton; +bind avr5mcu.b5 to globals.led singleton; diff --git a/platformio/examples/blink/specs/stm32.spec b/platformio/examples/blink/specs/stm32.spec new file mode 100644 index 0000000..b562d3d --- /dev/null +++ b/platformio/examples/blink/specs/stm32.spec @@ -0,0 +1,5 @@ + +use arch.stm32.stm32f1; + +bind stm32f1 to globals.mmcu singleton; +bind stm32f1.c13 to globals.led singleton; diff --git a/platformio/examples/blink/src/main.rob b/platformio/examples/blink/src/main.rob new file mode 100644 index 0000000..3da34be --- /dev/null +++ b/platformio/examples/blink/src/main.rob @@ -0,0 +1,26 @@ +/* + * Robcmp examples: Blink + * Blinks the board default led + */ + +use intfs.ports; + +type globals { + mmcu = mcu(); + led = digitalport(); +} + +int16 main() { + gg = globals(); + mmcu = gg.mmcu; + led = gg.led; + + led.mode(port_mode.output); + + loop { + led.set(true); + mmcu.wait_ms(500); + led.set(false); + mmcu.wait_ms(500); + } +} diff --git a/platformio/examples/avr328p-ssd1306/.gitignore b/platformio/examples/old/avr328p-blink/.gitignore similarity index 100% rename from platformio/examples/avr328p-ssd1306/.gitignore rename to platformio/examples/old/avr328p-blink/.gitignore diff --git a/platformio/examples/avr328p-blink/platformio.ini b/platformio/examples/old/avr328p-blink/platformio.ini similarity index 100% rename from platformio/examples/avr328p-blink/platformio.ini rename to platformio/examples/old/avr328p-blink/platformio.ini diff --git a/platformio/examples/avr328p-blink/src/main.rob b/platformio/examples/old/avr328p-blink/src/main.rob similarity index 100% rename from platformio/examples/avr328p-blink/src/main.rob rename to platformio/examples/old/avr328p-blink/src/main.rob diff --git a/platformio/examples/avr328p-blink/src/wait.rob b/platformio/examples/old/avr328p-blink/src/wait.rob similarity index 100% rename from platformio/examples/avr328p-blink/src/wait.rob rename to platformio/examples/old/avr328p-blink/src/wait.rob diff --git a/platformio/examples/stm32f1-blink/.gitignore b/platformio/examples/old/avr328p-ssd1306/.gitignore similarity index 100% rename from platformio/examples/stm32f1-blink/.gitignore rename to platformio/examples/old/avr328p-ssd1306/.gitignore diff --git a/platformio/examples/avr328p-ssd1306/genll.sh b/platformio/examples/old/avr328p-ssd1306/genll.sh similarity index 100% rename from platformio/examples/avr328p-ssd1306/genll.sh rename to platformio/examples/old/avr328p-ssd1306/genll.sh diff --git a/platformio/examples/old/avr328p-ssd1306/platformio.ini b/platformio/examples/old/avr328p-ssd1306/platformio.ini new file mode 100644 index 0000000..9b03d1f --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/platformio.ini @@ -0,0 +1,39 @@ + +[avr328p] +platform = robcmp +board = avr328p +upload_protocol = serial + +[env:avr328p_release_spi] +extends = avr328p +build_type = release +debug_tool = robcmp-ssd1306 +board_hardware_spec = specs/avr-spi.spec + +[env:avr328p_release_i2c] +extends = avr328p +build_type = release +debug_tool = robcmp-led +board_hardware_spec = specs/avr-i2c.spec + +[env:avr328p_debug_spi] +extends = avr328p +build_type = debug +debug_tool = robcmp-ssd1306 +board_hardware_spec = specs/avr-spi.spec + +[env:avr328p_debug_i2c] +extends = avr328p +build_type = debug +debug_tool = robcmp-led +board_hardware_spec = specs/avr-i2c.spec + +[stm32f1] +platform = robcmp +board = stm32f1 +upload_protocol = stlink + +[env:stm32f1_debug_i2c] +extends = stm32f1 +build_type = debug +board_hardware_spec = specs/stm32f1-i2c.spec diff --git a/platformio/examples/old/avr328p-ssd1306/specs/avr-i2c.spec b/platformio/examples/old/avr328p-ssd1306/specs/avr-i2c.spec new file mode 100644 index 0000000..10f03a2 --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/specs/avr-i2c.spec @@ -0,0 +1,18 @@ +/* + * Injections for a SSD1306 I2C display + * and an Atmega328p mcu + */ + +bind avr5mcu to global_instances.mmcu singleton; +bind avr5mcu to ssd1306.mmcu singleton; +bind avr5mcu.b5 to global_instances.led singleton; + +// I2C display +bind null_digitalport to ssd1306.reset singleton; +bind null_digitalport to ssd1306.datacmd singleton; +bind null_digitalport to ssd1306.select singleton; +bind avr5mcu.i2c to global_instances.dbus singleton; +bind avr5mcu.i2c to ssd1306.dbus singleton; + +bind ssd1306 to global_instances.oled singleton; +bind ssd1306.framebuffer to canvas8.buffer singleton; diff --git a/platformio/examples/old/avr328p-ssd1306/specs/avr-spi.spec b/platformio/examples/old/avr328p-ssd1306/specs/avr-spi.spec new file mode 100644 index 0000000..688319e --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/specs/avr-spi.spec @@ -0,0 +1,18 @@ +/* + * Injections for a SSD1306 SPI display + * and an Atmega328p mcu + */ + +bind avr5mcu to global_instances.mmcu singleton; +bind avr5mcu to ssd1306.mmcu singleton; +bind avr5mcu.b5 to global_instances.led singleton; + +// SPI display +bind avr5mcu.b0 to ssd1306.reset singleton; +bind avr5mcu.b1 to ssd1306.datacmd singleton; +bind avr5mcu.b2 to ssd1306.select singleton; +bind avr5mcu.spi to global_instances.dbus singleton; +bind avr5mcu.spi to ssd1306.dbus singleton; + +bind ssd1306 to global_instances.oled singleton; +bind ssd1306.framebuffer to canvas8.buffer singleton; \ No newline at end of file diff --git a/platformio/examples/old/avr328p-ssd1306/specs/stm32f1-i2c.spec b/platformio/examples/old/avr328p-ssd1306/specs/stm32f1-i2c.spec new file mode 100644 index 0000000..9e02845 --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/specs/stm32f1-i2c.spec @@ -0,0 +1,19 @@ +/* + * Injections for a SSD1306 I2C display + * and an stm32f103 mcu + */ + + bind stm32f1 to global_instances.mmcu singleton; + bind stm32f1 to ssd1306.mmcu singleton; + bind stm32f1.c13 to global_instances.led singleton; + + // I2C display + bind null_digitalport to ssd1306.reset singleton; + bind null_digitalport to ssd1306.datacmd singleton; + bind null_digitalport to ssd1306.select singleton; + bind stm32f1.i2c1 to global_instances.dbus singleton; + bind stm32f1.i2c1 to ssd1306.dbus singleton; + + bind ssd1306 to global_instances.oled singleton; + bind ssd1306.framebuffer to canvas8.buffer singleton; + \ No newline at end of file diff --git a/platformio/examples/old/avr328p-ssd1306/src/main.rob b/platformio/examples/old/avr328p-ssd1306/src/main.rob new file mode 100644 index 0000000..b09d34d --- /dev/null +++ b/platformio/examples/old/avr328p-ssd1306/src/main.rob @@ -0,0 +1,113 @@ +/* + * Robcmp examples: SSD1306 + */ + +//TODO: Move to .spec +//use arch.avr.avr5mcu; +use arch.stm32.stm32f1; +use display.ssd1306; + +use graphic.canvas8; +use math.random16; +use math.random32; +use intfs.mcu; +use intfs.display; +use intfs.databus; + +// for now, the binding only works inside a type +type global_instances { + mmcu = mcu(); + dbus = databus(); + oled = display(); + led = digitalport(); +} + +int16 main() { + gi = global_instances(); + mmcu = gi.mmcu; + dbus = gi.dbus; + canvas = canvas8(); + + // blink start + led = gi.led; + led.mode(port_mode.output); + led.set(true); + mmcu.wait_ms(500); + led.set(false); + mmcu.wait_ms(500); + led.set(true); + mmcu.wait_ms(500); + + if (dbus.get_protocol() == databus_protocol.I2C) { + dbus.setup(400E3); //400khz + } else { // SPI + dbus.setup(4E6); + } + dbus.enable(); + + oled = gi.oled; + oled.set_address(0x78); + oled.init_display(); + + symbol = {0b00000000, + 0b11111110, + 0b11000011, + 0b11000011, + 0b11111110, + 0b11000110, + 0b11000011, + 0b11000011}; + + col = 0u; + row = 0u; + + count = 1000; + while count > 0 { + col = random16()%(canvas.width()-1); + row = random16()%(canvas.height()-1); + canvas.set_pixel(row, col); + oled.update_frame(); + count--; + } + + loop { + // clear last draw + byte = 0u; + while byte < symbol.size { + symbolcol = 0u; + while symbolcol < 8 { + canvas.clear_pixel(row + byte, col + symbolcol); + symbolcol++; + } + byte++; + } + + col++; + row++; + + if col == canvas.width()-1 or + row == canvas.height()-1 { + //col = uint8(random16ub(canvas.width()-1)); + //row = uint8(random16ub(canvas.height()-1)); + col = random16()%(canvas.width()-1); + row = random16()%(canvas.height()-1); + } + + // clear last draw ball + byte = 0u; + while byte < symbol.size { + symbolcol = 0u; + while symbolcol < 8 { + if symbol[byte] & (1< 0 { + canvas.set_pixel(row + byte, col + (7-symbolcol)); + } + symbolcol++; + } + byte++; + } + + oled.update_frame(); + } + + return 0; +} diff --git a/platformio/examples/old/stm32f1-blink/.gitignore b/platformio/examples/old/stm32f1-blink/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/platformio/examples/old/stm32f1-blink/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/platformio/examples/old/stm32f1-blink/platformio.ini b/platformio/examples/old/stm32f1-blink/platformio.ini new file mode 100644 index 0000000..1afa668 --- /dev/null +++ b/platformio/examples/old/stm32f1-blink/platformio.ini @@ -0,0 +1,7 @@ + +[env:bluepill] +platform = robcmp +build_type = debug +board = stm32f1 +upload_protocol = stlink +board_hardware_spec = src/hardware.spec \ No newline at end of file diff --git a/platformio/examples/old/stm32f1-blink/src/hardware.spec b/platformio/examples/old/stm32f1-blink/src/hardware.spec new file mode 100644 index 0000000..e69de29 diff --git a/platformio/examples/old/stm32f1-blink/src/main.rob b/platformio/examples/old/stm32f1-blink/src/main.rob new file mode 100644 index 0000000..c7b2ab1 --- /dev/null +++ b/platformio/examples/old/stm32f1-blink/src/main.rob @@ -0,0 +1,21 @@ + +/* + * Sample Blink Led on port 13 for STM32F1 + */ + +use arch.stm32.stm32f1; +use intfs.ports; + +int8 main() { + mmcu = stm32f1(); + + c13 = mmcu.c13; + c13.mode(port_mode.output); + + loop { + c13.set(true); + mmcu.wait_ms(500); + c13.set(false); + mmcu.wait_ms(500); + } +} diff --git a/platformio/examples/ssd1306/.gitignore b/platformio/examples/ssd1306/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/platformio/examples/ssd1306/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/platformio/examples/ssd1306/elf_reader.py b/platformio/examples/ssd1306/elf_reader.py new file mode 100755 index 0000000..70c61e7 --- /dev/null +++ b/platformio/examples/ssd1306/elf_reader.py @@ -0,0 +1,643 @@ +#!python3.9 +# -*- coding: utf-8 -*- + +# Description +# ----------- +# Print information about an ELF binary + +import os +import sys +import textwrap +import traceback + +import lief +from lief import ELF +import argparse + +terminal_rows, terminal_columns = 100, 110 +try: + terminal_rows, terminal_columns = os.popen('stty size', 'r').read().split() +except ValueError: + pass + +terminal_columns = int(terminal_columns) - 10 +terminal_rows = int(terminal_rows) + +class exceptions_handler(object): + func = None + + def __init__(self, exceptions, on_except_callback=None): + self.exceptions = exceptions + self.on_except_callback = on_except_callback + + def __call__(self, *args, **kwargs): + if self.func is None: + self.func = args[0] + return self + try: + return self.func(*args, **kwargs) + except self.exceptions as e: + if self.on_except_callback is not None: + self.on_except_callback(e) + else: + print("-" * 60) + print("Exception in {}: {}".format(self.func.__name__, e)) + exc_type, exc_value, exc_traceback = sys.exc_info() + traceback.print_tb(exc_traceback) + print("-" * 60) + + +@exceptions_handler(Exception) +def print_header(binary): + header = binary.header + identity = header.identity + + + print("== Header ==\n") + format_str = "{:<30} {:<30}" + format_hex = "{:<30} 0x{:<13x}" + format_dec = "{:<30} {:<30d}" + format_ide = "{:<30} {:<02x} {:<02x} {:<02x} {:<02x}" + + eflags_str = "" + if header.machine_type == lief.ELF.ARCH.ARM: + eflags_str = " - ".join([str(s).split(".")[-1] for s in header.arm_flags_list]) + + if header.machine_type in [lief.ELF.ARCH.MIPS, lief.ELF.ARCH.MIPS_RS3_LE, lief.ELF.ARCH.MIPS_X]: + eflags_str = " - ".join([str(s).split(".")[-1] for s in header.mips_flags_list]) + + if header.machine_type == lief.ELF.ARCH.PPC64: + eflags_str = " - ".join([str(s).split(".")[-1] for s in header.ppc64_flags_list]) + + if header.machine_type == lief.ELF.ARCH.HEXAGON: + eflags_str = " - ".join([str(s).split(".")[-1] for s in header.hexagon_flags_list]) + print(identity) + print(format_ide.format("Magic:", identity[0], identity[1], identity[2], identity[3])) + print(format_str.format("Class:", str(header.identity_class).split(".")[-1])) + print(format_str.format("Endianness:", str(header.identity_data).split(".")[-1])) + print(format_str.format("Version:", str(header.identity_version).split(".")[-1])) + print(format_str.format("OS/ABI:", str(header.identity_os_abi).split(".")[-1])) + print(format_dec.format("ABI Version:", header.identity_abi_version)) + print(format_str.format("File Type:", str(header.file_type).split(".")[-1])) + print(format_str.format("Machine Type:", str(header.machine_type).split(".")[-1])) + print(format_str.format("Object File Version:", str(header.object_file_version).split(".")[-1])) + print(format_hex.format("Entry Point:", header.entrypoint)) + print(format_hex.format("Program Header Offset:", header.program_header_offset)) + print(format_hex.format("Section Header Offset:", header.section_header_offset)) + print(format_hex.format("Processor flags:", header.processor_flag) + eflags_str) + print(format_dec.format("Header Size:", header.header_size)) + print(format_dec.format("Program Header Size:", header.program_header_size)) + print(format_dec.format("Section Header Size:", header.section_header_size)) + print(format_dec.format("Number of segments:", header.numberof_segments)) + print(format_dec.format("Number of sections:", header.numberof_sections)) + print("") + + +@exceptions_handler(Exception) +def print_sections(binary): + sections = binary.sections + if len(sections) > 0: + print("== Sections ==\n") + f_title = "|{:<30} | {:<12}| {:<17}| {:<12}| {:<10}| {:<8}| {:<8}|" + f_value = "|{:<30} | {:<12}| 0x{:<14x} | 0x{:<10x}| 0x{:<8x}| {:<8.2f}| {:<10}" + print(f_title.format("Name", "Type", "Virtual address", "File offset", "Size", "Entropy", "Segment(s)")) + + for section in sections: + segments_str = " - ".join([str(s.type).split(".")[-1] for s in section.segments]) + print(f_value.format( + section.name, + str(section.type).split(".")[-1], + section.virtual_address, + section.file_offset, + section.size, + abs(section.entropy), + segments_str)) + print("") + else: + print("No sections") + +@exceptions_handler(Exception) +def print_segments(binary): + segments = binary.segments + # Segments + if len(segments) > 0: + print("== Segments ==\n") + f_title = "|{:<30} | {:<10}| {:<18}| {:<17}| {:<17}| {:<17}| {:<19}|" + f_value = "|{:<30} | {:<10}| 0x{:<16x}| 0x{:<15x}| 0x{:<15x}| 0x{:<15x}| {}" + print(f_title.format("Type", + "Flags", "File offset", "Virtual Address", "Virtual Size", "Size", "Sections")) + + for segment in segments: + sections = segment.sections + s = ", ".join([section.name for section in sections]) + flags_str = ["-"] * 3 + if ELF.SEGMENT_FLAGS.R in segment: + flags_str[0] = "r" + + if ELF.SEGMENT_FLAGS.W in segment: + flags_str[1] = "w" + + if ELF.SEGMENT_FLAGS.X in segment: + flags_str[2] = "x" + flags_str = "".join(flags_str) + + print(f_value.format( + str(segment.type).split(".")[-1], + flags_str, + segment.file_offset, + segment.virtual_address, + segment.virtual_size, + segment.physical_size, s)) + print("") + else: + print("No segments") + +@exceptions_handler(Exception) +def print_dynamic_entries(binary): + dynamic_entries = binary.dynamic_entries + # Dynamic entries + if len(dynamic_entries) == 0: + return + + print("== Dynamic entries ==\n") + f_title = "|{:<16} | {:<10}| {:<20}|" + f_value = "|{:<16} | 0x{:<8x}| {:<20}|" + print(f_title.format("Tag", "Value", "Info")) + for entry in dynamic_entries: + if entry.tag == ELF.DYNAMIC_TAGS.NULL: + continue + + if entry.tag in [ELF.DYNAMIC_TAGS.SONAME, ELF.DYNAMIC_TAGS.NEEDED, ELF.DYNAMIC_TAGS.RUNPATH, ELF.DYNAMIC_TAGS.RPATH]: + print(f_value.format(str(entry.tag).split(".")[-1], entry.value, entry.name)) + elif type(entry) is ELF.DynamicEntryArray: # [ELF.DYNAMIC_TAGS.INIT_ARRAY,ELF.DYNAMIC_TAGS.FINI_ARRAY]: + print(f_value.format(str(entry.tag).split(".")[-1], entry.value, ", ".join(map(hex, entry.array)))) + elif entry.tag == ELF.DYNAMIC_TAGS.FLAGS: + flags_str = " - ".join([str(ELF.DYNAMIC_FLAGS(s)).split(".")[-1] for s in entry.flags]) + print(f_value.format(str(entry.tag).split(".")[-1], entry.value, flags_str)) + elif entry.tag == ELF.DYNAMIC_TAGS.FLAGS_1: + flags_str = " - ".join([str(ELF.DYNAMIC_FLAGS_1(s)).split(".")[-1] for s in entry.flags]) + print(f_value.format(str(entry.tag).split(".")[-1], entry.value, flags_str)) + else: + print(f_value.format(str(entry.tag).split(".")[-1], entry.value, "")) + + print("") + + +@exceptions_handler(Exception) +def print_symbols(symbols, no_trunc): + can_demangle = len(symbols) > 0 and len(symbols[0].demangled_name) > 0 + if can_demangle: + maxsize = max([len(symbol.demangled_name) for symbol in symbols]) + else: + maxsize = max([len(symbol.name) for symbol in symbols]) + + SIZE = 70 + maxsize = min(maxsize, terminal_columns - SIZE) if terminal_columns > SIZE else terminal_columns + + f_title = "|{:<" + str(maxsize) + "} | {:<7}| {:<8}| {:<10}| {:<8}| {:<4}| {:<14}|" + f_value = "|{:<" + str(maxsize) + "} | {:<7}| {:<8x}| {:<10}| {:<8}| {:<4}| {:<14}|" + + print(f_title.format("Name", "Type", "Value", "Visibility", "Binding", "I/E", "Version")) + + for symbol in symbols: + symbol_version = symbol.symbol_version if symbol.has_version else "" + + import_export = "" + if symbol.imported: + import_export = "I" + + if symbol.exported: + import_export = "E" + + symbol_name = symbol.demangled_name + if len(symbol_name) == 0: + symbol_name = symbol.name + + wrapped = textwrap.wrap(symbol_name, maxsize) + + if len(wrapped) <= 1 or no_trunc: + symbol_name = symbol_name + else: + symbol_name = wrapped[0][:-3] + "..." + + print(f_value.format( + symbol_name, + str(symbol.type).split(".")[-1], + symbol.value, + str(symbol.visibility).split(".")[-1], + str(symbol.binding).split(".")[-1], + import_export, + str(symbol_version) + )) + +@exceptions_handler(Exception) +def print_dynamic_symbols(binary, args): + print("== Dynamic symbols ==\n") + print_symbols(binary.dynamic_symbols, args.no_trunc) + + +@exceptions_handler(Exception) +def print_static_symbols(binary, args): + print("== Static symbols ==\n") + print_symbols(binary.static_symbols, args.no_trunc) + +@exceptions_handler(Exception) +def print_relocations(binary, relocations): + f_title = "|{:<10} | {:<10}| {:<8}| {:<8}| {:<8}| {:<15}| {:<30} |" + f_value = "|0x{:<8x} | {:<10}| {:<8d}| {:<8d}| {:<8x}| {:<15}| {:<30} |" + + print(f_title.format("Address", "Type", "Info", "Size", "Addend", "Purpose", "Symbol")) + + for relocation in relocations: + type = str(relocation.type) + if binary.header.machine_type == ELF.ARCH.x86_64: + type = str(ELF.RELOCATION_X86_64(relocation.type)) + elif binary.header.machine_type == ELF.ARCH.i386: + type = str(ELF.RELOCATION_i386(relocation.type)) + elif binary.header.machine_type == ELF.ARCH.ARM: + type = str(ELF.RELOCATION_ARM(relocation.type)) + elif binary.header.machine_type == ELF.ARCH.AARCH64: + type = str(ELF.RELOCATION_AARCH64(relocation.type)) + + symbol_name = "" + if relocation.has_symbol: + symbol: lief.ELF.Symbol = relocation.symbol + if len(symbol.name) > 0: + symbol_name = symbol.name + elif symbol.type == lief.ELF.SYMBOL_TYPES.SECTION: + shndx = symbol.shndx + sections = binary.sections + if 0 < shndx and shndx < len(sections): + symbol_name = sections[shndx].name + " + " + hex(relocation.addend) + else: + symbol_name = "
".format(shndx) + + + print(f_value.format( + relocation.address, + type.split(".")[-1], + relocation.info, + relocation.size, + relocation.addend, + str(relocation.purpose).split(".")[-1], + symbol_name)) + + +@exceptions_handler(Exception) +def print_all_relocations(binary): + dynamicrelocations = binary.dynamic_relocations + pltgot_relocations = binary.pltgot_relocations + object_relocations = binary.object_relocations + + if len(dynamicrelocations) > 0: + print("== Dynamic Relocations ==\n") + print_relocations(binary, dynamicrelocations) + + + if len(pltgot_relocations) > 0: + print("== PLT/GOT Relocations ==\n") + print_relocations(binary, pltgot_relocations) + + if len(object_relocations) > 0: + print("== Object Relocations ==\n") + print_relocations(binary, object_relocations) + +@exceptions_handler(Exception) +def print_exported_symbols(binary, args): + symbols = binary.exported_symbols + + print("== Exported symbols ==\n") + if len(symbols) == 0: + print("No exports!") + return + print_symbols(symbols, args.no_trunc) + +@exceptions_handler(Exception) +def print_imported_symbols(binary, args): + symbols = binary.imported_symbols + print("== Imported symbols ==\n") + + if len(symbols) == 0: + print("No imports!") + return + print_symbols(symbols, args.no_trunc) + +@exceptions_handler(Exception) +def print_information(binary): + print("== Information ==\n") + format_str = "{:<30} {:<30}" + format_hex = "{:<30} 0x{:<28x}" + format_dec = "{:<30} {:<30d}" + print(format_str.format("Name:", binary.name)) + print(format_hex.format("Address base:", binary.imagebase)) + print(format_hex.format("Virtual size:", binary.virtual_size)) + print(format_str.format("PIE:", str(binary.is_pie))) + print(format_str.format("NX:", str(binary.has_nx))) + +@exceptions_handler(Exception) +def print_gnu_hash(binary): + print("== GNU Hash ==\n") + + if not binary.use_gnu_hash: + return + + gnu_hash = binary.gnu_hash + + format_str = "{:<30} {}" + format_hex = "{:<30} 0x{:<28x}" + format_dec = "{:<30} {:<30d}" + + print(format_dec.format("Number of buckets:", gnu_hash.nb_buckets)) + print(format_dec.format("First symbol index:", gnu_hash.symbol_index)) + print(format_hex.format("Shift Count:", gnu_hash.shift2)) + print(format_str.format("Bloom filters:", gnu_hash.bloom_filters)) + print(format_str.format("Buckets:", gnu_hash.buckets)) + print(format_str.format("Hash values:", gnu_hash.hash_values)) + + +@exceptions_handler(Exception) +def print_sysv_hash(binary): + print("== SYSV Hash ==\n") + + if not binary.use_sysv_hash: + return + + sysv_hash = binary.sysv_hash + + format_str = "{:<30} {}" + format_hex = "{:<30} 0x{:<28x}" + format_dec = "{:<30} {:<30d}" + + print(format_dec.format("Number of buckets:", sysv_hash.nbucket)) + print(format_dec.format("Number of chains:", sysv_hash.nchain)) + print(format_str.format("Buckets:", sysv_hash.buckets)) + print(format_str.format("Chains:", sysv_hash.chains)) + + +@exceptions_handler(Exception) +def print_notes(binary): + print("== Notes ==\n") + + format_str = "{:<19} {}" + format_hex = "{:<19} 0x{:<28x}" + format_dec = "{:<19} {:<30d}" + + notes = binary.notes + for idx, note in enumerate(notes): + description = note.description + description_str = " ".join(map(lambda e : "{:02x}".format(e), description[:16])) + if len(description) > 16: + description_str += " ..." + + print("Note #{:d}".format(idx)) + + type_str = note.type_core if note.is_core else note.type + type_str = str(type_str).split(".")[-1] + + print(format_str.format("Name:", note.name)) + print(format_str.format("Type:", type_str)) + print(format_str.format("Description:", description_str)) + + note_details = note.details + + if type(note_details) == lief.ELF.AndroidNote: + print(format_dec.format("SDK Version:", note_details.sdk_version)) + print(format_str.format("NDK Version:", note_details.ndk_version)) + print(format_str.format("NDK build number:", note_details.ndk_build_number)) + + if type(note_details) == lief.ELF.NoteAbi: + version = note_details.version + version_str = "{:d}.{:d}.{:d}".format(version[0], version[1], version[2]) + + print(format_str.format("ABI:", note_details.abi)) + print(format_str.format("Version:", version_str)) + + if ELF.NOTE_TYPES(note.type) == ELF.NOTE_TYPES.GOLD_VERSION: + print(format_str.format("Version:", "".join(map(chr, note.description)))) + + if note.is_core: + print(note_details) + + + print("\n") + + +@exceptions_handler(Exception) +def print_ctor(binary): + print("== Constructors ==\n") + + print("Functions: ({:d})".format(len(binary.ctor_functions))) + for idx, f in enumerate(binary.ctor_functions): + print(" [{:d}] {}: 0x{:x}".format(idx, f.name, f.address)) + +@exceptions_handler(Exception) +def print_strings(binary): + print("== Strings ==\n") + + + strings = binary.strings + print("Strings: ({:d})".format(len(binary.strings))) + for s in strings: + print(" {}".format(s)) + + +@exceptions_handler(Exception) +def print_functions(binary): + print("== Functions ==\n") + + functions = binary.functions + print("Functions: ({:d})".format(len(functions))) + for idx, f in enumerate(functions): + print(" [{:d}] {}: 0x{:x}".format(idx, f.name, f.address)) + + +def main(): + parser = argparse.ArgumentParser(add_help=False, prog=sys.argv[0]) + parser.add_argument("elf_file") + + parser.add_argument('-a', '--all', + action='store_true', dest='show_all', + help='Equivalent to: -h -l -S -s -r -d -V') + + parser.add_argument('-d', '--dynamic', + action='store_true', dest='show_dynamic_tags', + help='Display the dynamic section') + + parser.add_argument('-H', '--help', + action='help', dest='help', + help='Display this information') + + parser.add_argument('-h', '--file-header', + action='store_true', dest='show_file_header', + help='Display the ELF file header') + + parser.add_argument('-i', '--imported', + action='store_true', dest='show_imported_symbols', + help='Display imported symbols') + + parser.add_argument('-l', '--program-headers', '--segments', + action='store_true', dest='show_program_header', + help='Display the program headers') + + parser.add_argument('-S', '--section-headers', '--sections', + action='store_true', dest='show_section_header', + help="Display the sections' headers") + + parser.add_argument('-e', '--headers', + action='store_true', dest='show_all_headers', + help='Equivalent to: -h -l -S') + + parser.add_argument('-s', '--symbols', '--syms', + action='store_true', dest='show_symbols', + help='Display the symbol table') + + parser.add_argument('--dynamic-symbols', '--dsyms', + action='store_true', dest='show_dynamic_symbols', + help='Display the dynamic symbols') + + parser.add_argument('--static-symbols', '--ssyms', + action='store_true', dest='show_static_symbols', + help='Display the static symbols') + + parser.add_argument('-r', '--relocs', + action='store_true', dest='show_relocs', + help='Display the relocations (if present)') + + parser.add_argument('-V', '--version-info', + action='store_true', dest='show_version_info', + help='Display the version sections (if present)') + + parser.add_argument('-x', '--exported', + action='store_true', dest='show_exported_symbols', + help='Display exported symbols') + + parser.add_argument('--gnu-hash', + action='store_true', dest='show_gnu_hash', + help='Display GNU Hash') + + parser.add_argument('--sysv-hash', + action='store_true', dest='show_sysv_hash', + help='Display SYSV Hash') + + parser.add_argument('-n', '--notes', + action='store_true', dest='show_notes', + help='Display Notes') + + parser.add_argument('--no-trunc', + action='store_true', dest='no_trunc', + default=False, + help='Do not trunc symbol names ...') + + parser.add_argument('--ctor', + action='store_true', dest='show_ctor', + help='Constructor functions') + + parser.add_argument('--strings', + action='store_true', dest='show_strings', + help='Strings present in the current ELF') + + parser.add_argument('--functions', + action='store_true', dest='show_functions', + help='List all function addresses found') + + # Logging setup + logger_group = parser.add_argument_group('Logger') + verbosity = logger_group.add_mutually_exclusive_group() + + verbosity.add_argument('--debug', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.DEBUG) + + verbosity.add_argument('--trace', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.TRACE) + + verbosity.add_argument('--info', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.INFO) + + verbosity.add_argument('--warn', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.WARNING) + + verbosity.add_argument('--err', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.ERROR) + + verbosity.add_argument('--critical', + dest='main_verbosity', + action='store_const', + const=lief.logging.LOGGING_LEVEL.CRITICAL) + + parser.set_defaults(main_verbosity=lief.logging.LOGGING_LEVEL.WARNING) + + args = parser.parse_args() + + lief.logging.set_level(args.main_verbosity) + binary = ELF.parse(args.elf_file) + print_information(binary) + if args.show_all: + do_file_header = do_section_header = do_program_header = True + + if args.show_all_headers: + do_file_header = do_section_header = do_program_header = True + else: + do_file_header = args.show_file_header + do_section_header = args.show_section_header + do_program_header = args.show_program_header + + if do_file_header or args.show_all: + print_header(binary) + + if do_section_header or args.show_all: + print_sections(binary) + + if do_program_header or args.show_all: + print_segments(binary) + + if args.show_dynamic_tags or args.show_all: + print_dynamic_entries(binary) + + if (args.show_symbols or args.show_all or args.show_dynamic_symbols) and len(binary.dynamic_symbols) > 0: + print_dynamic_symbols(binary, args) + + if (args.show_symbols or args.show_all or args.show_static_symbols) and len(binary.static_symbols) > 0: + print_static_symbols(binary, args) + + if args.show_relocs or args.show_all: + print_all_relocations(binary) + + if args.show_imported_symbols or args.show_all: + print_imported_symbols(binary, args) + + if args.show_exported_symbols or args.show_all: + print_exported_symbols(binary, args) + + if (args.show_gnu_hash or args.show_all) and binary.use_gnu_hash: + print_gnu_hash(binary) + + if (args.show_sysv_hash or args.show_all) and binary.use_sysv_hash: + print_sysv_hash(binary) + + if args.show_notes or args.show_all: + print_notes(binary) + + if args.show_ctor or args.show_all: + print_ctor(binary) + + if args.show_strings or args.show_all: + print_strings(binary) + + if args.show_functions: + print_functions(binary) + + + + +if __name__ == "__main__": + main() diff --git a/platformio/examples/ssd1306/platformio.ini b/platformio/examples/ssd1306/platformio.ini new file mode 100644 index 0000000..a72c72a --- /dev/null +++ b/platformio/examples/ssd1306/platformio.ini @@ -0,0 +1,30 @@ + +[avr] +platform = robcmp +board = avr328p +upload_protocol = serial +board_hardware_spec = specs/avr.spec + +[env:avr-release] +extends = avr +build_type = release + +[env:avr-debug] +extends = avr +build_type = debug +debug_tool = robcmp-led + + + +[stm32] +platform = robcmp +board = stm32f1 +upload_protocol = stlink +board_hardware_spec = specs/stm32.spec + +[env:stm32-release] +extends = stm32 + +[env:stm32-debug] +extends = stm32 +build_type = debug diff --git a/platformio/examples/ssd1306/sections.txt b/platformio/examples/ssd1306/sections.txt new file mode 100644 index 0000000..de96037 --- /dev/null +++ b/platformio/examples/ssd1306/sections.txt @@ -0,0 +1,31 @@ +== Information == + +Name: .pio/build/stm32-debug/firmware.elf +Address base: 0x7ff0000 +Virtual size: 0x18011000 +PIE: False +NX: True +== Sections == + +|Name | Type | Virtual address | File offset | Size | Entropy | Segment(s)| +| | NULL | 0x0 | 0x0 | 0x0 | 0.00 | +|.isr_vector | PROGBITS | 0x8000000 | 0x10000 | 0x14c | 0.25 | LOAD +|.text | PROGBITS | 0x800014c | 0x1014c | 0x26c | 5.94 | LOAD +|.ARM.exidx | ARM_EXIDX | 0x80003b8 | 0x103b8 | 0x10 | 2.98 | LOAD - ARM_UNWIND +|.data | PROGBITS | 0x20000000 | 0x103c8 | 0x0 | 0.00 | LOAD +|.bss | NOBITS | 0x20000000 | 0x20000 | 0x24 | 0.00 | LOAD +|.got | PROGBITS | 0x20000024 | 0x20024 | 0x4 | 0.81 | LOAD - GNU_RELRO +|.ARM.attributes | ARM_ATTRIBUTES| 0x0 | 0x20028 | 0x3f | 4.82 | +|.debug_abbrev | PROGBITS | 0x0 | 0x20067 | 0x1bb | 4.55 | +|.debug_info | PROGBITS | 0x0 | 0x20222 | 0x1e5c | 4.39 | +|.debug_ranges | PROGBITS | 0x0 | 0x2207e | 0x2c0 | 1.81 | +|.debug_str | PROGBITS | 0x0 | 0x2233e | 0xf39 | 4.94 | +|.debug_pubnames | PROGBITS | 0x0 | 0x23277 | 0x92d | 5.17 | +|.debug_pubtypes | PROGBITS | 0x0 | 0x23ba4 | 0x2ca | 5.02 | +|.debug_frame | PROGBITS | 0x0 | 0x23e70 | 0x79c | 2.27 | +|.debug_line | PROGBITS | 0x0 | 0x2460c | 0xc6f | 4.87 | +|.comment | PROGBITS | 0x0 | 0x2527b | 0x1c | 4.08 | +|.symtab | SYMTAB | 0x0 | 0x25298 | 0x360 | 2.76 | +|.shstrtab | STRTAB | 0x0 | 0x255f8 | 0xcd | 4.28 | +|.strtab | STRTAB | 0x0 | 0x256c5 | 0x280 | 4.64 | + diff --git a/platformio/examples/ssd1306/specs/avr.spec b/platformio/examples/ssd1306/specs/avr.spec new file mode 100644 index 0000000..0f00502 --- /dev/null +++ b/platformio/examples/ssd1306/specs/avr.spec @@ -0,0 +1,4 @@ + +use arch.avr.avr5mcu; +use display.ssd1306; +use graphics.canvas; diff --git a/platformio/examples/ssd1306/specs/stm32.spec b/platformio/examples/ssd1306/specs/stm32.spec new file mode 100644 index 0000000..c8a70e6 --- /dev/null +++ b/platformio/examples/ssd1306/specs/stm32.spec @@ -0,0 +1,23 @@ +/* + * Injections for a SSD1306 I2C display + * and an stm32f103 mcu + */ + + use arch.stm32.stm32f1; + use display.ssd1306; + use graphic.canvas8; + + bind stm32f1 to globals.mmcu singleton; + bind stm32f1 to ssd1306.mmcu singleton; + bind stm32f1.c13 to globals.led singleton; + + // I2C display + bind null_digitalport to ssd1306.reset singleton; + bind null_digitalport to ssd1306.datacmd singleton; + bind null_digitalport to ssd1306.select singleton; + bind stm32f1.i2c1 to globals.dbus singleton; + bind stm32f1.i2c1 to ssd1306.dbus singleton; + + bind ssd1306 to globals.oled singleton; + bind ssd1306.framebuffer to canvas8.buffer singleton; + \ No newline at end of file diff --git a/platformio/examples/ssd1306/src/main.rob b/platformio/examples/ssd1306/src/main.rob new file mode 100644 index 0000000..b604820 --- /dev/null +++ b/platformio/examples/ssd1306/src/main.rob @@ -0,0 +1,72 @@ +/* + * Robcmp examples: Blink + * Blinks the board default led + */ + +use intfs.ports; +use intfs.mcu; +use intfs.display; +use intfs.databus; + +use math.random16; + +use graphic.canvas8; + +type globals { + mmcu = mcu(); + led = digitalport(); + oled = display(); + dbus = databus(); +} + +int16 main() { + gg = globals(); + mmcu = gg.mmcu; + led = gg.led; + + // blink led 10 times + led.mode(port_mode.output); + count = int16(10); + while count > 0 { + led.set(true); + mmcu.wait_ms(50); + led.set(false); + mmcu.wait_ms(50); + count--; + } + + // setup data bus + dbus = gg.dbus; + dbus.setup(0); + dbus.enable(); + + // init display + oled = gg.oled; + oled.set_address(0x78); + oled.init_display(); + oled.clear(); + + // This canvas will write in the display buffer. + // That is done through injection (see specs folder) + canvas = canvas8(); + + col = 0u; + row = 0u; + count = 1000; + loop { + // set a random pixel + col = uint8(random16()%(canvas.width()-1)); + row = uint8(random16()%(canvas.height()-1)); + canvas.set_pixel(row, col); + + // update display + oled.update_frame(); + + // clear the screen sometimes + count--; + if count == 0 { + canvas.clear(); + count = 1000; + } + } +} diff --git a/platformio/examples/ssd1306/teste b/platformio/examples/ssd1306/teste new file mode 100644 index 0000000000000000000000000000000000000000..a08bf9d17d22896e21f3b90f6f3763fcf611697f GIT binary patch literal 23192 zcmcg!3t*MSl|DBKa1&7=fToC;Af-Sd~OA8{jbX8u`LVa|jphas}YJEhpG(_0O$Kswdb7pd8xHo})O?&5czWKg0 zXXc;(zkjYQA3tS6AP@kP0x$^LS^!CD%F-!I6@#EVVjFkIY>%7p)!)v2m0Z;LydJq@ z$Bz2u-LczmXpLLjbwZDD{e<9z-U>4~eE-g%sy#XOYj588@$t^}JMSOc>$M@_vFArJfvT#BIvy&9$+|^#*)Qwa|BW%Rlb066hZC;a{}Ci2*S-WTsn#uKQe6Rr znx^`QO2s$7rE7pjCxrW-f$2q`-jI>ttYd!BD9@+9=u->?!YOB_5~V#+j-Kys)?{2EKYLvj7f5Lyh3%xifrh}Ds{GjW zKz*PA{m3^n((3`q`&;e?sf&K+bt}rqkPW3AX@9IVpOZ;bu&}F zeny|hP`rW-pyEYkXB+_-FB%U;ZoFV{5Tj~F!@ih0WEh&zkl6XNW0cQPKE=#!QLUEO zPkpGijNUUv*E)Mb#v@ui+M39IIo8aQ;x7ATJ-=w=Mf(vGWpDgX{J^VrAzmd*Fe)`8 z(4&zl^+hljLiM4*BI&QJPi;vG{0{d`fcAK9OdPESUcdV;2_NnAX#BEoo;hx6f3>xb zRqdIxpBJ7y`kq)1!<7);5An!HBUg?cgp9h@N z{;%h{VrMY?8U#;V5`Ll2gFIKN(Ojvdxl$?Ts_%7bX3o8io)2!Hgi(y6dm)~wop5F1 z@Ko$X&kT6l@`;zFw2Z&Dwf%zoUq2+@lKJ?LKrZ9+_3K>iqPgi1nlOCdndkmE8^)2@Y1^D3)rOX`M|XF}(M zE;j@rKISs$7U&-65z{Ns8?J~=3VbclKQPd+5Tj0if0?NP#KGyW+FAgy_`hjA+#a{p z1>zig7iq@Pm%#S!vg;DrKzld1+p%}^>^)(;WAEwNuYm53{R+?C2matt_VMgj!IO^t zD$kw_3mtp1XTJtUJN9cl`#|`X6Q6;eeK4GJ{2%Puhr(9JKGd@hhg!!z9InH5Ti0+8 zp9u+VMzm$Z>*#-1i^{Y$s>H$w*yPM_1l)z~phb^otGW8dl7cSAqNzT30!fuTd?|Sz4;RDD2_dRz0es-qE+(cAp z5|60lO1y{%wO_@Te>9x#tclPC#)wB&vJdTq87FG5=xkd0x$6zjUWskuBWxl*53hCj zyTNkgC%g8qC*)y++C-ZOSHO6zP#dR#?LH8HsczGI$3(aa9%g>sPKE`}_-mlT89xv* zo$-U=pfi3b4Ci?DQvAc=SL8UR0r=?wT>~HUcs-v?_zm`xf3!x4_`LXYbcEVCO>B>X z1>Dy28v|>&ov7^j@F4rE+XYY_tH;wbW+F_4fAHe@bsn$vu7_Xpc-@`~iO%?&;0*^q z3o_ZR@w4F%JYM^U&s&bacfeT(AA;=;e=)q~*yqCK0~!1 zhiQ)go8WTx7sG_(H^X|T{Ui)!|FwN9e8_F>?>5-t_`4mha@sqgAN!}r?}i7tt;g?y zAG5#O{w(xne|38=e2uRU9EScKfccJphv0LPP|`%FC70GA?&n|!d;HP zZ$PW#@0)PS@%L@0aQuA-UgP-oQ~tgS3-P?8_0#itAC7Q)tg<&jA8ymTghV(ATb=!Q z3YPGG)bTnE|H<*t`|&J%#`Dwrp%unBdSAd3j@~&q&HP#~5V#VZBmeaNj|=>c<5!QJ ziFm#v91?b5M(Jr?48h6Jd6Do8Kwm0%0T5pTK5os#vfnQ-qh#>tyy8KeN~Rw>FNz1( zLh+!k!$XtDGz9m8DsfF!Nt41fghZ(9#U%v~(~u-C@wEg&i(cS1PKu~(`)YlD*mi%$ zeVxm1a5(>;48_h)m-U+afl%k5EI{vDUsahcEMI4;L?Ig!iB zTwc%R4P4&H^LmUCIjP+8uA3Uf6V1(F8`U!r}Td9hmT>-e%cE7B!Slp_S3VH-B;VNGqt*;EH!`n z4XGt{rNwor_*SttwWhW_Gvm(mku_DNBbQW{)|M28s;fgw+r^e<%uByu@S;$4ZCZ!u zk@HJx3ri~&l+3Fwt*j`#v$DEyep%(*P+3iCdHK9W+8yO^he$$2bbqAfuR*C&25HiW zCNESKi^|Fhi%aL1)`rTe@TDyB8InlIP(`S$a(?^3{Apv;r_Y!Ep%~j+-#C zUChL3lW(jmys_W{K$F`CDYbTKCTE~Of_o6O_-8DW0J$7mi_#0Zy^o2JJthH$mIGdYQNJPLqVJ|J;NCn0Wz**$c*Xf z9ka9x;R{V{XElTKyFCZx(Gm4hm=~&89IDCn$!yPI3vTJMjL8Yv#g|e zWHgM47R5Xo<~(2V;Es6ODxmO{aGtNxhDu+fVWh9oFouWjAS0KAN^1)j)kO5wkhO<# z$S^v13#l!su3l6{H>~z)FAVJnC{N1Ur?nWmDnhlj)unS6)t1yiggYb$K2>j$c4I&f z0_gCfs&-N8g6bHiuc(f3O0*WA6bfsrLlre4^%QUc4qVg_cIKkSkYgnk#TVz+#SG9+ zUC4;?P-%q@i8@}|no$l#aviUX!m8@Z+RAyAWgUm}g3;RP4&mlfDjZlMBo}=dPggl+sFb4ysXRyJ*(%Rcd8W!UFh?a-S6Obh8l>_Z zm1nCwOXZm=&ro@~%2k$|r3R@yN9EZn&r*4&$}=!WCEZW(+)On{?`0g-PK=dh*i{H!G7b$)# zz4`7C@#`k|LSFoa;^aw(FqDjcw|jhz!av%sCVoqCVlsYN*od_M79mc??}Uh7Pr-MK z=CkoDVE+h1$@n+J<7*QB^=2H+Yb1`B{!PJ#*^81dP2;TYOl;HmD+q+i=u*7oJX*y( z=ykt|%XKJ%P^&cu8-_#jWow+(En;1Ie=Bk6h?BbXhY_`Ih({N!ZY*vdsT;-y{yD`a zfle$5ni$|B$ebBp(YNP0W*SkLISU1_zUFBUL-Gy$7&@IOC z_wAsH+4*i_-NByj)rgb2gM{u7q5GV-zFVT`?)27o8|x1B zbbs!xZ<^2@CUgg5Ad$kZ=`L*WpV<_niSyU7BIl7S_=XF#@o3{Yc}iZV=n#&nQM3+#}d8b;Ck;G-8czv8US|+mY^Dw`!c#O~y9qj`4JF#(t?= zC3NY}sYdsH&1ctR5VrZx$BNO+W0}TT-O<=4-F#2C4*R8UozNXCbk|~BWtyBu*+w_fOu7rOKD!BOfKF(1>}{W1@6lCMGVO%!~SG@tb^%zT8QWa3xg z@vRellNm?xyc)+#|EjPZ>H6rcaaNbshsIxzA4*2I2lmT(Y!tdv7)Rrt)^WD`;Jzrj zPidUhUB|jpNfeXO-HbS?yGiKY$T-sN>aE8{<|8gjhA-&FZ;Rl&iE+et633&o^=}jN z5r&fC`w;u3e>()<48{>(qvo@5q4Ocqdi+M?tnMys)A(8Vp=5LqV!zbgBXn-+rM>KYJh?>Avpm1Db!NbLb^+ADm#_+mM5j(LL<# zgCjzB4&zAob5FM^if*%~+seA;JBZQ!#M5mQy7Y4nGvB{@ai%Yyk=FNpFV3`Y$?p(; zC>h;9VZU78<3e{X<7nJg&1d&jFXkgIN`~(VjkD|9mvO}!W^s>VztlY;bW50zbYIqd zR(AllBhB}q##!AoY}5Gpp6*`km%2?tH!O7T*L+qt7u%8UtIIUb>e9JMx(htrI_#Ia z%|iDsp_`BU1Gj?Jox*%fXX7_QM4SxY6pgd#jx& zB{SxE#7W&rLU#@0NO!cSyCaHjhNruWbsr#6Ohz}=)14-Czt1?*9fO&i?{i2%zx_7J z@MUS7o$ndeUC%&+OGBKT?`)y_1H=-Jbo=1@I;s058gPkhGJM@N&gus7Jpqm1z(|AZ zia4oTBy{O#mPU7z7NYdA3?qh=Ay#zrE8p>@0YCmIAaZN7`Ekn z>xAx)n2&V7g#)B+9G>gcZ<685(>SZ!m2sOGXmF#kB6aJ9?vD{mIO6Z_os+$g4<8w9 zGJKuAb25o_H#5@UV!U&*LFoPju|{{br<)u__g+tT0P8;K>E7e%t`oXX3EhDh6dC8C zQFQxioQ-oD>u&XQlMsjhhdl1zD0Ke?`^ z>gjG0x<3=T|D?}9t6LC7ccaEx-ASyw-P7IRos(OH?hc`Qg{M0$iteSJ?o8I*>FLIM zx;upKGeS2BH?>^fImj1jKVPPCcD_ZdyW7)EK%89PJwo>vLU*mFOYgVMS`nqGuk>`w zSa*-7yWG>=FLZw;bRYH3$=WFMUGJTfb*%fWr@PiWCyxl-=Y(!ItjjppN72P&k#IK7 z_p$C?PnWo4oEwGiKD1H%FeK0u38n5D=0lT8CeHC1XLUC)?tq8uggB{tT<9J|tkDg5 z=hb6T=6j2GUTtFCL!Ryo@4Px8bbl>$-|}>~MA2>ZbhokYVNdsEPq#_v9ud0V!Jx=E z?~0;(kH*8{AUVp7qYFm!s&O^vgw0bkDHvn*_pSaPN7#NkaE6#*uE5cTRp8WxoIJos;y#2pa!3ekd8;x4d&QS?K{o?sm5zKjE;ZZG6Rs7;3NpvGC< zEY^LOkp{OHD^fR2=>8e8gd^R%aJA=}U+U%x-4BHBLCt6P z^CWDKWiBerJoadu)m?*a^1F$#2Dc0QrEZ?k{fPN!9K}`6cLTPwn2QR-m!NT0m;O6b z8h?_p2G<$;rS2r5`w8>WxXrkKrEVjRi}c>?VU4r8Cs_BCr~5<1N!@8e_pd^CA-?C5 zx=qMud?!j%FGrl@n=SZG3%)6u&-(WX`$rf`hHsL`S0wm8WgNxjZ~DG(_rV$DyPSwP z8NR=0oYn1$gK7L(5BCw`BviZ>bt*=R1^jzwmU2AWqJ=PUwCqbRYI~>3v6}>+SoVZXN5M z^K@5xy7fZ$E1`SR+xPXz7wLNYleh18v99?SHB6lU= 0) { - i--; - } -} diff --git a/platformio/platform/boards/stm32f1.json b/platformio/platform/boards/stm32f1.json index 0c98976..36e00db 100644 --- a/platformio/platform/boards/stm32f1.json +++ b/platformio/platform/boards/stm32f1.json @@ -1,5 +1,6 @@ { "build": { + "core": "stm32", "cpu": "cortex-m3", "f_cpu": "72000000L", "hwids": [ @@ -12,7 +13,7 @@ "0x0004" ] ], - "mcu": "stm32f103c8t6", + "mcu": "stm32f103cbt6", "product_line": "STM32F103xB", "variant": "PILL_F103XX" }, @@ -28,8 +29,7 @@ "openocd_target": "stm32f1x", "svd_path": "STM32F103xx.svd" }, - "frameworks": [ - ], + "frameworks": [], "name": "BluePill F103C8 (128k)", "upload": { "maximum_ram_size": 20480, @@ -37,12 +37,10 @@ "protocol": "stlink", "protocols": [ "jlink", - "cmsis-dap", "stlink", - "blackmagic", - "dfu" + "serial" ] }, "url": "http://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32f1-series/stm32f103/stm32f103c8.html", "vendor": "Generic" -} +} \ No newline at end of file diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 85b6e01..14c7c4c 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -7,6 +7,16 @@ from os.path import join from SCons.Script import AlwaysBuild, Builder, Default, DefaultEnvironment, Glob +from platformio.util import get_serial_ports + + +def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 + env.AutodetectUploadPort() + upload_options = {} + if "BOARD" in env: + upload_options = env.BoardConfig().get("upload", {}) + + env = DefaultEnvironment() platform = env.PioPlatform() ldscripts_folder = join(platform.get_package_dir("toolchain-robcmp"), "lib") @@ -20,29 +30,43 @@ ) sources = [] +auxsources = [] board = env.subst("$BOARD") mcu = env.subst("$BOARD_MCU") -ldflags = ["-nostdlib", "-entry=main", "-L", ldscripts_folder, "-Bstatic"] -if mcu == "stm32f1": +try: + hardware_spec = env.GetProjectOption("board_hardware_spec") +except: + hardware_spec = None + pass + +ldflags = ["-nostdlib", "-entry=main", "-L", stdlib_folder, "-Bstatic"] +if mcu.startswith("stm32f1"): ldflags.append("-Tstm32f1.ld") + auxsources += Glob(join(stdlib_folder, "stm32f1.rob")) elif mcu == "atmega328p": ldflags.append("-Tavr328p.ld") - ldflags.append(join(ldscripts_folder, "avr5.o")) - sources += Glob(join(ldscripts_folder, "avr328p.rob")) + ldflags.append(join(stdlib_folder, "avr5.o")) + auxsources += Glob(join(stdlib_folder, "avr328p.rob")) else: sys.stderr.write("The requested mcu is not supported.\n") env.Exit(1) +ldflags.append("--gc-sections") +ldflags.append("--lto=thin") + build_type = env.subst("$BUILD_TYPE") -robcmp_args = ["robcmp", "-bdep", "-a", board, "-o", "$TARGET"] +robcmp_args = ["robcmp", "-a", board, "-o", "$TARGET"] + if build_type == "debug": robcmp_args.append("-g") robcmp_args.append("-O0") elif build_type == "release": - robcmp_args.append("-O3") -ldflags.append("--gc-sections") -ldflags.append("--lto=thin") + robcmp_args.append("-Oz") + +hardware_spec_args = [] +if hardware_spec: + hardware_spec_args = ["-s", hardware_spec] robcmp_args.append("-I") robcmp_args.append(stdlib_folder) @@ -70,6 +94,11 @@ action = ' '.join(robcmp_args), suffix = '.o', src_suffix = '.rob', + ), + RobDep=Builder( + action = ' '.join(robcmp_args + hardware_spec_args + ["-bdep"]), + suffix = '.o', + src_suffix = '.rob', ) ) ) @@ -80,6 +109,8 @@ target_objs = [] for f in sources: + target_objs += env.RobDep(join("$BUILD_DIR", f.name + ".o"), f) +for f in auxsources: target_objs += env.Rob(join("$BUILD_DIR", f.name + ".o"), f) target_elf = env.Linker(join("$BUILD_DIR", "firmware"), target_objs) @@ -92,11 +123,11 @@ if upload_protocol == "serial": upload_actions.append(env.VerboseAction(env.AutodetectUploadPort, "Looking for upload port...")) - if mcu == "stm32f1": + if mcu.startswith("stm32"): stm32flash_bin = join(platform.get_package_dir("tool-stm32duino"), "stm32flash") env.Replace( UPLOADER=join(stm32flash_bin, "stm32flash"), - UPLOADERFLAGS=["-g", "0x08000000", "-b", "115200", "-w"], + UPLOADERFLAGS=["-b", "115200", "-w"], UPLOADCMD='$UPLOADER $UPLOADERFLAGS "$SOURCE" $UPLOAD_PORT' ) @@ -114,13 +145,13 @@ env.Exit(1) elif upload_protocol == "stlink": - if mcu == "stm32f1": + if mcu.startswith("stm32f1"): openocd_folder = platform.get_package_dir("tool-openocd") env.Replace( UPLOADER=join(openocd_folder, "bin", "openocd"), UPLOADERFLAGS=["-f", join(openocd_folder, "scripts/interface/stlink.cfg"), "-f", join(openocd_folder, "scripts/target/stm32f1x.cfg"), - "-c", "program $SOURCE reset 0x08000000 exit"], + "-c", "program $SOURCE reset exit"], UPLOADCMD="$UPLOADER $UPLOADERFLAGS" ) @@ -134,7 +165,11 @@ upload_actions.append(env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")) -upload = env.Alias(["upload"], target_bin, upload_actions) +upload = None +if mcu.startswith("stm32f1"): + upload = env.Alias(["upload"], target_elf, upload_actions) +else: + upload = env.Alias(["upload"], target_bin, upload_actions) AlwaysBuild(upload) # SIZE diff --git a/platformio/platform/platform.py b/platformio/platform/platform.py index d5a6a11..08d3b5e 100644 --- a/platformio/platform/platform.py +++ b/platformio/platform/platform.py @@ -15,10 +15,10 @@ def configure_default_packages(self, variables, targets): if upload_protocol == "serial": if board == "avr328p": required_tool = "tool-avrdude" - elif board == "stm32f1": + elif board.startswith("stm32f1"): required_tool = "tool-stm32duino" elif upload_protocol == "stlink": - if board == "stm32f1": + if board.startswith("stm32f1"): required_tool = "tool-openocd" if required_tool: @@ -62,5 +62,33 @@ def _add_default_debug_tools(self, board): "-g" ] + # J-Link, ST-Link + upload_protocols = board.manifest.get("upload", {}).get("protocols", []) + for link in ("jlink", "stlink"): + if link not in upload_protocols or link in debug["tools"]: + continue + + server_args = ["-s", "$PACKAGE_DIR/scripts"] + assert debug.get("openocd_target"), ( + "Missed target configuration for %s" % board.id) + server_args.extend([ + "-f", "interface/%s.cfg" % link, + "-c", "transport select %s" % ( + "hla_swd" if link == "stlink" else "swd"), + "-f", "target/%s.cfg" % debug.get("openocd_target") + ]) + server_args.extend(debug.get("openocd_extra_args", [])) + + debug["tools"][link] = { + "server": { + "package": "tool-openocd", + "executable": "bin/openocd", + "arguments": server_args + } + } + + debug["tools"][link]["onboard"] = link in debug.get("onboard_tools", []) + debug["tools"][link]["default"] = link in debug.get("default_tools", []) + board.manifest["debug"] = debug return board diff --git a/platformio/toolchain-robcmp/Makefile b/platformio/toolchain-robcmp/Makefile index 1d72ca9..fec367d 100644 --- a/platformio/toolchain-robcmp/Makefile +++ b/platformio/toolchain-robcmp/Makefile @@ -41,8 +41,8 @@ TOOLS=$(LLVM_OBJCOPY) \ $(LLVM_SIZE) \ $(AVR_GDB) \ $(AVR_OBJDUMP) \ - ../../build/robcmp \ - ../../build/robcmp-simavr-debug + $(abspath ../../build/robcmp) \ + $(abspath ../../build/robcmp-simavr-debug) ifeq ($(OS),Windows_NT) uname_S := Windows @@ -61,7 +61,7 @@ ifeq ($(uname_S), Linux) LIBS=$(shell ./libllvmpath.sh ${LLVM_LD}) endif -LIBS += ../../lib/*.ld ../../lib/*.o ../../lib/*.rob +#LIBS += ../../lib/*.ld ../../lib/*.o ../../lib/*.rob version=$(shell cat version) @@ -77,11 +77,11 @@ package.json: package-orig.json $(SED) s/sed_system_here/$(suffix)/ $< > $@ ../toolchain-robcmp-${suffix}-${version}.tar.gz: package.json - for f in $(TOOLS); do cp $$f bin; done; - for f in $(LIBS); do cp $$f lib; done; + ln -sf $(TOOLS) bin + ln -sf $(LIBS) lib if [ -f bin/ld.lld-18 ]; then cd bin && ln -s ld.lld-18 ld.lld; fi if [ -f bin/llvm-objcopy-18 ]; then cd bin && ln -s llvm-objcopy-18 llvm-objcopy; fi - tar cfz $@ $^ bin lib + tar chfz $@ $^ bin lib clean: rm -rf bin lib *.tar.gz package.json diff --git a/platformio/toolchain-robcmp/stdlib b/platformio/toolchain-robcmp/stdlib new file mode 120000 index 0000000..a3fadee --- /dev/null +++ b/platformio/toolchain-robcmp/stdlib @@ -0,0 +1 @@ +/Users/thborges/projects/robcmp/lib \ No newline at end of file diff --git a/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix b/platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix index 22e1499a31014744cd64f9834a075963e7966821..d6afee5537b4c381a795bf451eb7b6ab9167cb5c 100644 GIT binary patch delta 1195 zcmV;c1XTNi8jKnjP)h>@6aWAS2msYq(O968T%p4P007yM7cYNS8LEo@7#dV)>H4_J zv9G}+u_K>DVSoKDNePsyTWP1hAjdv`zIQ&~8Gf?NvtR)ZwKe^)7afKH7-^L@X+JFe zUH5Z%GWc-7r$Wv}3KL=U9iR_x)?1FE!)g;@4EDpB_r)<|C})rhjB+iVMSJHXX>+Dv z0hukpu>~%>jSYW0I_&ixwjZlk0J;iLr>5bMrw4ojUMS&3^>M&Q3XIo&6^w;ROA4VM zg6aNm&L%Q1aAmw$hMS-$q=>wlmPw{@25xN_2CSi;X)H3ax)M1IzT0G&7jezt zYm1J{3g8Z=B=$gHD;5PZXG;MXF> z0r}Q>7Sg%Bg{8l(Y?=`kAZd6HN%aY)ikPz+R3nGNLrQvpgQ>Hr6M0VBEe|={vZ!}l zii{Lj7g@!q&rEXmXtFY^O^Hb9^Xskc#H!B5q|Nq?#!_UlFO{~@&?<<|O{xu0jzm_{ z@%`*YpT2)o7mw`?S_gdw1sJ*=lDuiTZvj>{@?SvTv{5an)SY|l=JmDdP}W`n9$P6g z{To!9#HVgF#O?7>%`=V-(xc$xU{uDn=^fRQp+()V1qpiFKsRno5djX}?Hz z6feP}7tVuvS5@u5mdSf6#${1h=l76g8nLWW{04v3F$ib&(ER8?s2tvWo0{{brm?UN z)I_+sviBQDyer|AaSg4Z>hjUlX-WO8MP4|7kcf}n=4_`^@i9>h!l3P$Y&;sCU&ZH9 zt~gt-J~TScwjUurGIUk5Ols0}N zZxKW5hn*fh;b-(lwqX{{%OCwhONlsDiXJW$Nw$-Ymnc0+#>25a72TZe^OBskfl|62 z|34Z00Z>Z=1QY-O2nYbxR?)HpJOc#JR?%3KKn5v)Z^IxAh41|p5$BGyr)j?%RnXcze6qdJTA&^cKSow~e? zf>&(zF1*bJz?y7`7X2u|Xmzzm7iU*+!(x&}m}~ysK+tW7{`UqpM@vAQ|9#PJuVp11IE~j>D_0@s#s?Y~|yV z+=x`aWvx~bOfs0|??rwfG^CtMuJ3VpK#m1LAIUa-oIlasb?KT?OI3Rs6J=w$q&lm( z$o?OmSQqMe$KV{n52Guj%y$aO0rX6jtbJNY)03LkBkRf7!=fj@I0-U#8*z~{D_SO) z@IN`yNCQmYgs~?Lav=yRw#7pEUu8)$x+&zs!?2LmZS@0CO9u!l_6Q|B0RRA=v#AGN z0}a(y(O968T%p4P007yO6AL#3)mG7yO$!?W_X3j-0~M2h3n~HHld20+0iBcm3qb+l zlRpe0AJ10NSSt1iB|HHD0G02TlM00000000000HlF7lYb0D0=5T}$OkBs>@6aWAS2moYt&sd9eAj`i3007Pi000(~FAEuwG!lP?3{^#c z3=JwYx;_p$_BD7UcI0y??62P?DS=XTEA7-5MB=;8_s-`#ho7#pG+2T|ZA~xiM8{zO zMp~s!(hCcJ*Zv%y_CFl)iI5ACz*rc42k3*_jmt@NTsjfPU@x3|pLZEUIfqPOlxgWK z+B+Xfn=u7TNNo;|EpgSZZP$MC9Hp_Jiu8Ds%sF}2oT1N#T z_?A_}Z$yH9imml5q&1tt%Fjxh+3X(T@(E0tCTEp*#Tf_>35fvqC(b5LWElxI5aevf zqVl*BDaoua(~?nbl;rHu%hIeeB_h?#Z(N%f>#79fro^`z3z1HJp|p(#RzY-O5^aDA zBhrHQ>}MzX^rbv)>|lS;Ch2p?!O)SA6ivf@3$SdA{{s4^jcP!JZrxkAsLo1@s`d)- z$V!pw-=LZzJ`HpG^CIq)4y=}d(MX#GMpIijxvfswx=6j7Xg@FFs$u;+wvLop-98a5 z9hS+S;uU!G!g)~ds;d3hB7RTBX_4pF`2!@GMl8w_zd>~b!kK>qG(S2JDuXwlrh0#A zXe_M*H5P86?EN+n?+SQjUIS~WyL>cpTGBjgke3c1B;w<+Ioq35d_)w3&~IiY8x02+ z*VBtAQ=Dy99|j#~yEhLX8ak?JDz?LV_sxxi486q`DEmZvv zZq_;ceMD?-bGkq2grC#J*rb`)*M0O0EfwNSDY~st#OYo+UZV7*7!TX_RCK$y&r5RF zBueFa{87^X15ir?1QY-O2nYaVb5q)$$Q1zsP9khk2KuPG4T(E`y2I7g_sEyi| zY8=|$aR>C9f2jxr5!ngSX;eCq$h)SoPP(C027M!4i)4YDTMB}80XQM&bR1u0gNNMD z$5!1xs7;;fm+UoKz@~uN{$A`agqF1TDfP7-9+7=PFbKJJklQEvt1n$sYN_fDQ%5;i zF6rKBF1G)NSFa1TzhZC{2;=Aqsg`Pr^y%zCdR~iaLgqks3r&4-GGy#B;dSm+(=z#t z|H+?58Dah&i~|`^3q#b>l?dfumE|b$b90Lf<04j<)elfh2MChp@ar}K005S=vj<%R z4P= _stepInterval) - { - if (_direction == DIRECTION_CW) - { - // Clockwise - _currentPos += 1; - } - else - { - // Anticlockwise - _currentPos -= 1; - } - step(_currentPos); - - _lastStepTime = time; // Caution: does not account for costs in step() - - return true; - } - else - { - return false; - } -} - -long AccelStepper::distanceToGo() -{ - return _targetPos - _currentPos; -} - -long AccelStepper::targetPosition() -{ - return _targetPos; -} - -long AccelStepper::currentPosition() -{ - return _currentPos; -} - -// Useful during initialisations or after initial positioning -// Sets speed to 0 -void AccelStepper::setCurrentPosition(long position) -{ - _targetPos = _currentPos = position; - _n = 0; - _stepInterval = 0; - _speed = 0.0; -} - -void AccelStepper::computeNewSpeed() -{ - long distanceTo = distanceToGo(); // +ve is clockwise from curent location - - long stepsToStop = (long)((_speed * _speed) / (2.0 * _acceleration)); // Equation 16 - - if (distanceTo == 0 && stepsToStop <= 1) - { - // We are at the target and its time to stop - _stepInterval = 0; - _speed = 0.0; - _n = 0; - return; - } - - if (distanceTo > 0) - { - // We are anticlockwise from the target - // Need to go clockwise from here, maybe decelerate now - if (_n > 0) - { - // Currently accelerating, need to decel now? Or maybe going the wrong way? - if ((stepsToStop >= distanceTo) || _direction == DIRECTION_CCW) - _n = -stepsToStop; // Start deceleration - } - else if (_n < 0) - { - // Currently decelerating, need to accel again? - if ((stepsToStop < distanceTo) && _direction == DIRECTION_CW) - _n = -_n; // Start accceleration - } - } - else if (distanceTo < 0) - { - // We are clockwise from the target - // Need to go anticlockwise from here, maybe decelerate - if (_n > 0) - { - // Currently accelerating, need to decel now? Or maybe going the wrong way? - if ((stepsToStop >= -distanceTo) || _direction == DIRECTION_CW) - _n = -stepsToStop; // Start deceleration - } - else if (_n < 0) - { - // Currently decelerating, need to accel again? - if ((stepsToStop < -distanceTo) && _direction == DIRECTION_CCW) - _n = -_n; // Start accceleration - } - } - - // Need to accelerate or decelerate - if (_n == 0) - { - // First step from stopped - _cn = _c0; - _direction = (distanceTo > 0) ? DIRECTION_CW : DIRECTION_CCW; - } - else - { - // Subsequent step. Works for accel (n is +_ve) and decel (n is -ve). - _cn = _cn - ((2.0 * _cn) / ((4.0 * _n) + 1)); // Equation 13 - _cn = max(_cn, _cmin); - } - _n++; - _stepInterval = _cn; - _speed = 1000000.0 / _cn; - if (_direction == DIRECTION_CCW) - _speed = -_speed; - -#if 0 - Serial.println(_speed); - Serial.println(_acceleration); - Serial.println(_cn); - Serial.println(_c0); - Serial.println(_n); - Serial.println(_stepInterval); - Serial.println(distanceTo); - Serial.println(stepsToStop); - Serial.println("-----"); -#endif -} - -// Run the motor to implement speed and acceleration in order to proceed to the target position -// You must call this at least once per step, preferably in your main loop -// If the motor is in the desired position, the cost is very small -// returns true if the motor is still running to the target position. -boolean AccelStepper::run() -{ - if (runSpeed()) - computeNewSpeed(); - return _speed != 0.0 || distanceToGo() != 0; -} - -AccelStepper::AccelStepper(uint8_t interface, uint8_t pin1, uint8_t pin2, uint8_t pin3, uint8_t pin4, bool enable) -{ - _interface = interface; - _currentPos = 0; - _targetPos = 0; - _speed = 0.0; - _maxSpeed = 1.0; - _acceleration = 0.0; - _sqrt_twoa = 1.0; - _stepInterval = 0; - _minPulseWidth = 1; - _enablePin = 0xff; - _lastStepTime = 0; - _pin[0] = pin1; - _pin[1] = pin2; - _pin[2] = pin3; - _pin[3] = pin4; - _enableInverted = false; - - // NEW - _n = 0; - _c0 = 0.0; - _cn = 0.0; - _cmin = 1.0; - _direction = DIRECTION_CCW; - - int i; - for (i = 0; i < 4; i++) - _pinInverted[i] = 0; - if (enable) - enableOutputs(); - // Some reasonable default - setAcceleration(1); -} - -AccelStepper::AccelStepper(void (*forward)(), void (*backward)()) -{ - _interface = 0; - _currentPos = 0; - _targetPos = 0; - _speed = 0.0; - _maxSpeed = 1.0; - _acceleration = 0.0; - _sqrt_twoa = 1.0; - _stepInterval = 0; - _minPulseWidth = 1; - _enablePin = 0xff; - _lastStepTime = 0; - _pin[0] = 0; - _pin[1] = 0; - _pin[2] = 0; - _pin[3] = 0; - _forward = forward; - _backward = backward; - - // NEW - _n = 0; - _c0 = 0.0; - _cn = 0.0; - _cmin = 1.0; - _direction = DIRECTION_CCW; - - int i; - for (i = 0; i < 4; i++) - _pinInverted[i] = 0; - // Some reasonable default - setAcceleration(1); -} - -void AccelStepper::setMaxSpeed(float speed) -{ - if (speed < 0.0) - speed = -speed; - if (_maxSpeed != speed) - { - _maxSpeed = speed; - _cmin = 1000000.0 / speed; - // Recompute _n from current speed and adjust speed if accelerating or cruising - if (_n > 0) - { - _n = (long)((_speed * _speed) / (2.0 * _acceleration)); // Equation 16 - computeNewSpeed(); - } - } -} - -float AccelStepper::maxSpeed() -{ - return _maxSpeed; -} - -void AccelStepper::setAcceleration(float acceleration) -{ - if (acceleration == 0.0) - return; - if (acceleration < 0.0) - acceleration = -acceleration; - if (_acceleration != acceleration) - { - // Recompute _n per Equation 17 - _n = _n * (_acceleration / acceleration); - // New c0 per Equation 7, with correction per Equation 15 - _c0 = 0.676 * sqrt(2.0 / acceleration) * 1000000.0; // Equation 15 - _acceleration = acceleration; - computeNewSpeed(); - } -} - -void AccelStepper::setSpeed(float speed) -{ - if (speed == _speed) - return; - speed = constrain(speed, -_maxSpeed, _maxSpeed); - if (speed == 0.0) - _stepInterval = 0; - else - { - _stepInterval = fabs(1000000.0 / speed); - _direction = (speed > 0.0) ? DIRECTION_CW : DIRECTION_CCW; - } - _speed = speed; -} - -float AccelStepper::speed() -{ - return _speed; -} - -// Subclasses can override -void AccelStepper::step(long step) -{ - switch (_interface) - { - case FUNCTION: - step0(step); - break; - - case DRIVER: - step1(step); - break; - - case FULL2WIRE: - step2(step); - break; - - case FULL3WIRE: - step3(step); - break; - - case FULL4WIRE: - step4(step); - break; - - case HALF3WIRE: - step6(step); - break; - - case HALF4WIRE: - step8(step); - break; - } -} - -// You might want to override this to implement eg serial output -// bit 0 of the mask corresponds to _pin[0] -// bit 1 of the mask corresponds to _pin[1] -// .... -void AccelStepper::setOutputPins(uint8_t mask) -{ - uint8_t numpins = 2; - if (_interface == FULL4WIRE || _interface == HALF4WIRE) - numpins = 4; - else if (_interface == FULL3WIRE || _interface == HALF3WIRE) - numpins = 3; - uint8_t i; - for (i = 0; i < numpins; i++) - digitalWrite(_pin[i], (mask & (1 << i)) ? (HIGH ^ _pinInverted[i]) : (LOW ^ _pinInverted[i])); -} - -// 0 pin step function (ie for functional usage) -void AccelStepper::step0(long step) -{ - (void)(step); // Unused - if (_speed > 0) - _forward(); - else - _backward(); -} - -// 1 pin step function (ie for stepper drivers) -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step1(long step) -{ - (void)(step); // Unused - - // _pin[0] is step, _pin[1] is direction - setOutputPins(_direction ? 0b10 : 0b00); // Set direction first else get rogue pulses - setOutputPins(_direction ? 0b11 : 0b01); // step HIGH - // Caution 200ns setup time - // Delay the minimum allowed pulse width - delayMicroseconds(_minPulseWidth); - setOutputPins(_direction ? 0b10 : 0b00); // step LOW -} - - -// 2 pin step function -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step2(long step) -{ - switch (step & 0x3) - { - case 0: /* 01 */ - setOutputPins(0b10); - break; - - case 1: /* 11 */ - setOutputPins(0b11); - break; - - case 2: /* 10 */ - setOutputPins(0b01); - break; - - case 3: /* 00 */ - setOutputPins(0b00); - break; - } -} -// 3 pin step function -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step3(long step) -{ - switch (step % 3) - { - case 0: // 100 - setOutputPins(0b100); - break; - - case 1: // 001 - setOutputPins(0b001); - break; - - case 2: //010 - setOutputPins(0b010); - break; - - } -} - -// 4 pin step function for half stepper -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step4(long step) -{ - switch (step & 0x3) - { - case 0: // 1010 - setOutputPins(0b0101); - break; - - case 1: // 0110 - setOutputPins(0b0110); - break; - - case 2: //0101 - setOutputPins(0b1010); - break; - - case 3: //1001 - setOutputPins(0b1001); - break; - } -} - -// 3 pin half step function -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step6(long step) -{ - switch (step % 6) - { - case 0: // 100 - setOutputPins(0b100); - break; - - case 1: // 101 - setOutputPins(0b101); - break; - - case 2: // 001 - setOutputPins(0b001); - break; - - case 3: // 011 - setOutputPins(0b011); - break; - - case 4: // 010 - setOutputPins(0b010); - break; - - case 5: // 011 - setOutputPins(0b110); - break; - - } -} - -// 4 pin half step function -// This is passed the current step number (0 to 7) -// Subclasses can override -void AccelStepper::step8(long step) -{ - switch (step & 0x7) - { - case 0: // 1000 - setOutputPins(0b0001); - break; - - case 1: // 1010 - setOutputPins(0b0101); - break; - - case 2: // 0010 - setOutputPins(0b0100); - break; - - case 3: // 0110 - setOutputPins(0b0110); - break; - - case 4: // 0100 - setOutputPins(0b0010); - break; - - case 5: //0101 - setOutputPins(0b1010); - break; - - case 6: // 0001 - setOutputPins(0b1000); - break; - - case 7: //1001 - setOutputPins(0b1001); - break; - } -} - -// Prevents power consumption on the outputs -void AccelStepper::disableOutputs() -{ - if (! _interface) return; - - setOutputPins(0); // Handles inversion automatically - if (_enablePin != 0xff) - { - pinMode(_enablePin, OUTPUT); - digitalWrite(_enablePin, LOW ^ _enableInverted); - } -} - -void AccelStepper::enableOutputs() -{ - if (! _interface) - return; - - pinMode(_pin[0], OUTPUT); - pinMode(_pin[1], OUTPUT); - if (_interface == FULL4WIRE || _interface == HALF4WIRE) - { - pinMode(_pin[2], OUTPUT); - pinMode(_pin[3], OUTPUT); - } - else if (_interface == FULL3WIRE || _interface == HALF3WIRE) - { - pinMode(_pin[2], OUTPUT); - } - - if (_enablePin != 0xff) - { - pinMode(_enablePin, OUTPUT); - digitalWrite(_enablePin, HIGH ^ _enableInverted); - } -} - -void AccelStepper::setMinPulseWidth(unsigned int minWidth) -{ - _minPulseWidth = minWidth; -} - -void AccelStepper::setEnablePin(uint8_t enablePin) -{ - _enablePin = enablePin; - - // This happens after construction, so init pin now. - if (_enablePin != 0xff) - { - pinMode(_enablePin, OUTPUT); - digitalWrite(_enablePin, HIGH ^ _enableInverted); - } -} - -void AccelStepper::setPinsInverted(bool directionInvert, bool stepInvert, bool enableInvert) -{ - _pinInverted[0] = stepInvert; - _pinInverted[1] = directionInvert; - _enableInverted = enableInvert; -} - -void AccelStepper::setPinsInverted(bool pin1Invert, bool pin2Invert, bool pin3Invert, bool pin4Invert, bool enableInvert) -{ - _pinInverted[0] = pin1Invert; - _pinInverted[1] = pin2Invert; - _pinInverted[2] = pin3Invert; - _pinInverted[3] = pin4Invert; - _enableInverted = enableInvert; -} - -// Blocks until the target position is reached and stopped -void AccelStepper::runToPosition() -{ - while (run()) - ; -} - -boolean AccelStepper::runSpeedToPosition() -{ - if (_targetPos == _currentPos) - return false; - if (_targetPos >_currentPos) - _direction = DIRECTION_CW; - else - _direction = DIRECTION_CCW; - return runSpeed(); -} - -// Blocks until the new target position is reached -void AccelStepper::runToNewPosition(long position) -{ - moveTo(position); - runToPosition(); -} - -void AccelStepper::stop() -{ - if (_speed != 0.0) - { - long stepsToStop = (long)((_speed * _speed) / (2.0 * _acceleration)) + 1; // Equation 16 (+integer rounding) - if (_speed > 0) - move(stepsToStop); - else - move(-stepsToStop); - } -} - -bool AccelStepper::isRunning() -{ - return !(_speed == 0.0 && _targetPos == _currentPos); -} diff --git a/src/2018arm/AccelStepper.h b/src/2018arm/AccelStepper.h deleted file mode 100644 index 84c738c..0000000 --- a/src/2018arm/AccelStepper.h +++ /dev/null @@ -1,730 +0,0 @@ -// AccelStepper.h -// -/// \mainpage AccelStepper library for Arduino -/// -/// This is the Arduino AccelStepper library. -/// It provides an object-oriented interface for 2, 3 or 4 pin stepper motors and motor drivers. -/// -/// The standard Arduino IDE includes the Stepper library -/// (http://arduino.cc/en/Reference/Stepper) for stepper motors. It is -/// perfectly adequate for simple, single motor applications. -/// -/// AccelStepper significantly improves on the standard Arduino Stepper library in several ways: -/// \li Supports acceleration and deceleration -/// \li Supports multiple simultaneous steppers, with independent concurrent stepping on each stepper -/// \li API functions never delay() or block -/// \li Supports 2, 3 and 4 wire steppers, plus 3 and 4 wire half steppers. -/// \li Supports alternate stepping functions to enable support of AFMotor (https://github.com/adafruit/Adafruit-Motor-Shield-library) -/// \li Supports stepper drivers such as the Sparkfun EasyDriver (based on 3967 driver chip) -/// \li Very slow speeds are supported -/// \li Extensive API -/// \li Subclass support -/// -/// The latest version of this documentation can be downloaded from -/// http://www.airspayce.com/mikem/arduino/AccelStepper -/// The version of the package that this documentation refers to can be downloaded -/// from http://www.airspayce.com/mikem/arduino/AccelStepper/AccelStepper-1.58.zip -/// -/// Example Arduino programs are included to show the main modes of use. -/// -/// You can also find online help and discussion at http://groups.google.com/group/accelstepper -/// Please use that group for all questions and discussions on this topic. -/// Do not contact the author directly, unless it is to discuss commercial licensing. -/// Before asking a question or reporting a bug, please read -/// - http://en.wikipedia.org/wiki/Wikipedia:Reference_desk/How_to_ask_a_software_question -/// - http://www.catb.org/esr/faqs/smart-questions.html -/// - http://www.chiark.greenend.org.uk/~shgtatham/bugs.html -/// -/// Tested on Arduino Diecimila and Mega with arduino-0018 & arduino-0021 -/// on OpenSuSE 11.1 and avr-libc-1.6.1-1.15, -/// cross-avr-binutils-2.19-9.1, cross-avr-gcc-4.1.3_20080612-26.5. -/// Tested on Teensy http://www.pjrc.com/teensy including Teensy 3.1 built using Arduino IDE 1.0.5 with -/// teensyduino addon 1.18 and later. -/// -/// \par Installation -/// -/// Install in the usual way: unzip the distribution zip file to the libraries -/// sub-folder of your sketchbook. -/// -/// \par Theory -/// -/// This code uses speed calculations as described in -/// "Generate stepper-motor speed profiles in real time" by David Austin -/// http://fab.cba.mit.edu/classes/MIT/961.09/projects/i0/Stepper_Motor_Speed_Profile.pdf or -/// http://www.embedded.com/design/mcus-processors-and-socs/4006438/Generate-stepper-motor-speed-profiles-in-real-time or -/// http://web.archive.org/web/20140705143928/http://fab.cba.mit.edu/classes/MIT/961.09/projects/i0/Stepper_Motor_Speed_Profile.pdf -/// with the exception that AccelStepper uses steps per second rather than radians per second -/// (because we dont know the step angle of the motor) -/// An initial step interval is calculated for the first step, based on the desired acceleration -/// On subsequent steps, shorter step intervals are calculated based -/// on the previous step until max speed is achieved. -/// -/// \par Adafruit Motor Shield V2 -/// -/// The included examples AFMotor_* are for Adafruit Motor Shield V1 and do not work with Adafruit Motor Shield V2. -/// See https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library for examples that work with Adafruit Motor Shield V2. -/// -/// \par Donations -/// -/// This library is offered under a free GPL license for those who want to use it that way. -/// We try hard to keep it up to date, fix bugs -/// and to provide free support. If this library has helped you save time or money, please consider donating at -/// http://www.airspayce.com or here: -/// -/// \htmlonly
\endhtmlonly -/// -/// \par Trademarks -/// -/// AccelStepper is a trademark of AirSpayce Pty Ltd. The AccelStepper mark was first used on April 26 2010 for -/// international trade, and is used only in relation to motor control hardware and software. -/// It is not to be confused with any other similar marks covering other goods and services. -/// -/// \par Copyright -/// -/// This software is Copyright (C) 2010 Mike McCauley. Use is subject to license -/// conditions. The main licensing options available are GPL V2 or Commercial: -/// -/// \par Open Source Licensing GPL V2 -/// This is the appropriate option if you want to share the source code of your -/// application with everyone you distribute it to, and you also want to give them -/// the right to share who uses it. If you wish to use this software under Open -/// Source Licensing, you must contribute all your source code to the open source -/// community in accordance with the GPL Version 2 when your application is -/// distributed. See https://www.gnu.org/licenses/gpl-2.0.html -/// -/// \par Commercial Licensing -/// This is the appropriate option if you are creating proprietary applications -/// and you are not prepared to distribute and share the source code of your -/// application. Purchase commercial licenses at http://airspayce.binpress.com/ -/// -/// \par Revision History -/// \version 1.0 Initial release -/// -/// \version 1.1 Added speed() function to get the current speed. -/// \version 1.2 Added runSpeedToPosition() submitted by Gunnar Arndt. -/// \version 1.3 Added support for stepper drivers (ie with Step and Direction inputs) with _pins == 1 -/// \version 1.4 Added functional contructor to support AFMotor, contributed by Limor, with example sketches. -/// \version 1.5 Improvements contributed by Peter Mousley: Use of microsecond steps and other speed improvements -/// to increase max stepping speed to about 4kHz. New option for user to set the min allowed pulse width. -/// Added checks for already running at max speed and skip further calcs if so. -/// \version 1.6 Fixed a problem with wrapping of microsecond stepping that could cause stepping to hang. -/// Reported by Sandy Noble. -/// Removed redundant _lastRunTime member. -/// \version 1.7 Fixed a bug where setCurrentPosition() did not always work as expected. -/// Reported by Peter Linhart. -/// \version 1.8 Added support for 4 pin half-steppers, requested by Harvey Moon -/// \version 1.9 setCurrentPosition() now also sets motor speed to 0. -/// \version 1.10 Builds on Arduino 1.0 -/// \version 1.11 Improvments from Michael Ellison: -/// Added optional enable line support for stepper drivers -/// Added inversion for step/direction/enable lines for stepper drivers -/// \version 1.12 Announce Google Group -/// \version 1.13 Improvements to speed calculation. Cost of calculation is now less in the worst case, -/// and more or less constant in all cases. This should result in slightly beter high speed performance, and -/// reduce anomalous speed glitches when other steppers are accelerating. -/// However, its hard to see how to replace the sqrt() required at the very first step from 0 speed. -/// \version 1.14 Fixed a problem with compiling under arduino 0021 reported by EmbeddedMan -/// \version 1.15 Fixed a problem with runSpeedToPosition which did not correctly handle -/// running backwards to a smaller target position. Added examples -/// \version 1.16 Fixed some cases in the code where abs() was used instead of fabs(). -/// \version 1.17 Added example ProportionalControl -/// \version 1.18 Fixed a problem: If one calls the funcion runSpeed() when Speed is zero, it makes steps -/// without counting. reported by Friedrich, Klappenbach. -/// \version 1.19 Added MotorInterfaceType and symbolic names for the number of pins to use -/// for the motor interface. Updated examples to suit. -/// Replaced individual pin assignment variables _pin1, _pin2 etc with array _pin[4]. -/// _pins member changed to _interface. -/// Added _pinInverted array to simplify pin inversion operations. -/// Added new function setOutputPins() which sets the motor output pins. -/// It can be overridden in order to provide, say, serial output instead of parallel output -/// Some refactoring and code size reduction. -/// \version 1.20 Improved documentation and examples to show need for correctly -/// specifying AccelStepper::FULL4WIRE and friends. -/// \version 1.21 Fixed a problem where desiredSpeed could compute the wrong step acceleration -/// when _speed was small but non-zero. Reported by Brian Schmalz. -/// Precompute sqrt_twoa to improve performance and max possible stepping speed -/// \version 1.22 Added Bounce.pde example -/// Fixed a problem where calling moveTo(), setMaxSpeed(), setAcceleration() more -/// frequently than the step time, even -/// with the same values, would interfere with speed calcs. Now a new speed is computed -/// only if there was a change in the set value. Reported by Brian Schmalz. -/// \version 1.23 Rewrite of the speed algorithms in line with -/// http://fab.cba.mit.edu/classes/MIT/961.09/projects/i0/Stepper_Motor_Speed_Profile.pdf -/// Now expect smoother and more linear accelerations and decelerations. The desiredSpeed() -/// function was removed. -/// \version 1.24 Fixed a problem introduced in 1.23: with runToPosition, which did never returned -/// \version 1.25 Now ignore attempts to set acceleration to 0.0 -/// \version 1.26 Fixed a problem where certina combinations of speed and accelration could cause -/// oscillation about the target position. -/// \version 1.27 Added stop() function to stop as fast as possible with current acceleration parameters. -/// Also added new Quickstop example showing its use. -/// \version 1.28 Fixed another problem where certain combinations of speed and accelration could cause -/// oscillation about the target position. -/// Added support for 3 wire full and half steppers such as Hard Disk Drive spindle. -/// Contributed by Yuri Ivatchkovitch. -/// \version 1.29 Fixed a problem that could cause a DRIVER stepper to continually step -/// with some sketches. Reported by Vadim. -/// \version 1.30 Fixed a problem that could cause stepper to back up a few steps at the end of -/// accelerated travel with certain speeds. Reported and patched by jolo. -/// \version 1.31 Updated author and distribution location details to airspayce.com -/// \version 1.32 Fixed a problem with enableOutputs() and setEnablePin on Arduino Due that -/// prevented the enable pin changing stae correctly. Reported by Duane Bishop. -/// \version 1.33 Fixed an error in example AFMotor_ConstantSpeed.pde did not setMaxSpeed(); -/// Fixed a problem that caused incorrect pin sequencing of FULL3WIRE and HALF3WIRE. -/// Unfortunately this meant changing the signature for all step*() functions. -/// Added example MotorShield, showing how to use AdaFruit Motor Shield to control -/// a 3 phase motor such as a HDD spindle motor (and without using the AFMotor library. -/// \version 1.34 Added setPinsInverted(bool pin1Invert, bool pin2Invert, bool pin3Invert, bool pin4Invert, bool enableInvert) -/// to allow inversion of 2, 3 and 4 wire stepper pins. Requested by Oleg. -/// \version 1.35 Removed default args from setPinsInverted(bool, bool, bool, bool, bool) to prevent ambiguity with -/// setPinsInverted(bool, bool, bool). Reported by Mac Mac. -/// \version 1.36 Changed enableOutputs() and disableOutputs() to be virtual so can be overridden. -/// Added new optional argument 'enable' to constructor, which allows you toi disable the -/// automatic enabling of outputs at construction time. Suggested by Guido. -/// \version 1.37 Fixed a problem with step1 that could cause a rogue step in the -/// wrong direction (or not, -/// depending on the setup-time requirements of the connected hardware). -/// Reported by Mark Tillotson. -/// \version 1.38 run() function incorrectly always returned true. Updated function and doc so it returns true -/// if the motor is still running to the target position. -/// \version 1.39 Updated typos in keywords.txt, courtesey Jon Magill. -/// \version 1.40 Updated documentation, including testing on Teensy 3.1 -/// \version 1.41 Fixed an error in the acceleration calculations, resulting in acceleration of haldf the intended value -/// \version 1.42 Improved support for FULL3WIRE and HALF3WIRE output pins. These changes were in Yuri's original -/// contribution but did not make it into production.
-/// \version 1.43 Added DualMotorShield example. Shows how to use AccelStepper to control 2 x 2 phase steppers using the -/// Itead Studio Arduino Dual Stepper Motor Driver Shield model IM120417015.
-/// \version 1.44 examples/DualMotorShield/DualMotorShield.ino examples/DualMotorShield/DualMotorShield.pde -/// was missing from the distribution.
-/// \version 1.45 Fixed a problem where if setAcceleration was not called, there was no default -/// acceleration. Reported by Michael Newman.
-/// \version 1.45 Fixed inaccuracy in acceleration rate by using Equation 15, suggested by Sebastian Gracki.
-/// Performance improvements in runSpeed suggested by Jaakko Fagerlund.
-/// \version 1.46 Fixed error in documentation for runToPosition(). -/// Reinstated time calculations in runSpeed() since new version is reported -/// not to work correctly under some circumstances. Reported by Oleg V Gavva.
-/// \version 1.48 2015-08-25 -/// Added new class MultiStepper that can manage multiple AccelSteppers, -/// and cause them all to move -/// to selected positions at such a (constant) speed that they all arrive at their -/// target position at the same time. Suitable for X-Y flatbeds etc.
-/// Added new method maxSpeed() to AccelStepper to return the currently configured maxSpeed.
-/// \version 1.49 2016-01-02 -/// Testing with VID28 series instrument stepper motors and EasyDriver. -/// OK, although with light pointers -/// and slow speeds like 180 full steps per second the motor movement can be erratic, -/// probably due to some mechanical resonance. Best to accelerate through this speed.
-/// Added isRunning().
-/// \version 1.50 2016-02-25 -/// AccelStepper::disableOutputs now sets the enable pion to OUTPUT mode if the enable pin is defined. -/// Patch from Piet De Jong.
-/// Added notes about the fact that AFMotor_* examples do not work with Adafruit Motor Shield V2.
-/// \version 1.51 2016-03-24 -/// Fixed a problem reported by gregor: when resetting the stepper motor position using setCurrentPosition() the -/// stepper speed is reset by setting _stepInterval to 0, but _speed is not -/// reset. this results in the stepper motor not starting again when calling -/// setSpeed() with the same speed the stepper was set to before. -/// \version 1.52 2016-08-09 -/// Added MultiStepper to keywords.txt. -/// Improvements to efficiency of AccelStepper::runSpeed() as suggested by David Grayson. -/// Improvements to speed accuracy as suggested by David Grayson. -/// \version 1.53 2016-08-14 -/// Backed out Improvements to speed accuracy from 1.52 as it did not work correctly. -/// \version 1.54 2017-01-24 -/// Fixed some warnings about unused arguments. -/// \version 1.55 2017-01-25 -/// Fixed another warning in MultiStepper.cpp -/// \version 1.56 2017-02-03 -/// Fixed minor documentation error with DIRECTION_CCW and DIRECTION_CW. Reported by David Mutterer. -/// Added link to Binpress commercial license purchasing. -/// \version 1.57 2017-03-28 -/// _direction moved to protected at the request of Rudy Ercek. -/// setMaxSpeed() and setAcceleration() now correct negative values to be positive. -/// \version 1.58 2018-04-13 -/// Add initialisation for _enableInverted in constructor. -/// -/// \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS -// Copyright (C) 2009-2013 Mike McCauley -// $Id: AccelStepper.h,v 1.27 2016/08/14 10:26:54 mikem Exp mikem $ - -#ifndef AccelStepper_h -#define AccelStepper_h - -#include -#if ARDUINO >= 100 -#include -#else -#include -#include -#endif - -// These defs cause trouble on some versions of Arduino -#undef round - -///////////////////////////////////////////////////////////////////// -/// \class AccelStepper AccelStepper.h -/// \brief Support for stepper motors with acceleration etc. -/// -/// This defines a single 2 or 4 pin stepper motor, or stepper moter with fdriver chip, with optional -/// acceleration, deceleration, absolute positioning commands etc. Multiple -/// simultaneous steppers are supported, all moving -/// at different speeds and accelerations. -/// -/// \par Operation -/// This module operates by computing a step time in microseconds. The step -/// time is recomputed after each step and after speed and acceleration -/// parameters are changed by the caller. The time of each step is recorded in -/// microseconds. The run() function steps the motor once if a new step is due. -/// The run() function must be called frequently until the motor is in the -/// desired position, after which time run() will do nothing. -/// -/// \par Positioning -/// Positions are specified by a signed long integer. At -/// construction time, the current position of the motor is consider to be 0. Positive -/// positions are clockwise from the initial position; negative positions are -/// anticlockwise. The current position can be altered for instance after -/// initialization positioning. -/// -/// \par Caveats -/// This is an open loop controller: If the motor stalls or is oversped, -/// AccelStepper will not have a correct -/// idea of where the motor really is (since there is no feedback of the motor's -/// real position. We only know where we _think_ it is, relative to the -/// initial starting point). -/// -/// \par Performance -/// The fastest motor speed that can be reliably supported is about 4000 steps per -/// second at a clock frequency of 16 MHz on Arduino such as Uno etc. -/// Faster processors can support faster stepping speeds. -/// However, any speed less than that -/// down to very slow speeds (much less than one per second) are also supported, -/// provided the run() function is called frequently enough to step the motor -/// whenever required for the speed set. -/// Calling setAcceleration() is expensive, -/// since it requires a square root to be calculated. -/// -/// Gregor Christandl reports that with an Arduino Due and a simple test program, -/// he measured 43163 steps per second using runSpeed(), -/// and 16214 steps per second using run(); -class AccelStepper -{ -public: - /// \brief Symbolic names for number of pins. - /// Use this in the pins argument the AccelStepper constructor to - /// provide a symbolic name for the number of pins - /// to use. - typedef enum - { - FUNCTION = 0, ///< Use the functional interface, implementing your own driver functions (internal use only) - DRIVER = 1, ///< Stepper Driver, 2 driver pins required - FULL2WIRE = 2, ///< 2 wire stepper, 2 motor pins required - FULL3WIRE = 3, ///< 3 wire stepper, such as HDD spindle, 3 motor pins required - FULL4WIRE = 4, ///< 4 wire full stepper, 4 motor pins required - HALF3WIRE = 6, ///< 3 wire half stepper, such as HDD spindle, 3 motor pins required - HALF4WIRE = 8 ///< 4 wire half stepper, 4 motor pins required - } MotorInterfaceType; - - /// Constructor. You can have multiple simultaneous steppers, all moving - /// at different speeds and accelerations, provided you call their run() - /// functions at frequent enough intervals. Current Position is set to 0, target - /// position is set to 0. MaxSpeed and Acceleration default to 1.0. - /// The motor pins will be initialised to OUTPUT mode during the - /// constructor by a call to enableOutputs(). - /// \param[in] interface Number of pins to interface to. Integer values are - /// supported, but it is preferred to use the \ref MotorInterfaceType symbolic names. - /// AccelStepper::DRIVER (1) means a stepper driver (with Step and Direction pins). - /// If an enable line is also needed, call setEnablePin() after construction. - /// You may also invert the pins using setPinsInverted(). - /// AccelStepper::FULL2WIRE (2) means a 2 wire stepper (2 pins required). - /// AccelStepper::FULL3WIRE (3) means a 3 wire stepper, such as HDD spindle (3 pins required). - /// AccelStepper::FULL4WIRE (4) means a 4 wire stepper (4 pins required). - /// AccelStepper::HALF3WIRE (6) means a 3 wire half stepper, such as HDD spindle (3 pins required) - /// AccelStepper::HALF4WIRE (8) means a 4 wire half stepper (4 pins required) - /// Defaults to AccelStepper::FULL4WIRE (4) pins. - /// \param[in] pin1 Arduino digital pin number for motor pin 1. Defaults - /// to pin 2. For a AccelStepper::DRIVER (interface==1), - /// this is the Step input to the driver. Low to high transition means to step) - /// \param[in] pin2 Arduino digital pin number for motor pin 2. Defaults - /// to pin 3. For a AccelStepper::DRIVER (interface==1), - /// this is the Direction input the driver. High means forward. - /// \param[in] pin3 Arduino digital pin number for motor pin 3. Defaults - /// to pin 4. - /// \param[in] pin4 Arduino digital pin number for motor pin 4. Defaults - /// to pin 5. - /// \param[in] enable If this is true (the default), enableOutputs() will be called to enable - /// the output pins at construction time. - AccelStepper(uint8_t interface = AccelStepper::FULL4WIRE, uint8_t pin1 = 2, uint8_t pin2 = 3, uint8_t pin3 = 4, uint8_t pin4 = 5, bool enable = true); - - /// Alternate Constructor which will call your own functions for forward and backward steps. - /// You can have multiple simultaneous steppers, all moving - /// at different speeds and accelerations, provided you call their run() - /// functions at frequent enough intervals. Current Position is set to 0, target - /// position is set to 0. MaxSpeed and Acceleration default to 1.0. - /// Any motor initialization should happen before hand, no pins are used or initialized. - /// \param[in] forward void-returning procedure that will make a forward step - /// \param[in] backward void-returning procedure that will make a backward step - AccelStepper(void (*forward)(), void (*backward)()); - - /// Set the target position. The run() function will try to move the motor (at most one step per call) - /// from the current position to the target position set by the most - /// recent call to this function. Caution: moveTo() also recalculates the speed for the next step. - /// If you are trying to use constant speed movements, you should call setSpeed() after calling moveTo(). - /// \param[in] absolute The desired absolute position. Negative is - /// anticlockwise from the 0 position. - void moveTo(long absolute); - - /// Set the target position relative to the current position - /// \param[in] relative The desired position relative to the current position. Negative is - /// anticlockwise from the current position. - void move(long relative); - - /// Poll the motor and step it if a step is due, implementing - /// accelerations and decelerations to acheive the target position. You must call this as - /// frequently as possible, but at least once per minimum step time interval, - /// preferably in your main loop. Note that each call to run() will make at most one step, and then only when a step is due, - /// based on the current speed and the time since the last step. - /// \return true if the motor is still running to the target position. - boolean run(); - - /// Poll the motor and step it if a step is due, implementing a constant - /// speed as set by the most recent call to setSpeed(). You must call this as - /// frequently as possible, but at least once per step interval, - /// \return true if the motor was stepped. - boolean runSpeed(); - - /// Sets the maximum permitted speed. The run() function will accelerate - /// up to the speed set by this function. - /// Caution: the maximum speed achievable depends on your processor and clock speed. - /// \param[in] speed The desired maximum speed in steps per second. Must - /// be > 0. Caution: Speeds that exceed the maximum speed supported by the processor may - /// Result in non-linear accelerations and decelerations. - void setMaxSpeed(float speed); - - /// returns the maximum speed configured for this stepper - /// that was previously set by setMaxSpeed(); - /// \return The currently configured maximum speed - float maxSpeed(); - - /// Sets the acceleration/deceleration rate. - /// \param[in] acceleration The desired acceleration in steps per second - /// per second. Must be > 0.0. This is an expensive call since it requires a square - /// root to be calculated. Dont call more ofthen than needed - void setAcceleration(float acceleration); - - /// Sets the desired constant speed for use with runSpeed(). - /// \param[in] speed The desired constant speed in steps per - /// second. Positive is clockwise. Speeds of more than 1000 steps per - /// second are unreliable. Very slow speeds may be set (eg 0.00027777 for - /// once per hour, approximately. Speed accuracy depends on the Arduino - /// crystal. Jitter depends on how frequently you call the runSpeed() function. - void setSpeed(float speed); - - /// The most recently set speed - /// \return the most recent speed in steps per second - float speed(); - - /// The distance from the current position to the target position. - /// \return the distance from the current position to the target position - /// in steps. Positive is clockwise from the current position. - long distanceToGo(); - - /// The most recently set target position. - /// \return the target position - /// in steps. Positive is clockwise from the 0 position. - long targetPosition(); - - /// The currently motor position. - /// \return the current motor position - /// in steps. Positive is clockwise from the 0 position. - long currentPosition(); - - /// Resets the current position of the motor, so that wherever the motor - /// happens to be right now is considered to be the new 0 position. Useful - /// for setting a zero position on a stepper after an initial hardware - /// positioning move. - /// Has the side effect of setting the current motor speed to 0. - /// \param[in] position The position in steps of wherever the motor - /// happens to be right now. - void setCurrentPosition(long position); - - /// Moves the motor (with acceleration/deceleration) - /// to the target position and blocks until it is at - /// position. Dont use this in event loops, since it blocks. - void runToPosition(); - - /// Runs at the currently selected speed until the target position is reached - /// Does not implement accelerations. - /// \return true if it stepped - boolean runSpeedToPosition(); - - /// Moves the motor (with acceleration/deceleration) - /// to the new target position and blocks until it is at - /// position. Dont use this in event loops, since it blocks. - /// \param[in] position The new target position. - void runToNewPosition(long position); - - /// Sets a new target position that causes the stepper - /// to stop as quickly as possible, using the current speed and acceleration parameters. - void stop(); - - /// Disable motor pin outputs by setting them all LOW - /// Depending on the design of your electronics this may turn off - /// the power to the motor coils, saving power. - /// This is useful to support Arduino low power modes: disable the outputs - /// during sleep and then reenable with enableOutputs() before stepping - /// again. - /// If the enable Pin is defined, sets it to OUTPUT mode and clears the pin to disabled. - virtual void disableOutputs(); - - /// Enable motor pin outputs by setting the motor pins to OUTPUT - /// mode. Called automatically by the constructor. - /// If the enable Pin is defined, sets it to OUTPUT mode and sets the pin to enabled. - virtual void enableOutputs(); - - /// Sets the minimum pulse width allowed by the stepper driver. The minimum practical pulse width is - /// approximately 20 microseconds. Times less than 20 microseconds - /// will usually result in 20 microseconds or so. - /// \param[in] minWidth The minimum pulse width in microseconds. - void setMinPulseWidth(unsigned int minWidth); - - /// Sets the enable pin number for stepper drivers. - /// 0xFF indicates unused (default). - /// Otherwise, if a pin is set, the pin will be turned on when - /// enableOutputs() is called and switched off when disableOutputs() - /// is called. - /// \param[in] enablePin Arduino digital pin number for motor enable - /// \sa setPinsInverted - void setEnablePin(uint8_t enablePin = 0xff); - - /// Sets the inversion for stepper driver pins - /// \param[in] directionInvert True for inverted direction pin, false for non-inverted - /// \param[in] stepInvert True for inverted step pin, false for non-inverted - /// \param[in] enableInvert True for inverted enable pin, false (default) for non-inverted - void setPinsInverted(bool directionInvert = false, bool stepInvert = false, bool enableInvert = false); - - /// Sets the inversion for 2, 3 and 4 wire stepper pins - /// \param[in] pin1Invert True for inverted pin1, false for non-inverted - /// \param[in] pin2Invert True for inverted pin2, false for non-inverted - /// \param[in] pin3Invert True for inverted pin3, false for non-inverted - /// \param[in] pin4Invert True for inverted pin4, false for non-inverted - /// \param[in] enableInvert True for inverted enable pin, false (default) for non-inverted - void setPinsInverted(bool pin1Invert, bool pin2Invert, bool pin3Invert, bool pin4Invert, bool enableInvert); - - /// Checks to see if the motor is currently running to a target - /// \return true if the speed is not zero or not at the target position - bool isRunning(); - -protected: - - /// \brief Direction indicator - /// Symbolic names for the direction the motor is turning - typedef enum - { - DIRECTION_CCW = 0, ///< Counter-Clockwise - DIRECTION_CW = 1 ///< Clockwise - } Direction; - - /// Forces the library to compute a new instantaneous speed and set that as - /// the current speed. It is called by - /// the library: - /// \li after each step - /// \li after change to maxSpeed through setMaxSpeed() - /// \li after change to acceleration through setAcceleration() - /// \li after change to target position (relative or absolute) through - /// move() or moveTo() - void computeNewSpeed(); - - /// Low level function to set the motor output pins - /// bit 0 of the mask corresponds to _pin[0] - /// bit 1 of the mask corresponds to _pin[1] - /// You can override this to impment, for example serial chip output insted of using the - /// output pins directly - virtual void setOutputPins(uint8_t mask); - - /// Called to execute a step. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default calls step1(), step2(), step4() or step8() depending on the - /// number of pins defined for the stepper. - /// \param[in] step The current step phase number (0 to 7) - virtual void step(long step); - - /// Called to execute a step using stepper functions (pins = 0) Only called when a new step is - /// required. Calls _forward() or _backward() to perform the step - /// \param[in] step The current step phase number (0 to 7) - virtual void step0(long step); - - /// Called to execute a step on a stepper driver (ie where pins == 1). Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of Step pin1 to step, - /// and sets the output of _pin2 to the desired direction. The Step pin (_pin1) is pulsed for 1 microsecond - /// which is the minimum STEP pulse width for the 3967 driver. - /// \param[in] step The current step phase number (0 to 7) - virtual void step1(long step); - - /// Called to execute a step on a 2 pin motor. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of pin1 and pin2 - /// \param[in] step The current step phase number (0 to 7) - virtual void step2(long step); - - /// Called to execute a step on a 3 pin motor, such as HDD spindle. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of pin1, pin2, - /// pin3 - /// \param[in] step The current step phase number (0 to 7) - virtual void step3(long step); - - /// Called to execute a step on a 4 pin motor. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of pin1, pin2, - /// pin3, pin4. - /// \param[in] step The current step phase number (0 to 7) - virtual void step4(long step); - - /// Called to execute a step on a 3 pin motor, such as HDD spindle. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of pin1, pin2, - /// pin3 - /// \param[in] step The current step phase number (0 to 7) - virtual void step6(long step); - - /// Called to execute a step on a 4 pin half-steper motor. Only called when a new step is - /// required. Subclasses may override to implement new stepping - /// interfaces. The default sets or clears the outputs of pin1, pin2, - /// pin3, pin4. - /// \param[in] step The current step phase number (0 to 7) - virtual void step8(long step); - - /// Current direction motor is spinning in - /// Protected because some peoples subclasses need it to be so - boolean _direction; // 1 == CW - -private: - /// Number of pins on the stepper motor. Permits 2 or 4. 2 pins is a - /// bipolar, and 4 pins is a unipolar. - uint8_t _interface; // 0, 1, 2, 4, 8, See MotorInterfaceType - - /// Arduino pin number assignments for the 2 or 4 pins required to interface to the - /// stepper motor or driver - uint8_t _pin[4]; - - /// Whether the _pins is inverted or not - uint8_t _pinInverted[4]; - - /// The current absolution position in steps. - long _currentPos; // Steps - - /// The target position in steps. The AccelStepper library will move the - /// motor from the _currentPos to the _targetPos, taking into account the - /// max speed, acceleration and deceleration - long _targetPos; // Steps - - /// The current motos speed in steps per second - /// Positive is clockwise - float _speed; // Steps per second - - /// The maximum permitted speed in steps per second. Must be > 0. - float _maxSpeed; - - /// The acceleration to use to accelerate or decelerate the motor in steps - /// per second per second. Must be > 0 - float _acceleration; - float _sqrt_twoa; // Precomputed sqrt(2*_acceleration) - - /// The current interval between steps in microseconds. - /// 0 means the motor is currently stopped with _speed == 0 - unsigned long _stepInterval; - - /// The last step time in microseconds - unsigned long _lastStepTime; - - /// The minimum allowed pulse width in microseconds - unsigned int _minPulseWidth; - - /// Is the direction pin inverted? - ///bool _dirInverted; /// Moved to _pinInverted[1] - - /// Is the step pin inverted? - ///bool _stepInverted; /// Moved to _pinInverted[0] - - /// Is the enable pin inverted? - bool _enableInverted; - - /// Enable pin for stepper driver, or 0xFF if unused. - uint8_t _enablePin; - - /// The pointer to a forward-step procedure - void (*_forward)(); - - /// The pointer to a backward-step procedure - void (*_backward)(); - - /// The step counter for speed calculations - long _n; - - /// Initial step size in microseconds - float _c0; - - /// Last step size in microseconds - float _cn; - - /// Min step size in microseconds based on maxSpeed - float _cmin; // at max speed - -}; - -/// @example Random.pde -/// Make a single stepper perform random changes in speed, position and acceleration - -/// @example Overshoot.pde -/// Check overshoot handling -/// which sets a new target position and then waits until the stepper has -/// achieved it. This is used for testing the handling of overshoots - -/// @example MultipleSteppers.pde -/// Shows how to multiple simultaneous steppers -/// Runs one stepper forwards and backwards, accelerating and decelerating -/// at the limits. Runs other steppers at the same time - -/// @example ConstantSpeed.pde -/// Shows how to run AccelStepper in the simplest, -/// fixed speed mode with no accelerations - -/// @example Blocking.pde -/// Shows how to use the blocking call runToNewPosition -/// Which sets a new target position and then waits until the stepper has -/// achieved it. - -/// @example AFMotor_MultiStepper.pde -/// Control both Stepper motors at the same time with different speeds -/// and accelerations. - -/// @example AFMotor_ConstantSpeed.pde -/// Shows how to run AccelStepper in the simplest, -/// fixed speed mode with no accelerations - -/// @example ProportionalControl.pde -/// Make a single stepper follow the analog value read from a pot or whatever -/// The stepper will move at a constant speed to each newly set posiiton, -/// depending on the value of the pot. - -/// @example Bounce.pde -/// Make a single stepper bounce from one limit to another, observing -/// accelrations at each end of travel - -/// @example Quickstop.pde -/// Check stop handling. -/// Calls stop() while the stepper is travelling at full speed, causing -/// the stepper to stop as quickly as possible, within the constraints of the -/// current acceleration. - -/// @example MotorShield.pde -/// Shows how to use AccelStepper to control a 3-phase motor, such as a HDD spindle motor -/// using the Adafruit Motor Shield http://www.ladyada.net/make/mshield/index.html. - -/// @example DualMotorShield.pde -/// Shows how to use AccelStepper to control 2 x 2 phase steppers using the -/// Itead Studio Arduino Dual Stepper Motor Driver Shield -/// model IM120417015 - -#endif diff --git a/src/2018arm/Makefile b/src/2018arm/Makefile deleted file mode 100644 index 22039ad..0000000 --- a/src/2018arm/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -ARDUINO=10805 -F_CPU=16000000L -MCU=atmega328p - -INCLUDES= \ - -I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino \ - -I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/variants/eightanaloginputs - -ARGS=-Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -DARDUINO_AVR_PRO -DARDUINO_ARCH_AVR - -CPPS=$(patsubst %.cpp,%.o,$(wildcard *.cpp)) - -all: lib.a - -lib.a: ${CPPS} - $(foreach obj, $(CPPS), avr-ar rcs $@ $(obj);) - -%.o: %.cpp - avr-g++ ${ARGS} ${INCLUDES} -DF_CPU=${F_CPU} -DARDUINO=${ARDUINO} -mmcu=${MCU} -c $< -o $@ - -clean: - rm *.o - rm *.d diff --git a/src/2018arm/Servo.cpp b/src/2018arm/Servo.cpp deleted file mode 100644 index 3037c59..0000000 --- a/src/2018arm/Servo.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - Servo.cpp - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2 - Copyright (c) 2009 Michael Margolis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#if defined(ARDUINO_ARCH_AVR) - -#include -#include - -#include "Servo.h" - -#define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8) // converts microseconds to tick (assumes prescale of 8) // 12 Aug 2009 -#define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds - - -#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009 - -//#define NBR_TIMERS (MAX_SERVOS / SERVOS_PER_TIMER) - -static servo_t servos[MAX_SERVOS]; // static array of servo structures -static volatile int8_t Channel[_Nbr_16timers ]; // counter for the servo being pulsed for each timer (or -1 if refresh interval) - -uint8_t ServoCount = 0; // the total number of attached servos - - -// convenience macros -#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo -#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer -#define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel -#define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel - -#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo -#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo - -/************ static functions common to all instances ***********************/ - -long map(long x, long in_min, long in_max, long out_min, long out_max) -{ - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - -static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA) -{ - if( Channel[timer] < 0 ) - *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer - else{ - if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true ) - digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated - } - - Channel[timer]++; // increment to the next channel - if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) { - *OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks; - if(SERVO(timer,Channel[timer]).Pin.isActive == true) // check if activated - digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high - } - else { - // finished all channels so wait for the refresh period to expire before starting over - if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed - *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL); - else - *OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed - Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel - } -} - -#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform -// Interrupt handlers for Arduino -#if defined(_useTimer1) -SIGNAL (TIMER1_COMPA_vect) -{ - handle_interrupts(_timer1, &TCNT1, &OCR1A); -} -#endif - -#if defined(_useTimer3) -SIGNAL (TIMER3_COMPA_vect) -{ - handle_interrupts(_timer3, &TCNT3, &OCR3A); -} -#endif - -#if defined(_useTimer4) -SIGNAL (TIMER4_COMPA_vect) -{ - handle_interrupts(_timer4, &TCNT4, &OCR4A); -} -#endif - -#if defined(_useTimer5) -SIGNAL (TIMER5_COMPA_vect) -{ - handle_interrupts(_timer5, &TCNT5, &OCR5A); -} -#endif - -#elif defined WIRING -// Interrupt handlers for Wiring -#if defined(_useTimer1) -void Timer1Service() -{ - handle_interrupts(_timer1, &TCNT1, &OCR1A); -} -#endif -#if defined(_useTimer3) -void Timer3Service() -{ - handle_interrupts(_timer3, &TCNT3, &OCR3A); -} -#endif -#endif - - -static void initISR(timer16_Sequence_t timer) -{ -#if defined (_useTimer1) - if(timer == _timer1) { - TCCR1A = 0; // normal counting mode - TCCR1B = _BV(CS11); // set prescaler of 8 - TCNT1 = 0; // clear the timer count -#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__) - TIFR |= _BV(OCF1A); // clear any pending interrupts; - TIMSK |= _BV(OCIE1A) ; // enable the output compare interrupt -#else - // here if not ATmega8 or ATmega128 - TIFR1 |= _BV(OCF1A); // clear any pending interrupts; - TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt -#endif -#if defined(WIRING) - timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service); -#endif - } -#endif - -#if defined (_useTimer3) - if(timer == _timer3) { - TCCR3A = 0; // normal counting mode - TCCR3B = _BV(CS31); // set prescaler of 8 - TCNT3 = 0; // clear the timer count -#if defined(__AVR_ATmega128__) - TIFR |= _BV(OCF3A); // clear any pending interrupts; - ETIMSK |= _BV(OCIE3A); // enable the output compare interrupt -#else - TIFR3 = _BV(OCF3A); // clear any pending interrupts; - TIMSK3 = _BV(OCIE3A) ; // enable the output compare interrupt -#endif -#if defined(WIRING) - timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only -#endif - } -#endif - -#if defined (_useTimer4) - if(timer == _timer4) { - TCCR4A = 0; // normal counting mode - TCCR4B = _BV(CS41); // set prescaler of 8 - TCNT4 = 0; // clear the timer count - TIFR4 = _BV(OCF4A); // clear any pending interrupts; - TIMSK4 = _BV(OCIE4A) ; // enable the output compare interrupt - } -#endif - -#if defined (_useTimer5) - if(timer == _timer5) { - TCCR5A = 0; // normal counting mode - TCCR5B = _BV(CS51); // set prescaler of 8 - TCNT5 = 0; // clear the timer count - TIFR5 = _BV(OCF5A); // clear any pending interrupts; - TIMSK5 = _BV(OCIE5A) ; // enable the output compare interrupt - } -#endif -} - -static void finISR(timer16_Sequence_t timer) -{ - //disable use of the given timer -#if defined WIRING // Wiring - if(timer == _timer1) { - #if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__) - TIMSK1 &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt - #else - TIMSK &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt - #endif - timerDetach(TIMER1OUTCOMPAREA_INT); - } - else if(timer == _timer3) { - #if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__) - TIMSK3 &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt - #else - ETIMSK &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt - #endif - timerDetach(TIMER3OUTCOMPAREA_INT); - } -#else - //For arduino - in future: call here to a currently undefined function to reset the timer - (void) timer; // squash "unused parameter 'timer' [-Wunused-parameter]" warning -#endif -} - -static boolean isTimerActive(timer16_Sequence_t timer) -{ - // returns true if any servo is active on this timer - for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) { - if(SERVO(timer,channel).Pin.isActive == true) - return true; - } - return false; -} - - -/****************** end of static functions ******************************/ - -Servo::Servo() -{ - if( ServoCount < MAX_SERVOS) { - this->servoIndex = ServoCount++; // assign a servo index to this instance - servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009 - } - else - this->servoIndex = INVALID_SERVO ; // too many servos -} - -uint8_t Servo::attach(int pin) -{ - return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH); -} - -uint8_t Servo::attach(int pin, int min, int max) -{ - if(this->servoIndex < MAX_SERVOS ) { - pinMode( pin, OUTPUT) ; // set servo pin to output - servos[this->servoIndex].Pin.nbr = pin; - // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128 - this->min = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS - this->max = (MAX_PULSE_WIDTH - max)/4; - // initialize the timer if it has not already been initialized - timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex); - if(isTimerActive(timer) == false) - initISR(timer); - servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive - } - return this->servoIndex ; -} - -void Servo::detach() -{ - servos[this->servoIndex].Pin.isActive = false; - timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex); - if(isTimerActive(timer) == false) { - finISR(timer); - } -} - -void Servo::write(int value) -{ - if(value < MIN_PULSE_WIDTH) - { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds) - if(value < 0) value = 0; - if(value > 180) value = 180; - value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX()); - } - this->writeMicroseconds(value); -} - -void Servo::writeMicroseconds(int value) -{ - // calculate and store the values for the given channel - byte channel = this->servoIndex; - if( (channel < MAX_SERVOS) ) // ensure channel is valid - { - if( value < SERVO_MIN() ) // ensure pulse width is valid - value = SERVO_MIN(); - else if( value > SERVO_MAX() ) - value = SERVO_MAX(); - - value = value - TRIM_DURATION; - value = usToTicks(value); // convert to ticks after compensating for interrupt overhead - 12 Aug 2009 - - uint8_t oldSREG = SREG; - cli(); - servos[channel].ticks = value; - SREG = oldSREG; - } -} - -int Servo::read() // return the value as degrees -{ - return map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180); -} - -int Servo::readMicroseconds() -{ - unsigned int pulsewidth; - if( this->servoIndex != INVALID_SERVO ) - pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION ; // 12 aug 2009 - else - pulsewidth = 0; - - return pulsewidth; -} - -bool Servo::attached() -{ - return servos[this->servoIndex].Pin.isActive ; -} - -#endif // ARDUINO_ARCH_AVR - diff --git a/src/2018arm/Servo.h b/src/2018arm/Servo.h deleted file mode 100644 index da73484..0000000 --- a/src/2018arm/Servo.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2 - Copyright (c) 2009 Michael Margolis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* - A servo is activated by creating an instance of the Servo class passing - the desired pin to the attach() method. - The servos are pulsed in the background using the value most recently - written using the write() method. - - Note that analogWrite of PWM on pins associated with the timer are - disabled when the first servo is attached. - Timers are seized as needed in groups of 12 servos - 24 servos use two - timers, 48 servos will use four. - The sequence used to sieze timers is defined in timers.h - - The methods are: - - Servo - Class for manipulating servo motors connected to Arduino pins. - - attach(pin ) - Attaches a servo motor to an i/o pin. - attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds - default min is 544, max is 2400 - - write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds) - writeMicroseconds() - Sets the servo pulse width in microseconds - read() - Gets the last written servo pulse width as an angle between 0 and 180. - readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release) - attached() - Returns true if there is a servo attached. - detach() - Stops an attached servos from pulsing its i/o pin. - */ - -#ifndef Servo_h -#define Servo_h - -#include - -/* - * Defines for 16 bit timers used with Servo library - * - * If _useTimerX is defined then TimerX is a 16 bit timer on the current board - * timer16_Sequence_t enumerates the sequence that the timers should be allocated - * _Nbr_16timers indicates how many 16 bit timers are available. - */ - -// Architecture specific include -#if defined(ARDUINO_ARCH_AVR) -#include "ServoTimers.h" -#elif defined(ARDUINO_ARCH_SAM) -#include "sam/ServoTimers.h" -#elif defined(ARDUINO_ARCH_SAMD) -#include "samd/ServoTimers.h" -#elif defined(ARDUINO_ARCH_STM32F4) -#include "stm32f4/ServoTimers.h" -#elif defined(ARDUINO_ARCH_NRF52) -#include "nrf52/ServoTimers.h" -#else -#error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor." -#endif - -#define Servo_VERSION 2 // software version of this library - -#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo -#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo -#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached -#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds - -#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer -#define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER) - -#define INVALID_SERVO 255 // flag indicating an invalid servo index - -#if !defined(ARDUINO_ARCH_STM32F4) - -typedef struct { - uint8_t nbr :6 ; // a pin number from 0 to 63 - uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false -} ServoPin_t ; - -typedef struct { - ServoPin_t Pin; - volatile unsigned int ticks; -} servo_t; - -class Servo -{ -public: - Servo(); - uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure - uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes. - void detach(); - void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds - void writeMicroseconds(int value); // Write pulse width in microseconds - int read(); // returns current pulse width as an angle between 0 and 180 degrees - int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release) - bool attached(); // return true if this servo is attached, otherwise false -private: - uint8_t servoIndex; // index into the channel data for this servo - int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH - int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH -}; - -#endif -#endif diff --git a/src/2018arm/ServoTimers.h b/src/2018arm/ServoTimers.h deleted file mode 100644 index 9794c8e..0000000 --- a/src/2018arm/ServoTimers.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2 - Copyright (c) 2009 Michael Margolis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* - * Defines for 16 bit timers used with Servo library - * - * If _useTimerX is defined then TimerX is a 16 bit timer on the current board - * timer16_Sequence_t enumerates the sequence that the timers should be allocated - * _Nbr_16timers indicates how many 16 bit timers are available. - */ - -/** - * AVR Only definitions - * -------------------- - */ - -// Say which 16 bit timers can be used and in what order -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -#define _useTimer5 -#define _useTimer1 -#define _useTimer3 -#define _useTimer4 -typedef enum { _timer5, _timer1, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t; - -#elif defined(__AVR_ATmega32U4__) -#define _useTimer1 -typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t; - -#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) -#define _useTimer3 -#define _useTimer1 -typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t; - -#elif defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2561__) -#define _useTimer3 -#define _useTimer1 -typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t; - -#else // everything else -#define _useTimer1 -typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t; -#endif - diff --git a/src/2018arm/nodeh_ext.h b/src/2018arm/nodeh_ext.h deleted file mode 100644 index f748312..0000000 --- a/src/2018arm/nodeh_ext.h +++ /dev/null @@ -1,67 +0,0 @@ - -#include "../Header.h" - -class ServoGoto: public Node { -private: - Node *pos; - static Function *fservo_goto; -public: - ServoGoto(Node *position): pos(position) {} - - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - // value for the two parameters - vector args; - args.push_back(pos->generate(func, block, allocblock)); - - // get the function signature - if (!fservo_goto) { - - vector arg_types; - arg_types.push_back(Type::getInt16Ty(global_context)); - FunctionType *ftype = FunctionType::get(Type::getVoidTy(global_context), ArrayRef(arg_types), false); - fservo_goto = Function::Create(ftype, Function::ExternalLinkage, "servo_goto", mainmodule); - fservo_goto->setCallingConv(CallingConv::C); - } - - // generate code to call servo_goto function - ArrayRef argsRef(args); - return CallInst::Create(fservo_goto, argsRef, "", block); - } -}; - -class StepperGoto: public Node { -private: - int stp; - Node *pos; - static Function *fstepper_goto; -public: - StepperGoto(int stepper, Node *position): stp(stepper), pos(position) {} - - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - // value for the two parameters - Int16 nstp(stp); - - vector args; - args.push_back(nstp.generate(func, block, allocblock)); - args.push_back(pos->generate(func, block, allocblock)); - - // get the function signature - if (!fstepper_goto) { - - vector arg_types; - arg_types.push_back(Type::getInt16Ty(global_context)); - arg_types.push_back(Type::getInt16Ty(global_context)); - FunctionType *ftype = FunctionType::get(Type::getVoidTy(global_context), ArrayRef(arg_types), false); - fstepper_goto = Function::Create(ftype, Function::ExternalLinkage, "stepper_goto", mainmodule); - fstepper_goto->setCallingConv(CallingConv::C); - } - - // generate code to call stepper_goto function - ArrayRef argsRef(args); - return CallInst::Create(fstepper_goto, argsRef, "", block); - } -}; - -Function *StepperGoto::fstepper_goto = NULL; -Function *ServoGoto::fservo_goto = NULL; - diff --git a/src/2018arm/stepper_aux.cpp b/src/2018arm/stepper_aux.cpp deleted file mode 100644 index e35f011..0000000 --- a/src/2018arm/stepper_aux.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "stepper_aux.h" - -bool stepper_configured = false; -AccelStepper stepper_base(AccelStepper::HALF4WIRE, 2, 4, 3, 5); -AccelStepper stepper_updown(AccelStepper::HALF4WIRE, 6, 8, 7, 9); -AccelStepper stepper_forward(AccelStepper::HALF4WIRE, 10, 12, 11, 13); - -#define SERVO_PORT A5 -Servo servo_gripper; - -void stepper_goto(int stepper, int pos) { - if (!stepper_configured) { - // Change these to suit your stepper if you want - int maxSpeed = 4000; - int speed = 10; -// float acceleration = 100000; - float acceleration = 1000; - stepper_base.setMaxSpeed(maxSpeed); - stepper_updown.setMaxSpeed(maxSpeed); - stepper_forward.setMaxSpeed(maxSpeed); - stepper_base.setAcceleration(acceleration); - stepper_updown.setAcceleration(acceleration); - stepper_forward.setAcceleration(acceleration); - stepper_configured = true; - } - - AccelStepper *s; - if (stepper == 0) - s = &stepper_base; - else if (stepper == 1) - s = &stepper_updown; - else - s = &stepper_forward; - s->enableOutputs(); - s->runToNewPosition(pos); - s->disableOutputs(); -} - -void servo_goto(int pos) { - #define MIN_POS 82 - if (!servo_gripper.attached()) - servo_gripper.attach(SERVO_PORT); - if (pos >= 0 && pos <= 38) { - servo_gripper.write(pos + MIN_POS); - delay(15); // small delay - } -} - -void print(char t, char *p) { -} - diff --git a/src/2018arm/stepper_aux.h b/src/2018arm/stepper_aux.h deleted file mode 100644 index ea78da4..0000000 --- a/src/2018arm/stepper_aux.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef STEPPER_AUXH -#define STEPPER_AUXH - -#include "AccelStepper.h" -#include "Servo.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void stepper_goto(int stepper, int pos); -void servo_goto(int pos); -void print(char t, char *p); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/Array.cpp b/src/Array.cpp index 0fb251c..820a455 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -80,8 +80,6 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb GlobalVariable *gv = new GlobalVariable(*mainmodule, arrayType, false, GlobalValue::InternalLinkage, ConstantArray::get(arrayType, constantRefs), name); - gv->setDSOLocal(true); - gv->setAlignment(Align(2)); alloc = gv; if (debug_info) { diff --git a/src/ArrayElements.cpp b/src/ArrayElements.cpp index 52c1914..9075c4d 100644 --- a/src/ArrayElements.cpp +++ b/src/ArrayElements.cpp @@ -60,7 +60,10 @@ DataType ArrayElements::getArrayType() { // find distinct types set types; for(auto& i : elements) { - types.emplace(i->value->getDataType()); + DataType edt = i->value->getDataType(); + if (buildTypes->isEnum(edt)) + edt = tint8; + types.emplace(edt); } return getArrayConstType(types, &location); } diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index db85434..b117f3c 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -55,7 +55,7 @@ TargetInfo supportedTargets[__last_target] = { {rb_xtensa, "esp32", "xtensa", "", "", tint32}, }; -void print_llvm_ir(char opt_level) { +int print_llvm_ir(char opt_level) { const TargetInfo& ai = currentTarget(); if (ai.backend == rb_native) { @@ -79,7 +79,7 @@ void print_llvm_ir(char opt_level) { LLVMInitializeARMAsmPrinter(); } else { cerr << "No backend set for target " << ai.triple << ".\n"; - return; + return 1; } std::string defaultt = sys::getDefaultTargetTriple(); @@ -102,9 +102,26 @@ void print_llvm_ir(char opt_level) { } TargetOptions opt; + opt.FunctionSections = true; + opt.DataSections = true; + + auto reloc = Reloc::PIC_; + if (ai.backend == rb_arm) + reloc = Reloc::Static; + + CodeGenOptLevel cgoptl = CodeGenOptLevel::None; + switch (opt_level) { + case '1': cgoptl = CodeGenOptLevel::Less; break; + case '2': cgoptl = CodeGenOptLevel::Default; break; + case '3': + case 's': + case 'z': + cgoptl = CodeGenOptLevel::Aggressive; + break; + } + auto targetMachine = Target->createTargetMachine(ai.triple, - ai.cpu, ai.features, opt, Reloc::PIC_, - CodeModel::Small, CodeGenOptLevel::Aggressive); + ai.cpu, ai.features, opt, reloc, CodeModel::Small, cgoptl); mainmodule->setDataLayout(targetMachine->createDataLayout()); mainmodule->setTargetTriple(ai.triple); @@ -136,24 +153,34 @@ void print_llvm_ir(char opt_level) { default : ol = OptimizationLevel::Oz; break; } + bool llvmir_errors = false; + for(auto &f : mainmodule->getFunctionList()) { + if (verifyFunction(f, &llvm::errs())) { + cerr << endl << "Error(s) detected while verifying function " << f.getName().str() << endl; + llvmir_errors = true; + } + } + + bool broken_debug = false; + if (verifyModule(*mainmodule, &llvm::errs(), &broken_debug)) { + cerr << endl << "Error(s) detected while verifying the global module." << endl; + llvmir_errors = true; + } + + if (broken_debug) + cerr << "Errors in debug information were detected while verifying the global module." << endl; + // This is used to see the llvm IR prior to any analysis. // Sometimes when adding new features, we want to see the IR even // it being invalid. if (debugopt) { mainmodule->print(outs(), nullptr); - - for(auto &f : mainmodule->getFunctionList()) { - if (verifyFunction(f, &llvm::errs())) { - cerr << "Error(s) detected while verifying function " << f.getName().str() << endl; - } - } - - if (verifyModule(*mainmodule), &llvm::errs()) - cerr << "Error(s) detected while verifying the global module." << endl; - - return; + return 0; } + if (llvmir_errors) + return 1; + UpgradeDebugInfo(*mainmodule); ModulePassManager modulePassManager; @@ -181,6 +208,8 @@ void print_llvm_ir(char opt_level) { // print IR to stdout mainmodule->print(outs(), nullptr); } + + return 0; } const TargetInfo& currentTarget() { diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 2116345..1c302c6 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -21,6 +21,7 @@ BuildTypes::BuildTypes(DataType targetPointerType) { tinfo[tint6u] = {"uint6", 6, Type::getIntNTy(global_context, 6), dwarf::DW_ATE_unsigned}; tinfo[tint7u] = {"uint7", 7, Type::getIntNTy(global_context, 7), dwarf::DW_ATE_unsigned}; tinfo[tint8u] = {"uint8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint12u] = {"uint12", 12, Type::getIntNTy(global_context, 12),dwarf::DW_ATE_unsigned}; tinfo[tint16u] = {"uint16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tint32u] = {"uint32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tint64u] = {"uint64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_unsigned}; @@ -141,8 +142,8 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi members.push_back(n); } - assert((members.size() == llvmType->getNumContainedTypes()) && - "Number of fields differ between LLVM Type and Node."); + //assert((members.size() == llvmType->getNumContainedTypes()) && + // "Number of fields differ between LLVM Type and Node."); int i = 0; elems.reserve(members.size()); diff --git a/src/BuildTypes.h b/src/BuildTypes.h index 179debb..78d4100 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -13,7 +13,7 @@ typedef int DataType; enum BasicDataType {tvoid, tbool, tchar, tint8, tint16, tint32, tint64, tint2u, tint3u, tint4u, tint5u, tint6u, tint7u, - tint8u, tint16u, tint32u, tint64u, + tint8u, tint12u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, /* new types here! */ __bdt_last}; @@ -199,19 +199,42 @@ class BuildTypes { DataType unsignedToSigned(DataType tid) { assert(isUnsignedDataType(tid)); - if (tid == tchar) - return tint8; - else if (tid >= tint2u && tid <= tint7u) - return tint8; - else - return tid - (tint64u - tint64); + switch (tid) { + case tchar: + return tint8; + case tint2u: + case tint3u: + case tint4u: + case tint5u: + case tint6u: + case tint7u: + case tint8u: + return tint8; + case tint16u: + return tint16; + case tint32u: + return tint32; + case tint64u: + default: + return tint64; + } } DataType signedToUnsigned(DataType tid) { assert(isSignedDataType(tid)); - if (tid != tbool) - tid += tint64u - tint64; - return tid; + if (tid == tbool) + return tid; + switch (tid) { + case tint8: + return tint8u; + case tint16: + return tint16u; + case tint32: + return tint32u; + case tint64: + default: + return tint64u; + } } bool isDefined(DataType tid) { diff --git a/src/ConstructorCall.cpp b/src/ConstructorCall.cpp index ae75677..59a206e 100644 --- a/src/ConstructorCall.cpp +++ b/src/ConstructorCall.cpp @@ -43,7 +43,7 @@ Value* ConstructorCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlo funcDecl->setScope(program); funcDecl->setLocation(this); funcDecl->generate(NULL, NULL, global_alloc); - funcDecl->setInline(true); + funcDecl->setAttributes(new FunctionAttributes(fa_inline)); program->addSymbol(funcDecl); } RobDbgInfo.emitLocation(this); diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index 4fb5e1e..f15c547 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -17,13 +17,19 @@ void DebugInfo::emitLocation(SourceLocation *s) { scope->getContext(), s->getLineNo(), s->getColNo(), scope)); } -void DebugInfo::push_scope(DIFile *f, DIScope *s) { +void DebugInfo::push_scope(DIScope *s) { scopes.push_back(s); +} + +void DebugInfo::push_file(DIFile *f) { files.push_back(f); } void DebugInfo::pop_scope() { scopes.pop_back(); +} + +void DebugInfo::pop_file() { files.pop_back(); } @@ -42,14 +48,14 @@ DIScope* DebugInfo::currScope() { DIExpression *DebugInfo::getFixedOffsetExpression() { // TODO: For some unknown reason (to me), we need to offset // the var declaration by one to see its actual value - if (currentTarget().backend == rb_avr) { + /*if (currentTarget().backend == rb_avr) { SmallVector Ops; DIExpression *ex = DBuilder->createExpression(); ex->appendOffset(Ops, 1); return DIExpression::prependOpcodes(ex, Ops, false); - } else { + } else {*/ return DBuilder->createExpression(); - } + //} } void DebugInfo::declareVar(Node *n, Value *alloc, BasicBlock *allocblock) { diff --git a/src/Dispatch.cpp b/src/Dispatch.cpp index 5a2e60c..b39aeb0 100644 --- a/src/Dispatch.cpp +++ b/src/Dispatch.cpp @@ -37,7 +37,6 @@ void Dispatch::generateDispatchFunctions(Node *scope) { if (!dispatchFunc) { dispatchFunc = Function::Create(functionDecl->getLLVMFunction()->getFunctionType(), Function::ExternalLinkage, codeAddrSpace, dispatchFuncName, mainmodule); - dispatchFunc->setDSOLocal(true); dispatchFunc->setCallingConv(CallingConv::C); if (impls.size() == 1) dispatchFunc->addFnAttr(Attribute::AlwaysInline); diff --git a/src/FlexDependencies.h b/src/FlexDependencies.h index b19b255..459263e 100644 --- a/src/FlexDependencies.h +++ b/src/FlexDependencies.h @@ -19,8 +19,9 @@ class MatrixElement; class Variable; class Field; -#include "SourceLocation.h" #include "Colors.h" +#include "SourceLocation.h" +#include "FunctionAttributes.h" typedef void* yyscan_t; diff --git a/src/FunctionAttributes.h b/src/FunctionAttributes.h new file mode 100644 index 0000000..c5584d4 --- /dev/null +++ b/src/FunctionAttributes.h @@ -0,0 +1,29 @@ + +#pragma once + +enum FunctionAttributeType {fa_weak, fa_inline, fa_noinline, fa_section}; + +typedef pair FunctionAttribute; + +class FunctionAttributes { +protected: + vector attributes; +public: + FunctionAttributes() {} + FunctionAttributes(FunctionAttributeType attr, const string& value = "") { + addAttribute(attr, value); + } + ~FunctionAttributes() { + for(auto *attr : attributes) + delete attr; + } + void addAttribute(FunctionAttributeType attr, const string& value = "") { + attributes.push_back(new FunctionAttribute(attr, value)); + } + void addAttribute(FunctionAttribute *attr) { + attributes.push_back(attr); + } + const vector& getAttributes() { + return attributes; + } +}; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 24d1857..e7f77b4 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -207,7 +207,6 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock if (!intf_cfunc) { intf_cfunc = Function::Create(cfunc->getFunctionType(), Function::ExternalLinkage, codeAddrSpace, inject_name, mainmodule); - intf_cfunc->setDSOLocal(true); intf_cfunc->setCallingConv(CallingConv::C); intf_cfunc->addFnAttr(Attribute::AlwaysInline); } diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 971770c..3f49521 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -1,6 +1,7 @@ #include "FunctionDecl.h" #include "BackLLVM.h" +#include "Matrix.h" void FunctionBase::addThisArgument(DataType dt) { thisArgDt = dt; @@ -77,6 +78,34 @@ void FunctionBase::addPseudoParameters() { } } +void FunctionBase::addFunctionAttributes(Function *func) { + + //func->addFnAttr(Attribute::MinSize); + func->addFnAttr("target-cpu", currentTarget().cpu); + func->addFnAttr("frame-pointer", "all"); + func->addFnAttr("stack-protector-buffer-size", "8"); + + if (!attributes) + return; + + for(auto *attr : attributes->getAttributes()) { + switch (attr->first) { + case fa_weak: + func->setLinkage(GlobalValue::WeakAnyLinkage); + break; + case fa_inline: + func->addFnAttr(Attribute::AlwaysInline); + break; + case fa_noinline: + func->addFnAttr(Attribute::NoInline); + break; + case fa_section: + func->setSection(attr->second); + break; + } + } +} + Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocblock) { Node *symbol = findSymbol(name); @@ -95,13 +124,10 @@ Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocbloc xtype = xtype->getPointerTo(); FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - Function *nfunc = Function::Create(ftype, Function::ExternalLinkage, codeAddrSpace, getFinalName(), mainmodule); - nfunc->setDSOLocal(true); + Function *nfunc = Function::Create(ftype, linkage, codeAddrSpace, getFinalName(), mainmodule); nfunc->setCallingConv(CallingConv::C); + addFunctionAttributes(nfunc); - if (attrInline) - nfunc->addFnAttr(Attribute::AlwaysInline); - if (buildTypes->isUnsignedDataType(dt)) nfunc->addRetAttr(Attribute::ZExt); diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 1b37d5c..8a73f9b 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -3,25 +3,26 @@ #include "BuildTypes.h" #include "Node.h" #include "FunctionParams.h" -#include "Variable.h" -#include "Matrix.h" +#include "FunctionAttributes.h" class FunctionBase: public NamedNode { protected: FunctionParams *parameters; + FunctionAttributes *attributes = new FunctionAttributes(); Function *func = NULL; bool declaration = true; bool constructor = false; bool external = false; bool returnIsPointer = false; - bool attrInline = false; DataType thisArgDt = BuildTypes::undefinedType; Value *thisArg = NULL; DataType parentArgDt = BuildTypes::undefinedType; Value *parentArg = NULL; string prefixName; + GlobalValue::LinkageTypes linkage = Function::ExternalLinkage; bool validateAndGetArgsTypes(std::vector &args); + void addFunctionAttributes(Function *f); public: FunctionBase(DataType dt, string name, FunctionParams *fp, location_t loc) : @@ -40,6 +41,11 @@ class FunctionBase: public NamedNode { addPseudoParameters(); } + ~FunctionBase() { + delete parameters; + delete attributes; + } + void addPseudoParameters(); FunctionParams& getParameters() { @@ -78,10 +84,6 @@ class FunctionBase: public NamedNode { external = e; } - void setInline(bool i) { - attrInline = i; - } - bool isExternal() { return external; } @@ -124,6 +126,19 @@ class FunctionBase: public NamedNode { else return prefixName + ":" + name; } + + void setAttributes(FunctionAttributes *attributes) { + delete this->attributes; + this->attributes = attributes; + } + + FunctionAttributes *getAttributes() { + return attributes; + } + + void setLinkage(GlobalValue::LinkageTypes l) { + linkage = l; + } }; class FunctionDecl: public FunctionBase { diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index cfe9462..dd7dedc 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -6,6 +6,7 @@ FunctionImpl::FunctionImpl(DataType dt, string name, FunctionParams *fp, vector< location_t loc, location_t ef, bool constructor) : FunctionBase(dt, name, fp, std::move(stmts), loc, constructor), endfunction(ef) { this->declaration = false; + funit = RobDbgInfo.currFile(); for(auto p: fp->getParameters()) { symbols[p->getName()] = p; @@ -38,7 +39,7 @@ bool FunctionImpl::preGenerate() { return false; FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); - func = Function::Create(ftype, Function::ExternalLinkage, codeAddrSpace, getFinalName(), mainmodule); + func = Function::Create(ftype, linkage, codeAddrSpace, getFinalName(), mainmodule); } #ifdef __MINGW64__ @@ -46,38 +47,18 @@ bool FunctionImpl::preGenerate() { func->setName("__main"); #endif - func->setDSOLocal(true); - llvm::AttrBuilder attrs(global_context); - //attrs.addAttribute(Attribute::MinSize); - attrs.addAttribute("target-cpu", currentTarget().cpu); - attrs.addAttribute("frame-pointer", "all"); - attrs.addAttribute("stack-protector-buffer-size", "8"); - - if (attrInline) { - // inline constructors and functions with only one node. - // TODO: Check the resulting binary size. - //if (!debug_info) - attrs.addAttribute(Attribute::AlwaysInline); - } else if (node_children.size() == 1) - attrs.addAttribute(Attribute::InlineHint); - - if (name == "__vectors") { // FIXME: remove after adding functions attributes to language - func->setSection(".vectors"); - } - - func->setAttributes(llvm::AttributeList().addFnAttributes(global_context, attrs)); + addFunctionAttributes(func); func->setCallingConv(CallingConv::C); if (buildTypes->isUnsignedDataType(dt)) func->addRetAttr(Attribute::ZExt); if (debug_info && !declaration) { - funit = DBuilder->createFile(RobDbgInfo.cunit->getFilename(), RobDbgInfo.cunit->getDirectory()); - DIScope *fcontext = funit; - sp = DBuilder->createFunction(fcontext, getFinalName(), StringRef(), funit, this->getLineNo(), - getFunctionDIType(), this->getLineNo(), DINode::FlagZero, DISubprogram::SPFlagDefinition); + sp = DBuilder->createFunction(funit, getFinalName(), StringRef(), funit, + this->getLineNo(), getFunctionDIType(), this->getLineNo(), DINode::FlagZero, + DISubprogram::SPFlagDefinition); func->setSubprogram(sp); - RobDbgInfo.push_scope(funit, sp); + RobDbgInfo.push_scope(sp); } if (isExternal()) @@ -148,7 +129,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo return NULL; if (debug_info) { - RobDbgInfo.push_scope(funit, sp); + RobDbgInfo.push_scope(sp); RobDbgInfo.emitLocation(this); } diff --git a/src/Header.h b/src/Header.h index 5b78c31..5499a94 100644 --- a/src/Header.h +++ b/src/Header.h @@ -5,9 +5,6 @@ #error Please include this file only on .y or visitor files #endif -//#define ENABLE_ARDUINO -//#define ENABLE_PRINT - #include "HeaderGlobals.h" #include "SourceLocation.h" #include "Scanner.h" diff --git a/src/HeaderGlobals.h b/src/HeaderGlobals.h index 9c0795f..f6ac6b9 100644 --- a/src/HeaderGlobals.h +++ b/src/HeaderGlobals.h @@ -23,8 +23,10 @@ struct DebugInfo { vector files; vector scopes; void emitLocation(SourceLocation *s); - void push_scope(DIFile *f, DIScope *); + void push_scope(DIScope*); + void push_file(DIFile*); void pop_scope(); + void pop_file(); DIFile *currFile(); DIScope *currScope(); void declareVar(Node *n, Value *alloc, BasicBlock *allocblock); diff --git a/src/Interface.cpp b/src/Interface.cpp index 33af603..d3402c3 100644 --- a/src/Interface.cpp +++ b/src/Interface.cpp @@ -27,22 +27,12 @@ void Interface::createDataType() { Value *Interface::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - // generate init function/constructor - /*FunctionParams *fp = new FunctionParams(); - FunctionDecl *finit = new FunctionDecl((DataType)tvoid, "init", fp); - finit->addThisArgument(dt); - finit->setUserTypeName(getName()); - finit->setExternal(true); - addChild(finit); - addSymbol(finit);*/ - // set function parameters for(Node *n : node_children) { FunctionDecl *fd = dynamic_cast(n); if (fd) { fd->setPrefixName(getName()); fd->addThisArgument(dt); - fd->setExternal(true); fd->generate(func, block, allocblock); } } @@ -58,7 +48,7 @@ bool Interface::validateImplementation(UserType *ut) { if (!symb) { yyerrorcpp(string_format("Type %s doesn't implement %s.", ut->getName().c_str(), key.c_str()), ut); - yyerrorcpp(string_format("%s is defined here.", key.c_str()), func_decl); + yywarncpp(string_format("%s is defined here.", key.c_str()), func_decl); result = false; } else if (!fimpl) { yyerrorcpp(key + " must be a function.", symb); diff --git a/src/Language.l b/src/Language.l index 391f28e..4075328 100644 --- a/src/Language.l +++ b/src/Language.l @@ -1,4 +1,5 @@ %{ +#include "HeaderGlobals.h" #include #include "Language_gen_y.hpp" @@ -43,6 +44,11 @@ EXP ([Ee][-+]?[0-9]+)? "implements" { return TOK_IMPL; } "use" { return TOK_USE; } +"inline" { return TOK_INLINE; } +"noinline" { return TOK_NOINLINE; } +"weak" { return TOK_WEAK; } +"section" { return TOK_SECTION; } + "bind" { return TOK_BIND; } "to" { return TOK_TO; } "singleton" { return TOK_SINGLETON; } @@ -128,12 +134,12 @@ EXP ([Ee][-+]?[0-9]+)? return TOK_UINTEGER; } [0-9]+{EXP}[Uu] { char *aux = strndup(yytext, yyleng-1); - yylval->unint = strtoull(aux, NULL, 10); + yylval->unint = (uint64_t)strtod(aux, NULL); free(aux); return TOK_UINTEGER; } [0-9]+{EXP} { char *aux = strndup(yytext, yyleng); - yylval->nint = strtoll(aux, NULL, 10); + yylval->nint = (int64_t)strtod(aux, NULL); free(aux); return TOK_INTEGER; } @@ -148,7 +154,7 @@ EXP ([Ee][-+]?[0-9]+)? return TOK_CHAR; } /* deixar por último. Caractere não reconhecido pelo alfabeto. */ -. { yyerror(yylloc, NULL, COLOR_RED "lexical error:" COLOR_RED " caractere nao pertence ao alfabeto da linguagem:"); } +. { yyerror(yylloc, NULL, string_format(COLOR_RED "lexical error:" COLOR_RED " unknown char '%c'.", yytext[0]).c_str()); } %% diff --git a/src/Language.y b/src/Language.y index 7694e7e..42b58b6 100644 --- a/src/Language.y +++ b/src/Language.y @@ -37,9 +37,13 @@ %type TOK_DOUBLE %type TOK_LDOUBLE %type TOK_STRING asminline +%type function_attributes +%type function_attribute %% +programa : %empty + programa : globals { for(auto stmt : *($globals)) { program->addChild(stmt); @@ -113,17 +117,39 @@ enum_item : TOK_IDENTIFIER[id] { function : function_decl | function_impl -function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' ';' { - $$ = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params, @id); - } +function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' function_attributes[fa] ';' { + FunctionDecl *func = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params, @id); + func->setAttributes($fa); + $$ = func; +} -function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' '{' stmts '}'[ef] { +function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' function_attributes[fa] '{' stmts '}'[ef] { FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, std::move(*$stmts), @id, @ef); - func->setLocation(@type); + func->setAttributes($fa); $$ = func; } +function_attributes: function_attributes[fas] ',' function_attribute[fa] { + $fas->addAttribute($fa); + $$ = $fas; +} + +function_attributes : function_attribute[fa] { + $$ = new FunctionAttributes(); + $$->addAttribute($fa); +} + +function_attributes : %empty { + $$ = new FunctionAttributes(); +} + +function_attribute + : TOK_WEAK { $$ = new FunctionAttribute(fa_weak, ""); } + | TOK_INLINE { $$ = new FunctionAttribute(fa_inline, ""); } + | TOK_NOINLINE { $$ = new FunctionAttribute(fa_noinline, ""); } + | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } + event : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { /*char funcname[100]; snprintf(funcname, 100, "__callback_int_p%d_e%d", (int)$2, (int)$4); diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index 9e9eea8..eb2a2f2 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -35,6 +35,8 @@ %token TOK_QUANDO TOK_ESTA %token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT +%token TOK_INLINE TOK_NOINLINE TOK_WEAK TOK_SECTION + %union { char *ident; char *str; @@ -48,6 +50,8 @@ ArrayElements *aes; MatrixElements *mes; FunctionParams *fps; + FunctionAttributes *fattrs; + FunctionAttribute *fattr; ParamsCall *pc; vector *nodes; vector *strings; diff --git a/src/LanguageUse.y b/src/LanguageUse.y index b64464a..9460286 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -37,6 +37,9 @@ %type TOK_LDOUBLE %type TOK_CHAR +%type function_attributes +%type function_attribute + %printer { fprintf(yyo, "'%s'", $$); } %printer { fprintf(yyo, "'%s'", $$ ? $$->getName().c_str() : ""); } @@ -119,20 +122,42 @@ enum_item : TOK_IDENTIFIER[id] { function : function_decl | function_impl -function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' ';' { - $$ = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params, @id); +function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' function_attributes[fa] ';' { + FunctionDecl *func = new FunctionDecl(buildTypes->getType($type, true), $id, $function_params, @id); + func->setAttributes($fa); + $$ = func; } -function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' '{' stmts '}'[ef] { +function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' function_attributes[fa] '{' stmts '}'[ef] { vector stmts; FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, std::move(stmts), @type, @ef); func->setExternal(true); func->setDeclaration(true); - func->setLocation(@type); + func->setAttributes($fa); $$ = func; } +function_attributes: function_attributes[fas] ',' function_attribute[fa] { + $fas->addAttribute($fa); + $$ = $fas; +} + +function_attributes : function_attribute[fa] { + $$ = new FunctionAttributes(); + $$->addAttribute($fa); +} + +function_attributes : %empty { + $$ = new FunctionAttributes(); +} + +function_attribute + : TOK_WEAK { $$ = new FunctionAttribute(fa_weak, ""); } + | TOK_INLINE { $$ = new FunctionAttribute(fa_inline, ""); } + | TOK_NOINLINE { $$ = new FunctionAttribute(fa_noinline, ""); } + | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } + qualifier : TOK_CONST { $$ = qconst; } | TOK_VOLATILE { $$ = qvolatile; } @@ -171,12 +196,10 @@ register : TOK_REGISTER TOK_IDENTIFIER[type] TOK_IDENTIFIER[name] TOK_AT const_e interface : TOK_INTF TOK_IDENTIFIER[id] '{' interface_decls[intf] '}' { $$ = new Interface($id, std::move(*$intf), @id); - $$->setLocation(@TOK_INTF); } interface : TOK_INTF TOK_IDENTIFIER[id] '{' '}' { $$ = new Interface($id, @id); - $$->setLocation(@TOK_INTF); } interface_decls : interface_decls function_decl { diff --git a/src/Load.cpp b/src/Load.cpp index afe7684..4b71fdd 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -118,7 +118,7 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl } bool Load::isConstExpr() { - Variable *symbol = dynamic_cast(ident.getSymbol(getScope())); + Node *symbol = ident.getSymbol(getScope()); return symbol && symbol->isConstExpr(); } diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 27a9b45..88d2581 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -63,8 +63,6 @@ Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc GlobalVariable *gv = new GlobalVariable(*mainmodule, matrixType, false, GlobalValue::InternalLinkage, ConstantArray::get(matrixType, constantRefs), name); - gv->setDSOLocal(true); - gv->setAlignment(Align(2)); alloc = gv; if (debug_info) { diff --git a/src/MemCopy.cpp b/src/MemCopy.cpp index 33cfc3d..7b6adec 100644 --- a/src/MemCopy.cpp +++ b/src/MemCopy.cpp @@ -49,6 +49,7 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo size = Builder->CreateBinOp(Instruction::Mul, elbytes, nelem, "matrixsize"); } else { TypeSize ts = dl.getTypeAllocSize(buildTypes->llvmType(dt)); + nelem = ConstantInt::get(Type::getInt8Ty(global_context), 1); size = ConstantInt::get(Type::getInt32Ty(global_context), ts); } @@ -79,7 +80,7 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo RobDbgInfo.declareVar(this, dest, allocblock); } - if (!dest || !expr || !leftvty->isPointerTy() || + if (!dest || !expr || //!leftvty->isPointerTy() || !exprvty->isPointerTy()) { yyerrorcpp("Can not copy these operands.", this); return NULL; diff --git a/src/Pointer.cpp b/src/Pointer.cpp index 0e79f90..277bc95 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -25,6 +25,12 @@ Value *Pointer::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo return NULL; } + if (!buildTypes->isDefined(dt)) { + yyerrorcpp(string_format("The type %s is undefined.", + buildTypes->name(dt)), this); + return NULL; + } + Type *targetPointerType = buildTypes->llvmType(dt)->getPointerTo(); if (allocblock == global_alloc) { diff --git a/src/Program.cpp b/src/Program.cpp index 1081802..85f9b43 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -25,7 +25,8 @@ Program::Program() : Node({0,0,0,0}) { "Robcmp", false, "", 0); // global scope - RobDbgInfo.push_scope(RobDbgInfo.cunit->getFile(), RobDbgInfo.cunit); + RobDbgInfo.push_file(RobDbgInfo.cunit->getFile()); + RobDbgInfo.push_scope(RobDbgInfo.cunit); } buildTypes = make_unique(currentTarget().pointerType); @@ -39,91 +40,6 @@ Program::~Program() { delete mainmodule; } -void Program::declara_auxiliary_c_funcs() { - std::vector arg_types; - FunctionType *ftype; - - #ifdef ENABLE_ARDUINO - // analogRead - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - ftype = FunctionType::get(Type::getInt16Ty(global_context), - ArrayRef(arg_types), false); - analogRead = Function::Create(ftype, Function::ExternalLinkage, "analogRead", mainmodule); - analogRead->setCallingConv(CallingConv::C); - - // analogWrite or digitalWrite - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - arg_types.push_back(Type::getInt16Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - analogWrite = Function::Create(ftype, Function::ExternalLinkage, "analogWrite", mainmodule); - - // digitalWrite instead - /*arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - arg_types.push_back(Type::getInt8Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - analogWrite = Function::Create(ftype, Function::ExternalLinkage, "digitalWrite", mainmodule); - */ - - analogWrite->setCallingConv(CallingConv::C); - - // delay - arg_types.clear(); - arg_types.push_back(Type::getInt32Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - delay = Function::Create(ftype, Function::ExternalLinkage, "delay", mainmodule); - delay->setCallingConv(CallingConv::C); - - - // delayMicroseconds - arg_types.clear(); - arg_types.push_back(Type::getInt32Ty(global_context)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - delayMicroseconds = Function::Create(ftype, Function::ExternalLinkage, "delayMicroseconds", mainmodule); - delayMicroseconds->setCallingConv(CallingConv::C); - - // init - ftype = FunctionType::get(Type::getVoidTy(global_context), false); - init = Function::Create(ftype, Function::ExternalLinkage, "init", mainmodule); - init->setCallingConv(CallingConv::C); - #endif - - #ifdef ENABLE_PRINT - // print - arg_types.clear(); - arg_types.push_back(Type::getInt8Ty(global_context)); - arg_types.push_back(PointerType::get(IntegerType::get(global_context, 8), 0)); - ftype = FunctionType::get(Type::getVoidTy(global_context), - ArrayRef(arg_types), false); - print = Function::Create(ftype, Function::ExternalLinkage, "print", mainmodule); - print->setCallingConv(CallingConv::C); - #endif - - /* Not necessary anymore. Stay as an example - AttributeSet print_func_attrs; - print_func_attrs = - print_func_attrs.addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::NoUnwind) - .addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::StackProtect) - .addAttribute(global_context, AttributeSet::FunctionIndex, Attribute::UWTable) - .addAttribute(global_context, 1, Attribute::ZExt); - print->setAttributes(print_func_attrs); */ - - // i16divse) - /*arg_types.clear(); - arg_types.push_back(Type::getInt16Ty(global_context)); - arg_types.push_back(Type::getInt16Ty(global_context)); - ftype = FunctionType::get(Type::getInt16Ty(global_context), - ArrayRef(arg_types), false); - i16div = Function::Create(ftype, Function::ExternalLinkage, "i16div", mainmodule); - i16div->setCallingConv(CallingConv::C);*/ -} - Value *Program::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { return NULL; } @@ -191,7 +107,7 @@ void Program::generateInjectionSetup(SourceLocation *sl) { new FunctionParams(), vector(), loc, loc, false); finject->setReturnIsPointer(true); finject->setScope(this); - finject->setInline(true); + finject->setAttributes(new FunctionAttributes(fa_inline)); if (scope == bs_singleton) { string globalVarName; @@ -243,10 +159,9 @@ void Program::generateInjectionSetup(SourceLocation *sl) { if (!aliasFunc) { aliasFunc = Function::Create(implFunc->getFunctionType(), Function::ExternalLinkage, codeAddrSpace, to_name, mainmodule); - aliasFunc->setDSOLocal(true); aliasFunc->setCallingConv(CallingConv::C); - aliasFunc->addFnAttr(Attribute::AlwaysInline); } + aliasFunc->addFnAttr(Attribute::AlwaysInline); auto fblock = BasicBlock::Create(global_context, "", aliasFunc); Builder->SetInsertPoint(fblock); @@ -309,7 +224,7 @@ void Program::generate() { n->generate(NULL, NULL, global_alloc); } - if (injections.size() > 0) { + if (mainFunc && injections.size() > 0) { generateInjectionSetup(mainFunc); FunctionCall *fc = new FunctionCall(":injections_init", new ParamsCall(), mainFunc->getLoc()); diff --git a/src/PropagateTypes.cpp b/src/PropagateTypes.cpp index f1bbdc6..1db5e58 100644 --- a/src/PropagateTypes.cpp +++ b/src/PropagateTypes.cpp @@ -135,12 +135,16 @@ DataType PropagateTypes::coerceArithOrCmp(Node &n, Node *lNode, Node *rNode) { return returnTy; } + if (buildTypes->isEnum(lTy)) + lTy = tint8; + if (buildTypes->isEnum(rTy)) + rTy = tint8; + uint lBWidth = buildTypes->bitWidth(lTy); uint rBWidth = buildTypes->bitWidth(rTy); // both sides integer if (buildTypes->isIntegerDataType(lTy) && buildTypes->isIntegerDataType(rTy)) { - bool lUnsigned = buildTypes->isUnsignedDataType(lTy); bool rUnsigned = buildTypes->isUnsignedDataType(rTy); @@ -210,16 +214,17 @@ DataType PropagateTypes::coerceArithOrCmp(Node &n, Node *lNode, Node *rNode) { return newTy; } + // Coerce between char and int8/uint8 if ((lTy == tchar && rTy == tint8u) || (lTy == tint8u && rTy == tchar)) return lTy; - else if (lTy == rTy) { + + if (lTy == rTy) { return lTy; - } else { - yyerrorcpp(string_format("FIXME: the pair %s and %s needs a coercion.", - buildTypes->name(lTy), buildTypes->name(rTy)), &n); - assert(returnTy != BuildTypes::undefinedType); } + yyerrorcpp(string_format("FIXME: the pair %s and %s needs a coercion.", + buildTypes->name(lTy), buildTypes->name(rTy)), &n); + assert(returnTy != BuildTypes::undefinedType); return returnTy; } @@ -245,6 +250,8 @@ Node* PropagateTypes::visit(FunctionImpl& n) { Node* PropagateTypes::visit(Return& n) { if (!n.value()){ n.dt = tvoid; + if (currentFunctionDt != tvoid) + yyerrorcpp(string_format("Return must be %s.", buildTypes->name(currentFunctionDt)), &n); return NULL; } else { propagateChildren(n); @@ -394,9 +401,13 @@ Node* PropagateTypes::visit(Enum& n) { Node* PropagateTypes::visit(Variable& n) { propagateChildren(n); + + bool checkCoercion = false; + DataType destDt = BuildTypes::undefinedType; Node *firstDecl = n.getScope()->findSymbol(n.getName()); DataType sameNameDt = buildTypes->getType(n.getName()); + if (sameNameDt != BuildTypes::undefinedType) { yyerrorcpp(string_format("The name %s is already used to define a type.", n.getName().c_str()), &n); if (firstDecl) @@ -404,21 +415,32 @@ Node* PropagateTypes::visit(Variable& n) { } else if (firstDecl && firstDecl != &n) { DataType ndt = n.getDataType(); - DataType fdt = firstDecl->getDataType(); + destDt = firstDecl->getDataType(); if (ndt != BuildTypes::undefinedType && - fdt != BuildTypes::undefinedType && - ndt != fdt) { - // the var was first defined as fdt. + destDt != BuildTypes::undefinedType && + ndt != destDt) { + // the var was first defined as destDt. // we coherce the right hand side to match it - Node *result = NULL; - if (Scalar *sc = dynamic_cast(&n)) { - result = coerceTo(sc->expr(), fdt); - sc->setExpr(result); - } - if (!result) - yywarncpp(string_format("The symbol %s was first defined here.", n.getName().c_str()), firstDecl); + checkCoercion = true; } } + + Node *expr = n.getExpr(); + if (expr && (n.getDataType() != expr->getDataType())) { + // the variable type is distinct from the right hand side + // this can occur when using types, e.g. usertype.x = newvalue; + destDt = n.getDataType(); + checkCoercion = true; + } + + if (checkCoercion) { + Node *result = NULL; + result = coerceTo(expr, destDt); + n.setExpr(result); + if (!result) + yywarncpp(string_format("The symbol %s was first defined here.", n.getName().c_str()), firstDecl); + } + return NULL; } @@ -429,13 +451,18 @@ Node* PropagateTypes::visit(Scalar& n) { // although this should be done on SymbolizeTree, // some type propagarion in the tree change symbols // for scalars (e.g. FunctionCall -> ConstructorCall) - auto& exprSymbols = n.expr()->getSymbols(); + auto& exprSymbols = n.getExpr()->getSymbols(); if (exprSymbols.size() > 0) n.symbols = exprSymbols; return NULL; } Node* PropagateTypes::visit(Load& n) { + // skip the :parent field. For nested user types, + // the parameter doesn't exists at this point + if (n.getName() == ":parent") + return NULL; + // although this should be done on SymbolizeTree, // some type propagarion in the tree change symbols // for scalars (e.g. FunctionCall -> ConstructorCall) diff --git a/src/Scalar.cpp b/src/Scalar.cpp index a611137..2484f7a 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -3,7 +3,6 @@ #include "FunctionImpl.h" #include "BackLLVM.h" #include "Pointer.h" -#include "PropagateTypes.h" Scalar::Scalar(Identifier ident, Node *e) : Variable(ident.getFullName(), ident.getLoc()) { @@ -48,12 +47,13 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc // set the allocated left value to: // - a constructor initializing a user type field // - a load for a new variable - expr()->setLeftValue(symbol); + Node *expr = getExpr(); + expr->setLeftValue(symbol); - Value *exprv = expr()->generate(func, block, allocblock); + Value *exprv = expr->generate(func, block, allocblock); if (!exprv) return NULL; - DataType exprv_dt = expr()->getDataType(); + DataType exprv_dt = expr->getDataType(); Builder->SetInsertPoint(block); if (!alloc) @@ -76,16 +76,18 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc ret = alloc = exprvc; else { Type *gty = buildTypes->llvmType(dt); - if (expr()->isPointerToPointer()) + if (expr->isPointerToPointer()) gty = gty->getPointerTo(); GlobalVariable *gv = new GlobalVariable(*mainmodule, gty, false, - GlobalValue::InternalLinkage, exprvc, name); - gv->setDSOLocal(true); + GlobalValue::ExternalLinkage, exprvc, name); ret = alloc = gv; if (debug_info) { + llvm::DIType *dty = buildTypes->diType(dt); + if (expr->isPointerToPointer()) + dty = buildTypes->diPointerType(dt); auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", - funit, getLineNo(), buildTypes->diType(dt), false); + funit, getLineNo(), dty, false); gv->addDebugInfo(d); } } @@ -93,7 +95,6 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(allocblock); AllocaInst *temp = Builder->CreateAlloca(exprv->getType(), dataAddrSpace, 0, name); - temp->setAlignment(Align(1)); alloc = temp; Builder->SetInsertPoint(block); ret = Builder->CreateStore(exprv, alloc, symbol->hasQualifier(qvolatile)); @@ -177,8 +178,13 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc } DataType Scalar::getDataType() { - if (dt == BuildTypes::undefinedType) - return dt = expr()->getDataType(); - else - return dt; + if (dt == BuildTypes::undefinedType) { + if (ident.isComplex()) { + Node *symbol = ident.getSymbol(getScope(), false); + if (symbol) + dt = symbol->getDataType(); + } else + dt = getExpr()->getDataType(); + } + return dt; } diff --git a/src/Scalar.h b/src/Scalar.h index 4076c31..898cdd8 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -10,11 +10,11 @@ class Scalar: public Variable { Scalar(Identifier ident, Node *e); - Node *expr() { + virtual Node *getExpr() override { return node_children[0]; } - void setExpr(Node *expr) { + virtual void setExpr(Node *expr) override { node_children[0] = expr; dt = expr->getDataType(); } @@ -22,7 +22,7 @@ class Scalar: public Variable { virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; virtual bool isConstExpr() override { - return hasQualifier(qconst) && expr()->isConstExpr(); + return hasQualifier(qconst) && getExpr()->isConstExpr(); } virtual DataType getDataType() override; diff --git a/src/Scanner.cpp b/src/Scanner.cpp index 39b233f..554897c 100644 --- a/src/Scanner.cpp +++ b/src/Scanner.cpp @@ -87,7 +87,8 @@ bool parseFile(const string& source) { buildStackScanner.push_back(scanner); MAINset_in(f, scanner); - program = new Program(); + if (program == NULL) + program = new Program(); MAINparse(scanner); @@ -99,6 +100,14 @@ bool parseFile(const string& source) { FILE *findFile(string file_name, filesystem::path& file_path) { FILE *f = NULL; + + // test current dir + filesystem::path test_path = file_name; + f = fopen(test_path.string().c_str(), "r"); + if (f) { + file_path = test_path; + return f; + } // include the dir of the current file if (useStack.size() > 0) @@ -120,18 +129,27 @@ FILE *findFile(string file_name, filesystem::path& file_path) { return f; } -bool parseUseFile(const string& use, location_t loc) { +bool parseUseFile(const string& use, location_t loc, bool isPath) { // search for and open {use}.rob file - const string sep{filesystem::path::preferred_separator}; - string use_file = regex_replace(use, regex("\\."), sep); - string file_name = use_file + ".rob"; + string file_name; + if (isPath) + file_name = use; + else { + const string sep{filesystem::path::preferred_separator}; + string use_file = regex_replace(use, regex("\\."), sep); + file_name = use_file + ".rob"; + } filesystem::path file_path; FILE *f = findFile(file_name, file_path); if (f == NULL) { - SourceLocation s(loc); - yyerrorcpp(string_format(file_not_found, file_name.c_str()), &s); + if (loc.first_line == 0) // spec file + cerr << string_format(file_not_found, file_name.c_str()); + else { + SourceLocation s(loc); + yyerrorcpp(string_format(file_not_found, file_name.c_str()), &s); + } return false; } @@ -164,9 +182,18 @@ bool parseUseFile(const string& use, location_t loc) { MAINset_in(f, scanner); //extern int USEdebug; //USEdebug = 1; - if (build_dependencies) + if (build_dependencies) { + if (debug_info) { + string bPath = buildStack[buildStackCurrent]; + DIFile *file = DBuilder->createFile(bPath, std::filesystem::current_path().string()); + RobDbgInfo.push_file(file); + } + MAINparse(scanner); - else + + if (debug_info) + RobDbgInfo.pop_file(); + } else USEparse(scanner); MAINlex_destroy(scanner); diff --git a/src/Scanner.h b/src/Scanner.h index 25ac814..a6a9acf 100644 --- a/src/Scanner.h +++ b/src/Scanner.h @@ -22,4 +22,4 @@ void yyerrorcpp(const string& s, SourceLocation *n, bool semantic); void yywarncpp(const string& s, SourceLocation *n); bool parseFile(const string &source); -bool parseUseFile(const string& use, location_t loc); +bool parseUseFile(const string& use, location_t loc, bool isPath = false); diff --git a/src/Spec.l b/src/Spec.l deleted file mode 100644 index bb1e32f..0000000 --- a/src/Spec.l +++ /dev/null @@ -1,53 +0,0 @@ -%{ - -#include "FlexDependencies.h" -#include "Spec_y.hpp" - -extern void unescape(char *s); -void specerror(YYLTYPE *loc, yyscan_t yyscanner, const char *s); - -%} - -%option noinput nounput noyywrap -%option yylineno -%option reentrant bison-locations -%option prefix="spec" - -%option yylineno - -D [0-9] -L [a-zA-Z] - -%% - - -[ \t\n\r] { /* espaços */ } - -"port" { return SPEC_PORT; } -"digital" { return SPEC_DIGITAL; } -"pwm" { return SPEC_PWM; } -"name" { return SPEC_NAME; } - -"bind" { return SPEC_BIND; } - -"true" { return SPEC_TRUE; } -"false" { return SPEC_FALSE; } - -"to" { return SPEC_TO; } - -\"[^\"]+\" { yylval->str = strndup(yytext+1, yyleng-2); unescape(yylval->str); return SPEC_STRING; } - -"{" { return '{'; } -"}" { return '}'; } - -"=" { return '='; } -":" { return ':'; } -";" { return ';'; } - -{L}({L}|{D})*(\.({L}|{D})*)* { yylval->ident = strndup(yytext, yyleng); unescape(yylval->ident); return SPEC_XIDENT; } - - -. { specerror(yylloc, NULL, "lexical error, caractere nao pertence ao alfabeto da linguagem:"); } - -%% - diff --git a/src/Spec.y b/src/Spec.y deleted file mode 100644 index 8fce795..0000000 --- a/src/Spec.y +++ /dev/null @@ -1,128 +0,0 @@ -%{ - -%} - -%locations -%define api.location.type {location_t} -%define api.pure full -%param {yyscan_t scanner} - -%name-prefix="spec" -//%define api.prefix {spec} // not working in Bison 3.8.2 - -%code provides { - #define YY_DECL int speclex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) - YY_DECL; - void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); -} - -%code top { - #ifndef YYLTYPE - #define YYLTYPE location_t - #endif - #include "FlexDependencies.h" - #define SCANNER_OR_VISITOR - #include "Header.h" -} - -%union { - // char *port; - char *ident; - char *str; - - - Node *node; - // Stmts *stmt; - // vector *nodes; - -} - -/* %union { - char *ident; - char *str; - int64_t nint; - float nfloat; - double ndouble; - long double nldouble; - Node *node; - ArrayElements *aes; - MatrixElements *mes; - FunctionParams *fps; - ParamsCall *pc; - vector *nodes; - vector *strings; - ArrayElement *ae; - MatrixElement *me; - FunctionParam *fp; -} */ - -%token SPEC_PORT SPEC_PORT_NAME SPEC_DIGITAL SPEC_BIND SPEC_IDENT SPEC_TO SPEC_XIDENT -%token SPEC_PWM SPEC_NAME SPEC_TRUE SPEC_FALSE SPEC_PORT_IDENT SPEC_STRING - -/* %type globals */ -/* %type global bind */ -%type bind -%type SPEC_IDENT SPEC_XIDENT ident - - - -%start program - -%% - -program : %empty - | stmts - ; - -stmts : stmts stmt - | stmt - ; - -stmt : bind - /* | port_statement */ - ; - - -bind : SPEC_BIND ident[id] SPEC_TO ident[to] ';' { - injections.insert({$to, make_pair(string($id), BindScope(bs_singleton))}); -} - -ident : SPEC_IDENT - | SPEC_XIDENT - ; - -/* port_statement : SPEC_PORT_NAME '{' port_attributes '}' - ; - -port_attributes : port_attributes port_attribute - | port_attribute - ; - -port_attribute : attribute_digital - | attribute_pwm - | port_bind - ; - -attribute_digital : SPEC_DIGITAL '=' SPEC_TRUE - | SPEC_DIGITAL '=' SPEC_FALSE - ; - -attribute_pwm : SPEC_PWM '=' SPEC_TRUE - | SPEC_PWM '=' SPEC_FALSE - ; - -port_bind : SPEC_BIND '=' SPEC_IDENT { } - ; */ - - -%% - -extern char *spec_filename; -extern int errorsfound; - -void specerror(YYLTYPE *loc, yyscan_t yyscanner, const char *s) -{ - fprintf(stderr, "%s:%d: error: %s\n", spec_filename, loc->first_line, s); - errorsfound++; -} - diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index 236b6a6..286ef5d 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -30,6 +30,7 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * return NULL; } + Builder->SetInsertPoint(block); Value *sym = symbol->getLLVMValue(func); // sym type can be GlobalVariable or AllocInst diff --git a/src/UserType.cpp b/src/UserType.cpp index 29000ba..7515734 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -1,6 +1,8 @@ #include "UserType.h" +#include "FunctionAttributes.h" #include "HeaderGlobals.h" +#include "Identifier.h" #include "Interface.h" #include "FunctionImpl.h" #include "FunctionDecl.h" @@ -15,8 +17,12 @@ class ParentScalar: public Scalar { public: - ParentScalar(DataType parentDt, location_t loc) : Scalar("parent", new Load("parent", loc)) { - expr()->setScope(this); + ParentScalar(DataType parentDt, location_t loc) : + Scalar(Identifier("parent", loc), NULL) { + Load *load = new Load(":parent", loc); + load->setDataType(parentDt); + load->setScope(this); + setExpr(load); dt = parentDt; pointer = pm_pointer; } @@ -44,7 +50,6 @@ bool UserType::createDataType() { int idx = 0; unsigned startBit = 0; - vector addedVars; // if needed, add typeid as the first field UInt8 *typeId = NULL; @@ -52,7 +57,7 @@ bool UserType::createDataType() { typeId = new UInt8(0, getLoc()); // zero is changed below Scalar *sc = new Scalar("typeid", typeId); sc->setScope(this); - addChild(sc); + addChild(sc, true); addSymbol(sc); } @@ -77,7 +82,7 @@ bool UserType::createDataType() { v->dt = ut->getDataType(); cc->setScope(v); v->setScope(this); - addedVars.push_back(v); + addChild(v); // fix the symbol table due to the renaming getScope()->addSymbol(ut); @@ -119,11 +124,6 @@ bool UserType::createDataType() { } bitWidth = startBit; - for(auto a: addedVars) { - addChild(a); - addSymbol(a); - } - StructType *uttype = StructType::create(global_context, ArrayRef(elements), getName()); dt = buildTypes->addDataType(this, uttype, bitWidth); if (parent) @@ -166,6 +166,21 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all } } + /* set function parameters before generate + * A function can call others that are still not generated + * and request their type info. So, here we set all needed + * info to pre-generate their type. + */ + for(auto & [key, stmt] : getSymbols()) { + if (FunctionImpl *f = dynamic_cast(stmt)) { + f->setPrefixName(getName()); + f->addThisArgument(dt); + for(auto &field : fields) + f->addSymbol(dynamic_cast(field)); + f->setExternal(declaration); + } + } + // generate user types and enums for(auto & [key, stmt] : getSymbols()) { if (UserType *ut = dynamic_cast(stmt)) { @@ -186,28 +201,16 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all std::move(fields), getLoc(), getLoc(), true); } finit->addThisArgument(dt); - if (parent) + if (parent) { finit->addParentArgument(parent->getDataType()); + // nested user types can be inlined in the parent init + finit->getAttributes()->addAttribute(fa_inline); + } finit->setPrefixName(getName()); finit->setExternal(declaration); finit->setConstructor(true); finit->generate(func, block, allocblock); - /* set function parameters before generate - * A function can call others that are still not generated - * and request their type info. So, here we set all needed - * info to pre-generate their type. - */ - for(auto & [key, stmt] : getSymbols()) { - if (FunctionImpl *f = dynamic_cast(stmt)) { - f->setPrefixName(getName()); - f->addThisArgument(dt); - for(auto &field : fields) - f->addSymbol(dynamic_cast(field)); - f->setExternal(declaration); - } - } - // generate functions for(auto & [key, stmt] : getSymbols()) { if (FunctionImpl *f = dynamic_cast(stmt)) { @@ -238,5 +241,12 @@ const string UserType::getName() const { void UserType::addSymbol(NamedNode *nm) { // addSymbol is overrided here because UserType has its // own scope and shouldn't call findSymbol recursivelly - symbols[nm->getName()] = nm; + const string& label = nm->getName(); + auto it = symbols.find(label); + if (it != symbols.end()) { + yyerrorcpp(string_format("Symbol %s already declared for this type.", label.c_str()), nm); + yywarncpp("The first declaration is here.", it->second); + } + else + symbols[nm->getName()] = nm; } diff --git a/src/Variable.cpp b/src/Variable.cpp index d95cf67..5b3bc1e 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -18,7 +18,8 @@ Value *Variable::getLLVMValue(Node *stem) { // in the global or same scope, defer :this and gep the field alloc = Builder->CreateStructGEP(thisTy, thisptr, gepidx, "gepthis"); } else { - // in distinct scopes, access :parent (gep 0) in :this and gep the field + // FIXME: in distinct scopes, access :parent (gep 0 or 1) in :this and gep the field + // currently, the CreateStructGEP deference 0; but zero sometimes is the typeid var Type *parentTy = buildTypes->llvmType(this->getScope()->getDataType()); Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, 0, "gepthis"); Value *parentptr = Builder->CreateLoad(parentTy->getPointerTo(), parentAlloc, "derefparent"); diff --git a/src/Variable.h b/src/Variable.h index 2f253f6..216e252 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -42,4 +42,9 @@ class Variable: public NamedNode { this->alloc = alloc; } + virtual Node *getExpr() { + return NULL; + } + + virtual void setExpr(Node *e) {} }; diff --git a/src/main.cpp b/src/main.cpp index 3fb51f3..db613a6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,9 +5,9 @@ #include "Scanner.h" #include "Program.h" -Program *program; +Program *program = NULL; -void print_llvm_ir(char opt_level); +int print_llvm_ir(char opt_level); bool debug_info; bool build_dependencies; char *build_outputfilename; @@ -94,31 +94,27 @@ int main(int argc, char *argv[]) { i++; } - if (specin) { - yyscan_t scanner; - speclex_init(&scanner); - specset_in(specin, scanner); - specparse(scanner); - speclex_destroy(scanner); - fclose(specin); - } - // set current target and basic build types setTarget(targetarch); - if (!parseFile(buildFileName)) + if (!buildFileName || !parseFile(buildFileName)) exit(1); + if (specin) { + if (!parseUseFile(spec_filename, {0,0,0,0}, true)) + exit(1); + } + program->doSemanticAnalysis(); - if (errorsfound > 0) { - fprintf(stderr, "%d error(s) found.\n", errorsfound); - } else { + if (errorsfound <= 0) program->generate(); - } if (errorsfound <= 0) - print_llvm_ir(optimization); + errorsfound = print_llvm_ir(optimization); + + if (errorsfound > 0) + fprintf(stderr, "%d error(s) found.\n", errorsfound); return errorsfound; } diff --git a/test/avr328p/bitstruct-field-i5.rob b/test/avr328p/bitstruct-field-i5.rob new file mode 100644 index 0000000..025393b --- /dev/null +++ b/test/avr328p/bitstruct-field-i5.rob @@ -0,0 +1,18 @@ +/* + * Tests I2C start condition + */ + +use arch.avr.avr5regs; + +int8 main() { + + TWCR = ETWCR.TWSTA | ETWCR.TWEN | ETWCR.TWINT; + while TWCR & ETWCR.TWINT == 0; + + if TWSR.TWS != (0x8 >> 3) { + return 1; + } + + return 0; +} + diff --git a/test/avr328p/bsscheck.rob b/test/avr328p/bsscheck.rob index fcc0dc4..56f3e0f 100644 --- a/test/avr328p/bsscheck.rob +++ b/test/avr328p/bsscheck.rob @@ -4,8 +4,14 @@ before main, is working properly. */ +random_seed16 = 0xE7A8; matrix = {{0u:128}:8}; +uint16 check_random(uint8 row) { + random_seed16 += row; + return random_seed16; +} + int8 main() { row = 0u; while row < matrix.rows { @@ -18,6 +24,9 @@ int8 main() { } row++; } + if check_random(row) != 0xE7A8 + 8 { + return 2; + } return 0; } diff --git a/test/avr328p/datacheck.rob b/test/avr328p/datacheck.rob new file mode 100644 index 0000000..cb74e1b --- /dev/null +++ b/test/avr328p/datacheck.rob @@ -0,0 +1,20 @@ + +/* This test case allocates a variable in data region. + It tests if the assembly func __do_data_copy, called + before main, is working properly. + */ + +random_seed16 = 0xE7A8; + +uint16 check_random() { + random_seed16 += 1; + return random_seed16; +} + +int8 main() { + if check_random() != 0xE7A9 { + return 2; + } + return 0; +} + diff --git a/test/avr328p/globaldata.rob b/test/avr328p/globaldata.rob new file mode 100644 index 0000000..279deb5 --- /dev/null +++ b/test/avr328p/globaldata.rob @@ -0,0 +1,12 @@ + +random_seed16 = 0xE7A8; + +int8 main() { + + if random_seed16 == 0xE7A8 { + return 0; + } else { + return 1; + } +} + diff --git a/test/avr328p/uartdata.rob b/test/avr328p/uartdata.rob new file mode 100644 index 0000000..8b0d314 --- /dev/null +++ b/test/avr328p/uartdata.rob @@ -0,0 +1,33 @@ + +use arch.avr.avr5mcu; +use convert.itoa; + +random_seed16 = 0xE7A8; + +uint16 check_random() { + random_seed16 += 1; + return random_seed16; +} + +void print_result(databus s, char[] result) { + i = 0; + while result[i] != 0 { + s.write(result[i]); + i++; + } + s.write('\n'); +} + +int16 main() { + mmcu = avr5mcu(); + serial = mmcu.uart0; + serial.setup(9600); + + a = check_random(); + result = {'\0':18}; + itoa(a, 10, result); + print_result(serial, result); + + return 0; +} + diff --git a/test/debug/platformio.ini b/test/debug/platformio.ini index b75fd8c..ced8e26 100644 --- a/test/debug/platformio.ini +++ b/test/debug/platformio.ini @@ -9,4 +9,4 @@ build_type = release [env:debug] build_type = debug -debug_tool = robcmp +debug_tool = robcmp-ssd1306 diff --git a/test/general/bind.spec b/test/general/bind.spec index d4fd20e..0e7d181 100644 --- a/test/general/bind.spec +++ b/test/general/bind.spec @@ -1,5 +1,5 @@ -bind b3 to display.reset; +bind b3 to display.reset singleton; diff --git a/test/general/function_attribs.rob b/test/general/function_attribs.rob new file mode 100644 index 0000000..3dba8d2 --- /dev/null +++ b/test/general/function_attribs.rob @@ -0,0 +1,10 @@ + +void func_attribs() inline, weak { + return; +} + +int8 main() { + func_attribs(); + return 0; +} + From bf02fceb977a4ebefb06fdf76fac8d727bb0d776 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Fri, 21 Jun 2024 22:20:58 -0300 Subject: [PATCH 060/117] Allows empty void functions. --- lib/arch/stm32/stm32f1.rob | 74 +++++++------------------------ src/Language.y | 10 +++-- test/general/Return_in_While.rob | 6 +-- test/general/byref.rob | 4 +- test/general/fibonacci.rob | 4 +- test/general/function_attribs.rob | 1 - test/general/simplescope.rob | 2 +- test/general/simplesubtype.rob | 4 +- test/general/unsigned.rob | 2 +- 9 files changed, 31 insertions(+), 76 deletions(-) diff --git a/lib/arch/stm32/stm32f1.rob b/lib/arch/stm32/stm32f1.rob index 1557257..d2657c3 100644 --- a/lib/arch/stm32/stm32f1.rob +++ b/lib/arch/stm32/stm32f1.rob @@ -91,36 +91,15 @@ type stm32f1 implements mcu { xx = MOSI xx = MISO xx = SCK */ - void setup(uint32 speed) { - return; - } - - void enable() { - return; - } - - void disable() { - return; - } - - void write(uint8 b) { - return; - } - - void write_array(int8[] data) { - return; - } - - uint8 read() { - return 0; - } - - bool has_data() { - return false; - } - + void setup(uint32 speed) {} + void enable() {} + void disable() {} + void write(uint8 b) {} + void write_array(int8[] data) {} + uint8 read() { return 0; } + bool has_data() { return false; } bool start_transaction(uint16 address) { return true; } - void end_transaction() { return; } + void end_transaction() { } databus_protocol get_protocol() { return databus_protocol.SPI; @@ -128,36 +107,15 @@ type stm32f1 implements mcu { } uart0 implements databus { - void setup(uint32 baud) { - return; - } - - void enable() { - return; - } - - void disable() { - return; - } - - void write(uint8 b) { - return; - } - - void write_array(int8[] data) { - return; - } - - uint8 read() { - return 0; - } - - bool has_data() { - return false; - } - + void setup(uint32 baud) {} + void enable() {} + void disable() {} + void write(uint8 b) {} + void write_array(int8[] data) {} + uint8 read() { return 0; } + bool has_data() { return false; } bool start_transaction(uint16 address) { return true; } - void end_transaction() { return; } + void end_transaction() {} databus_protocol get_protocol() { return databus_protocol.UART; diff --git a/src/Language.y b/src/Language.y index 42b58b6..19e1a04 100644 --- a/src/Language.y +++ b/src/Language.y @@ -10,7 +10,7 @@ } %type globals type_stmts enum_items interface_decls -%type stmts elseblock +%type stmts stmts_rec elseblock %type global register interface type type_stmt use %type function function_decl function_impl returnblock %type enum enum_item interface_impl @@ -300,11 +300,13 @@ element : expr ':' TOK_INTEGER { $$ = new ArrayElement($1, (unsigned)$3); } asminline : TOK_ASM TOK_STRING { $$ = $2; } -stmts : stmts stmt { +stmts : %empty { $$ = new vector(); } + | stmts_rec + +stmts_rec : stmts_rec stmt { $1->push_back($stmt); } - -stmts : stmt { +stmts_rec : stmt { $$ = new vector(); $$->push_back($stmt); $stmt->setLocation(@stmt); diff --git a/test/general/Return_in_While.rob b/test/general/Return_in_While.rob index 8435a77..b70c4d8 100644 --- a/test/general/Return_in_While.rob +++ b/test/general/Return_in_While.rob @@ -1,20 +1,20 @@ void fb(int16 a) { b = a; - while(b > 3) { + while b > 3 { b = b - 1; } } double fa(int16 a) { b = a; - while(b > 3) { + while b > 3 { b = b - 1; return b; } return 0; } -int16 main (){ +int16 main () { fa(10); fb(10); return 0; diff --git a/test/general/byref.rob b/test/general/byref.rob index 4e6b72b..095aa0c 100644 --- a/test/general/byref.rob +++ b/test/general/byref.rob @@ -16,9 +16,7 @@ type main_t { } ii implements intf { - void print(int8 v) { - return; - } + void print(int8 v) {} } } diff --git a/test/general/fibonacci.rob b/test/general/fibonacci.rob index a7a453a..f5d26da 100644 --- a/test/general/fibonacci.rob +++ b/test/general/fibonacci.rob @@ -21,8 +21,8 @@ int8 main() { }; i = 0u; - while (i < check.size) { - if (result[i] != check[i]) { + while i < check.size { + if result[i] != check[i] { return 1; } i++; diff --git a/test/general/function_attribs.rob b/test/general/function_attribs.rob index 3dba8d2..b662099 100644 --- a/test/general/function_attribs.rob +++ b/test/general/function_attribs.rob @@ -1,6 +1,5 @@ void func_attribs() inline, weak { - return; } int8 main() { diff --git a/test/general/simplescope.rob b/test/general/simplescope.rob index d2fc3d2..62a8930 100644 --- a/test/general/simplescope.rob +++ b/test/general/simplescope.rob @@ -2,7 +2,7 @@ int16 main() { i = 0; - while (i < 6) { + while i < 6 { i++; } return i != 6; diff --git a/test/general/simplesubtype.rob b/test/general/simplesubtype.rob index 036c0fe..7d2ba24 100644 --- a/test/general/simplesubtype.rob +++ b/test/general/simplesubtype.rob @@ -5,9 +5,7 @@ interface a { type b { x implements a { - void print() { - return; - } + void print() { } } } diff --git a/test/general/unsigned.rob b/test/general/unsigned.rob index bf35150..e6e0b71 100644 --- a/test/general/unsigned.rob +++ b/test/general/unsigned.rob @@ -8,7 +8,7 @@ uint16 func_a(uint16 x) { int16 main() { b = 130U; a = func_a(b); - if (a == 10u) { + if a == 10u { return 0; } else { return 1; From 5d93813e397b72289d509bcc1894e0a1e3d93b4f Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 22 Jun 2024 20:49:49 -0300 Subject: [PATCH 061/117] Fixes parent field setting and improves/fixes debug information --- src/BackLLVM.cpp | 15 ++-- src/BuildTypes.cpp | 175 +++++++++++++++++++++++++++++++---------- src/BuildTypes.h | 10 +++ src/DebugInfo.cpp | 15 ++++ src/HeaderGlobals.h | 1 + src/Identifier.cpp | 2 +- src/Pointer.cpp | 27 ++++--- src/Program.cpp | 2 + src/PropagateTypes.cpp | 1 + src/Scalar.cpp | 13 +-- src/UserType.cpp | 56 ++++++------- src/UserType.h | 20 +++-- src/Variable.cpp | 16 ++-- src/main.cpp | 3 + 14 files changed, 249 insertions(+), 107 deletions(-) diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index b117f3c..5e101d7 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -37,6 +37,7 @@ std::unique_ptr> Builder; std::unique_ptr DBuilder; struct DebugInfo RobDbgInfo; std::unique_ptr buildTypes; +TargetMachine *targetMachine; unsigned int codeAddrSpace = 1; unsigned int dataAddrSpace = 0; @@ -55,8 +56,8 @@ TargetInfo supportedTargets[__last_target] = { {rb_xtensa, "esp32", "xtensa", "", "", tint32}, }; -int print_llvm_ir(char opt_level) { - +void setup_target_machine(char opt_level) { + const TargetInfo& ai = currentTarget(); if (ai.backend == rb_native) { // Native target init @@ -79,7 +80,7 @@ int print_llvm_ir(char opt_level) { LLVMInitializeARMAsmPrinter(); } else { cerr << "No backend set for target " << ai.triple << ".\n"; - return 1; + return; } std::string defaultt = sys::getDefaultTargetTriple(); @@ -120,12 +121,16 @@ int print_llvm_ir(char opt_level) { break; } - auto targetMachine = Target->createTargetMachine(ai.triple, + targetMachine = Target->createTargetMachine(ai.triple, ai.cpu, ai.features, opt, reloc, CodeModel::Small, cgoptl); + const DataLayout dl = targetMachine->createDataLayout(); - mainmodule->setDataLayout(targetMachine->createDataLayout()); + mainmodule->setDataLayout(dl); mainmodule->setTargetTriple(ai.triple); mainmodule->setFramePointer(FramePointerKind::All); +} + +int print_llvm_ir(char opt_level) { PassBuilder passBuilder(targetMachine); auto loopAnalysisManager = LoopAnalysisManager{}; diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 1c302c6..b3fd092 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -1,12 +1,21 @@ #include "BuildTypes.h" #include "HeaderGlobals.h" +#include "Identifier.h" +#include "NamedConst.h" #include "Node.h" +#include "Program.h" #include "Scanner.h" #include "Variable.h" +#include "Array.h" +#include "Matrix.h" +#include "UserType.h" #include "BackLLVM.h" +#include "Int8.h" + +BuildTypes::BuildTypes(DataType targetPointerType) : + targetPointerType(targetPointerType) { -BuildTypes::BuildTypes(DataType targetPointerType) { tinfo[tvoid] = {"void", 0, Type::getVoidTy(global_context), dwarf::DW_ATE_address}; tinfo[tbool] = {"bool", 1, Type::getInt1Ty(global_context), dwarf::DW_ATE_boolean}; tinfo[tchar] = {"char", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned_char}; @@ -106,12 +115,13 @@ DataType BuildTypes::getType(const string& name, bool createUndefined) { DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBitWidth, bool isEnum) { - const string& name = userType->getName(); + string name = userType->getName(); + if (UserType *ut = dynamic_cast(userType)) + name = ut->getTypeName(); auto udt = namedTypes.find(name); DataType id; - const DataLayout &dl = mainmodule->getDataLayout(); - + const DataLayout& dl = mainmodule->getDataLayout(); uint64_t bitWidth = typeBitWidth; if (typeBitWidth == 0 && llvmType->isSized()) typeBitWidth = dl.getTypeAllocSizeInBits(llvmType); @@ -132,44 +142,6 @@ DataType BuildTypes::addDataType(Node* userType, Type* llvmType, unsigned typeBi info.bitWidth = bitWidth; info.isInternal = false; info.isInterface = false; - - if (debug_info) { - unsigned offset = 0; - vector elems; - vector members; - for(auto& [key, m] : userType->getSymbols()) { - if (Node *n = dynamic_cast(m)) - members.push_back(n); - } - - //assert((members.size() == llvmType->getNumContainedTypes()) && - // "Number of fields differ between LLVM Type and Node."); - - int i = 0; - elems.reserve(members.size()); - for(Node *m : members) { - DataType mdt = m->getDataType(); - if (mdt == -1 || tinfo[mdt].bitWidth == 0) { - continue; - } - Type *memberTy = llvmType->getContainedType(i); - uint64_t memberBitWidth = dl.getTypeSizeInBits(memberTy); - uint32_t memberAlign = dl.getABITypeAlign(memberTy).value(); - DIType *di = DBuilder->createMemberType(RobDbgInfo.currScope(), m->getName(), - RobDbgInfo.currFile(), m->getLineNo(), - memberBitWidth, memberAlign, offset, DINode::DIFlags::FlagZero, - diType(m->getDataType())); - elems.push_back(di); - offset += memberBitWidth; - i++; - } - auto dielems = DBuilder->getOrCreateArray(elems); - info.diType = DBuilder->createClassType(RobDbgInfo.currScope(), name, - RobDbgInfo.currFile(), userType->getLineNo(), bitWidth, 1, 0, - DINode::DIFlags::FlagZero, nullptr, dielems); - unsigned ptbw = tinfo[currentTarget().pointerType].bitWidth; - info.diPointerType = DBuilder->createPointerType(info.diType, ptbw); - } return id; } @@ -179,3 +151,122 @@ Type *BuildTypes::llvmType(DataType tid) { else return tinfo[tid].llvmType; } + +void BuildTypes::generateDebugInfoForEnum(DataTypeInfo &info, Node *userType) { + + unsigned offset = 0; + vector elems; + + for(auto *m : userType->children()) { + if (NamedConst *n = dynamic_cast(m)) { + Node *value = n->getValue(); + uint8_t v = 0; + if (Int8 *i8 = dynamic_cast(value)) + v = i8->getNumber(); + else if (UInt8 *ui8 = dynamic_cast(value)) + v = ui8->getNumber(); + else + assert(0 && "Unknown enum value node."); + + auto etor = DBuilder->createEnumerator(n->getName(), v); + elems.push_back(etor); + } else + assert(0 && "Unknown enum node."); + } + + auto dielems = DBuilder->getOrCreateArray(elems); + info.diType = DBuilder->createEnumerationType(RobDbgInfo.currScope(), info.name, + RobDbgInfo.currFile(), userType->getLineNo(), info.bitWidth, 1, + dielems, tinfo[tint8].diType); +} + +void BuildTypes::generateDebugInfoForUserType(DataTypeInfo &info, Node *userType) { + + const DataLayout& dl = mainmodule->getDataLayout(); + unsigned offset = 0; + vector elems; + vector members; + for(auto *m : userType->children()) { + if (Node *n = dynamic_cast(m)) + members.push_back(n); + } + + //assert((members.size() == llvmType->getNumContainedTypes()) && + // "Number of fields differ between LLVM Type and Node."); + + elems.reserve(members.size()); + for(Node *m : members) { + DataType mdt = m->getDataType(); + if (isInterface(mdt)) { + // search the injections + string fieldName = info.name; + fieldName.append("." + m->getName()); + string injType = injections[fieldName].first; + Node *symbol = Identifier(injType, userType->getLoc()).getSymbol(program, false); + mdt = symbol->getDataType(); + } + if (mdt == -1 || tinfo[mdt].bitWidth == 0) { + continue; + } + + Type *memberTy = tinfo[mdt].llvmType; + DIType *memberDiType = diType(mdt); + if (Variable *v = dynamic_cast(m)) { + if (v->getPointerMode() == pm_pointer) { + memberTy = memberTy->getPointerTo(); + memberDiType = diPointerType(mdt); + if (!memberDiType) { + // parent field + memberDiType = diPointerType(targetPointerType); + } + } + } + + uint64_t memberBitWidth = dl.getTypeAllocSizeInBits(memberTy); + if (memberTy->isArrayTy()) { + memberBitWidth = dl.getTypeAllocSizeInBits(memberTy->getArrayElementType()); + if (Matrix *matrix = dynamic_cast(m)) + memberBitWidth *= matrix->getRows() * matrix->getCols(); + else if (Array *array = dynamic_cast(m)) + memberBitWidth *= array->getSize(); + } + uint32_t memberAlignInBits = dl.getABITypeAlign(memberTy).value() * 8; + + // align offset according to memberAlign + // TODO: improved this when implementing packed structs/types + if (offset % memberAlignInBits != 0) + offset += memberAlignInBits - (offset % memberAlignInBits); + + DIType *di = DBuilder->createMemberType(RobDbgInfo.currScope(), m->getName(), + RobDbgInfo.currFile(), m->getLineNo(), memberBitWidth, memberAlignInBits, + offset, DINode::DIFlags::FlagZero, memberDiType); + assert(di); + elems.push_back(di); + offset += memberBitWidth; + } + + auto dielems = DBuilder->getOrCreateArray(elems); + info.diType = DBuilder->createClassType(RobDbgInfo.currScope(), info.name, + RobDbgInfo.currFile(), userType->getLineNo(), info.bitWidth, 1, 0, + DINode::DIFlags::FlagZero, nullptr, dielems); + unsigned ptbw = tinfo[targetPointerType].bitWidth; + info.diPointerType = DBuilder->createPointerType(info.diType, ptbw); +} + +void BuildTypes::generateDebugInfoForTypes() { + if (!debug_info) + return; + + for (DataType dt = nextt-1; dt >= __bdt_last; dt--) { + auto& info = tinfo[dt]; + + Node *userType = program->findSymbol(info.name); + if (!userType) + continue; + + if (info.isEnum) + generateDebugInfoForEnum(info, userType); + else + generateDebugInfoForUserType(info, userType); + } +} diff --git a/src/BuildTypes.h b/src/BuildTypes.h index 78d4100..5d08617 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -64,6 +64,7 @@ class BuildTypes { map tinfo; map namedTypes; DataType nextt = __bdt_last; + DataType targetPointerType; DataType addDataType(const DataTypeInfo& udt) { DataType result = nextt++; @@ -72,6 +73,9 @@ class BuildTypes { return result; } + void generateDebugInfoForEnum(DataTypeInfo &info, Node *userType); + void generateDebugInfoForUserType(DataTypeInfo &info, Node *userType); + public: static const DataType undefinedType = -1; @@ -241,6 +245,12 @@ class BuildTypes { assert(tid != -1 && "Undefined type"); return tinfo[tid].isDefined; } + + unsigned getTargetPointerBitWidth() { + return tinfo[targetPointerType].bitWidth; + } + + void generateDebugInfoForTypes(); }; // TODO: Replace all places with buildType::name diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index f15c547..24be3ee 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -75,3 +75,18 @@ void DebugInfo::declareVar(Node *n, Value *alloc, BasicBlock *allocblock) { DBuilder->insertDeclare(alloc, d, getFixedOffsetExpression(), DILocation::get(sp->getContext(), n->getLineNo(), n->getColNo(), sp), allocblock); } + +void DebugInfo::declareGlobalVar(Node *n, GlobalVariable *gv, BasicBlock *allocblock) { + DataType dt = n->getDataType(); + llvm::DIType *dty = buildTypes->diType(dt); + if (n->isPointerToPointer()) + dty = buildTypes->diPointerType(dt); + if (n->hasQualifier(qvolatile)) { + dty = DBuilder->createQualifiedType(dwarf::DW_TAG_volatile_type, dty); + } + auto sp = RobDbgInfo.currScope(); + auto funit = RobDbgInfo.currFile(); + auto *d = DBuilder->createGlobalVariableExpression(sp, n->getName(), "", + funit, n->getLineNo(), dty, false); + gv->addDebugInfo(d); +} \ No newline at end of file diff --git a/src/HeaderGlobals.h b/src/HeaderGlobals.h index f6ac6b9..4eca9f2 100644 --- a/src/HeaderGlobals.h +++ b/src/HeaderGlobals.h @@ -30,6 +30,7 @@ struct DebugInfo { DIFile *currFile(); DIScope *currScope(); void declareVar(Node *n, Value *alloc, BasicBlock *allocblock); + void declareGlobalVar(Node *n, GlobalVariable *gv, BasicBlock *allocblock); DIExpression *getFixedOffsetExpression(); }; extern struct DebugInfo RobDbgInfo; diff --git a/src/Identifier.cpp b/src/Identifier.cpp index 8e93a39..05fc6e9 100644 --- a/src/Identifier.cpp +++ b/src/Identifier.cpp @@ -21,7 +21,7 @@ Node* Identifier::getSymbol(Node *scope, bool validate) { } if (!result && validate) { - yyerrorcpp("Symbol " + ci + " not found.", this); + yyerrorcpp("Symbol " + ident + " not found.", this); } return result; } diff --git a/src/Pointer.cpp b/src/Pointer.cpp index 277bc95..197a7fd 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -1,6 +1,7 @@ #include "Pointer.h" #include "BackLLVM.h" +#include "HeaderGlobals.h" #include "UserType.h" Pointer::Pointer(const char *name, DataType type, Node *address, location_t loc): @@ -32,18 +33,24 @@ Value *Pointer::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo } Type *targetPointerType = buildTypes->llvmType(dt)->getPointerTo(); + + // In favor of faster and smaller code size, we return the pointer + // as a ConstantExpr. This limits pointer arithmetic. + Constant *addr_num = dyn_cast(addr); + assert(addr_num && "FIXME: global pointer defined without constant address."); + Constant *calloc = ConstantExpr::getIntToPtr(addr_num, targetPointerType); + alloc = calloc; - if (allocblock == global_alloc) { - Constant *addr_num = dyn_cast(addr); - assert(addr_num && "FIXME: global pointer defined without constant address."); - alloc = ConstantExpr::getIntToPtr(addr_num, targetPointerType); - return alloc; - } else { - RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(block); - alloc = Builder->CreateIntToPtr(addr, targetPointerType, name); - return alloc; + extern bool build_dependencies; + if (debug_info && build_dependencies) { + // we add a global variable associated with the pointer + // to easy debugging + GlobalVariable *gv = new GlobalVariable(*mainmodule, targetPointerType, false, + GlobalValue::ExternalLinkage, calloc, name); + RobDbgInfo.declareGlobalVar(this, gv, allocblock); } + + return alloc; } unsigned Pointer::getFieldStartBit(Node *field) { diff --git a/src/Program.cpp b/src/Program.cpp index 85f9b43..37b24ae 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -202,6 +202,8 @@ void Program::doSemanticAnalysis() { PropagateTypes pt; pt.visit(*this); + buildTypes->generateDebugInfoForTypes(); + /*std::fstream fs; fs.open("ast", std::fstream::out); PrintAstVisitor(fs).visit(*this); diff --git a/src/PropagateTypes.cpp b/src/PropagateTypes.cpp index 1db5e58..43a65dd 100644 --- a/src/PropagateTypes.cpp +++ b/src/PropagateTypes.cpp @@ -1,6 +1,7 @@ #include "PropagateTypes.h" #include "ConstructorCall.h" +#include "Scalar.h" void PropagateTypes::propagateChildren(Node& n, std::function lambda) { for (auto it = n.node_children.begin(); it != n.node_children.end(); ++it) { diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 2484f7a..bfd87a4 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -2,6 +2,7 @@ #include "Scalar.h" #include "FunctionImpl.h" #include "BackLLVM.h" +#include "HeaderGlobals.h" #include "Pointer.h" Scalar::Scalar(Identifier ident, Node *e) : @@ -78,18 +79,12 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Type *gty = buildTypes->llvmType(dt); if (expr->isPointerToPointer()) gty = gty->getPointerTo(); - GlobalVariable *gv = new GlobalVariable(*mainmodule, gty, false, + GlobalVariable *gv = new GlobalVariable(*mainmodule, gty, hasQualifier(qconst), GlobalValue::ExternalLinkage, exprvc, name); ret = alloc = gv; - if (debug_info) { - llvm::DIType *dty = buildTypes->diType(dt); - if (expr->isPointerToPointer()) - dty = buildTypes->diPointerType(dt); - auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", - funit, getLineNo(), dty, false); - gv->addDebugInfo(d); - } + if (debug_info) + RobDbgInfo.declareGlobalVar(expr, gv, allocblock); } } else { RobDbgInfo.emitLocation(this); diff --git a/src/UserType.cpp b/src/UserType.cpp index 7515734..6c29104 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -14,6 +14,8 @@ #include "Load.h" #include "BackLLVM.h" #include "Int8.h" +#include "Scalar.h" +#include "Program.h" class ParentScalar: public Scalar { public: @@ -34,18 +36,21 @@ class ParentScalar: public Scalar { } }; +void UserType::setNestedParent() { + for(auto child : this->children()) { + if (UserType *ut = dynamic_cast(child)) { + ut->setParent(this); + } + } +} + bool UserType::createDataType() { - if (dt != BuildTypes::undefinedType) { - // internal types can be created during symbolization, - // while the parent is not set. - if (buildTypes->name(dt) != getName()) - buildTypes->updateName(dt, getName()); + if (dt != BuildTypes::undefinedType) return true; - } // create an undefined type to use in recursive subtypes - dt = buildTypes->getType(getName(), true); + dt = buildTypes->getType(getTypeName(), true); std::vector elements; int idx = 0; @@ -71,24 +76,22 @@ bool UserType::createDataType() { s->setScope(ut); ut->addChild(s); ut->addSymbol(s); - - string varname = ut->getName(); - ut->setParent(this); // name changes after setting parent ut->createDataType(); // create a new var in the parent to store the intf implementation - ConstructorCall *cc = new ConstructorCall(ut->getName(), ut->getLoc()); - v = new Scalar(varname, cc); + ConstructorCall *cc = new ConstructorCall(ut->getTypeName(), ut->getLoc()); + v = new Scalar(ut->getName(), cc); v->dt = ut->getDataType(); cc->setScope(v); v->setScope(this); addChild(v); - // fix the symbol table due to the renaming - getScope()->addSymbol(ut); - symbols[ut->getName()] = ut; // init + // replace the v->getName() symbol with its var and symbols[v->getName()] = v; + // add the nested type to the program root + program->addSymbol(ut->getTypeName(), ut); + } else { v = dynamic_cast(child); } @@ -103,12 +106,6 @@ bool UserType::createDataType() { } else if (v->getPointerMode() == pm_unknown) v->setPointer(pm_nopointer); - if (!buildTypes->isDefined(vdt)) { - Node *undeft = Identifier(buildTypes->name(vdt), getLoc()).getSymbol(this); - UserType *undefut = dynamic_cast(undeft); - if (undefut) - undefut->createDataType(); - } Type *llvmType = v->getLLVMType(); assert(llvmType && "Can not construct a type without its LLVM type."); if (!llvmType) @@ -119,7 +116,10 @@ bool UserType::createDataType() { //FIXME: Fix for data alignment on non-packed structure/type startBits[v->getName()] = startBit; - startBit += buildTypes->bitWidth(v->getDataType()); + if (llvmType->isPointerTy()) + startBit += buildTypes->getTargetPointerBitWidth(); + else + startBit += buildTypes->bitWidth(v->getDataType()); } } bitWidth = startBit; @@ -130,8 +130,8 @@ bool UserType::createDataType() { buildTypes->setInternal(dt, true); if (dt == BuildTypes::undefinedType) { - yyerrorcpp("Type " + name + " alread defined.", this); - yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); + yyerrorcpp("Type " + getTypeName() + " alread defined.", this); + yywarncpp(getTypeName() + " was first defined here.", buildTypes->location(dt)); return false; } @@ -182,7 +182,7 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all } // generate user types and enums - for(auto & [key, stmt] : getSymbols()) { + for(auto* stmt : node_children) { if (UserType *ut = dynamic_cast(stmt)) { ut->setDeclaration(declaration); ut->generate(func, block, allocblock); @@ -231,11 +231,11 @@ unsigned UserType::getFieldStartBit(Node *field) { return startBits[field->getName()]; } -const string UserType::getName() const { +const string UserType::getTypeName() const { if (parent) - return parent->getName() + ":" + NamedNode::getName(); + return parent->getName() + ":" + getName(); else - return NamedNode::getName(); + return getName(); } void UserType::addSymbol(NamedNode *nm) { diff --git a/src/UserType.h b/src/UserType.h index c6d0d39..c9b1e49 100644 --- a/src/UserType.h +++ b/src/UserType.h @@ -1,9 +1,7 @@ #pragma once -#include "HeaderExternals.h" #include "Node.h" -#include "Scalar.h" class Visitor; @@ -16,14 +14,19 @@ class UserType: public NamedNode { unsigned bitWidth = 0; bool createDataType(); + void setNestedParent(); public: UserType(const string name, vector &&stmts, location_t loc): - NamedNode(name, std::move(stmts), loc) { } + NamedNode(name, std::move(stmts), loc) { + setNestedParent(); + } UserType(const string name, vector &&stmts, vector &&implements, location_t loc): - NamedNode(name, std::move(stmts), loc), implements(std::move(implements)) { } + NamedNode(name, std::move(stmts), loc), implements(std::move(implements)) { + setNestedParent(); + } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; @@ -43,7 +46,7 @@ class UserType: public NamedNode { parent = ut; } - virtual const string getName() const override; + virtual const string getTypeName() const; virtual void addSymbol(NamedNode *nm) override; @@ -56,7 +59,12 @@ class UserType: public NamedNode { } DataType getDataType() override { - createDataType(); + if (parent) { + // forces the definition of the parent first, as it adds the + // parent field on subtypes and also create them + parent->getDataType(); + } else + createDataType(); return dt; } }; diff --git a/src/Variable.cpp b/src/Variable.cpp index 5b3bc1e..9cc1c20 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -12,16 +12,20 @@ Value *Variable::getLLVMValue(Node *stem) { FunctionImpl *func = dynamic_cast(stem); if (func && func->getThisArg()) { // generating a function of a type: get the gep on :this or :parent parameters - Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); + DataType thisDt = func->getThisArgDt(); + Type *thisTy = buildTypes->llvmType(thisDt); Value *thisptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); if (!stem->getScope() || this->getScope() == stem->getScope()) { - // in the global or same scope, defer :this and gep the field + // the var is being accessed in global scope (!stem->getScope()) or + // in a method of the type itself. Thus, we :this and gep the field alloc = Builder->CreateStructGEP(thisTy, thisptr, gepidx, "gepthis"); } else { - // FIXME: in distinct scopes, access :parent (gep 0 or 1) in :this and gep the field - // currently, the CreateStructGEP deference 0; but zero sometimes is the typeid var - Type *parentTy = buildTypes->llvmType(this->getScope()->getDataType()); - Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, 0, "gepthis"); + // this var is in the parent scope. :this is an nested type. + // Thus, we access :parent in :this and gep the field + DataType parentDt = this->getScope()->getDataType(); + Type *parentTy = buildTypes->llvmType(parentDt); + int idxParentInThis = static_cast(symbols["parent"])->getGEPIndex(); + Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, idxParentInThis, "gepthis"); Value *parentptr = Builder->CreateLoad(parentTy->getPointerTo(), parentAlloc, "derefparent"); alloc = Builder->CreateStructGEP(parentTy, parentptr, gepidx, "gepparent"); } diff --git a/src/main.cpp b/src/main.cpp index db613a6..837358a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,7 @@ Program *program = NULL; int print_llvm_ir(char opt_level); +void setup_target_machine(char opt_level); bool debug_info; bool build_dependencies; char *build_outputfilename; @@ -105,6 +106,8 @@ int main(int argc, char *argv[]) { exit(1); } + setup_target_machine(optimization); + program->doSemanticAnalysis(); if (errorsfound <= 0) From 2707f953e41ebc0c0627cb65ed2f6ae1ef075811 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 22 Jun 2024 20:51:50 -0300 Subject: [PATCH 062/117] Fixes stm32f1 i2c speed to 400Mhz. Now working in -Oz -O3 and -O0 (added volatile var when opening transaction) --- lib/arch/stm32/stm32f1.rob | 24 +++++++++++++++++------- lib/intfs/ports.rob | 8 ++++---- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/lib/arch/stm32/stm32f1.rob b/lib/arch/stm32/stm32f1.rob index d2657c3..fd86b1c 100644 --- a/lib/arch/stm32/stm32f1.rob +++ b/lib/arch/stm32/stm32f1.rob @@ -140,13 +140,23 @@ type stm32f1 implements mcu { // disable peripheral to configure I2C1_CR1.pe = false; - // asuming 8Mhz clock - // FIX: should compute based on mcu/peripheral clock + /* How to compute the values below (assuming 8Mhz Clock, PRESCALER=1) + fs == true and duty == true (400Khz) + CCR = ((1/400000)/PRESCALER) / (25/8000000) + CCR = 2500ns/3125ns = 0.8 = ~0 -> won't work at 8Mhz + + fs == true and duty == false (400Khz) + CCR = ((1/400000)/PRESCALER) / (3/8000000) + CCR = 2500ns/375ns = ~6.6667 = ~ 6 + + TRISE calculated by PCLK (in MHz) * 0.3ms + 1 + */ + I2C1_CCR.fs = true; - I2C1_CCR.duty = true; - I2C1_CR2.freq = 0x8; - I2C1_CCR.ccr = 0x1; - I2C1_TRISE = 0x1e; + //I2C1_CCR.duty = true; + I2C1_CR2.freq = uint6(clock()/1E6); // no APB1 prescaler + I2C1_CCR.ccr = uint12(((1.0/400000)/2) / (3.0/clock())); + I2C1_TRISE = uint16(clock()/1E6*0.3+1); } void enable() { @@ -168,7 +178,7 @@ type stm32f1 implements mcu { while !I2C1_SR1.addr; // wait addr send // clear ADDR condition - temp = I2C1_SR2.msl; + volatile temp = I2C1_SR2.msl; return true; } diff --git a/lib/intfs/ports.rob b/lib/intfs/ports.rob index 8ee2757..714ec33 100644 --- a/lib/intfs/ports.rob +++ b/lib/intfs/ports.rob @@ -18,13 +18,13 @@ interface analogport { } type null_digitalport implements digitalport { - void mode(port_mode m) inline { return; } - void set(bool v) inline { return; } + void mode(port_mode m) inline {} + void set(bool v) inline {} bool get() inline { return false; } } type null_analogport implements analogport { - void mode(port_mode m) inline { return; } - void set(uint16 v) inline { return; } + void mode(port_mode m) inline {} + void set(uint16 v) inline {} uint16 get() inline { return 0; } } From afc35c44c49f2e98047396b00efb0d043285ca11 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 23 Jun 2024 09:13:16 -0300 Subject: [PATCH 063/117] Fixes dispatch generation while building nested types; allow function without body (stmts) in LanguageUse. --- src/Dispatch.cpp | 7 +++++++ src/Interface.cpp | 11 ----------- src/LanguageUse.y | 7 +++++-- src/UserType.cpp | 4 ++-- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/Dispatch.cpp b/src/Dispatch.cpp index b39aeb0..428110d 100644 --- a/src/Dispatch.cpp +++ b/src/Dispatch.cpp @@ -4,6 +4,7 @@ #include "Interface.h" #include "FunctionImpl.h" #include "BackLLVM.h" +#include "Scanner.h" void Dispatch::addDataTypeImplementation(DataType base, DataType impl) { set& impls = dispatchHash[base]; @@ -68,6 +69,12 @@ void Dispatch::generateDispatchFunctions(Node *scope) { string destFuncName = destTypeName + ":" + method; Function *destFunc = mainmodule->getFunction(destFuncName); + if (!destFunc) { + yyerrorcpp(string_format("Function %s not found while generating dispatch.", + destFuncName.c_str()), scope); + continue; + } + Value *call = Builder->CreateCall(destFunc, args); if (call->getType()->isVoidTy()) Builder->CreateRetVoid(); diff --git a/src/Interface.cpp b/src/Interface.cpp index d3402c3..213c1fe 100644 --- a/src/Interface.cpp +++ b/src/Interface.cpp @@ -5,17 +5,6 @@ #include "FunctionDecl.h" void Interface::createDataType() { - // TRY: prevent opaque type - // the interface type is replaced at link stage - /*Scalar *no_opaque = new Scalar("no_opaque", new Int1(0)); - no_opaque->setGEPIndex(0); - addChild(no_opaque); - addSymbol(no_opaque); - - std::vector elements; - elements.push_back(Type::getInt1Ty(global_context)); - - StructType *intftype = StructType::create(global_context, ArrayRef(elements), getName());*/ StructType *intftype = StructType::create(global_context, getName()); dt = buildTypes->addDataType(this, intftype); buildTypes->setInterface(dt, true); diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 9460286..aff3573 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -13,7 +13,7 @@ } %type globals type_stmts enum_items interface_decls -%type stmts +%type stmts stmts_rec %type global register interface type type_stmt use %type function function_decl function_impl %type enum enum_item const_expr expr unary interface_impl @@ -128,7 +128,7 @@ function_decl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' $$ = func; } -function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' function_attributes[fa] '{' stmts '}'[ef] { +function_impl : TOK_IDENTIFIER[type] TOK_IDENTIFIER[id] '(' function_params ')' function_attributes[fa] '{' stmts_rec '}'[ef] { vector stmts; FunctionImpl *func = new FunctionImpl(buildTypes->getType($type, true), $id, $function_params, std::move(stmts), @type, @ef); @@ -333,6 +333,9 @@ ignore_param : ignore_p { $$ = NULL; } ignore_p : TOK_INTEGER { YYERROR; } | TOK_IDENTIFIER { YYERROR; } +stmts_rec : %empty { $$ = NULL; } + | stmts { $$ = NULL; } + stmts : stmts ignore_stmt { $$ = NULL; } | ignore_stmt { $$ = NULL; } diff --git a/src/UserType.cpp b/src/UserType.cpp index 6c29104..9b60b05 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -173,7 +173,7 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all */ for(auto & [key, stmt] : getSymbols()) { if (FunctionImpl *f = dynamic_cast(stmt)) { - f->setPrefixName(getName()); + f->setPrefixName(getTypeName()); f->addThisArgument(dt); for(auto &field : fields) f->addSymbol(dynamic_cast(field)); @@ -206,7 +206,7 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all // nested user types can be inlined in the parent init finit->getAttributes()->addAttribute(fa_inline); } - finit->setPrefixName(getName()); + finit->setPrefixName(getTypeName()); finit->setExternal(declaration); finit->setConstructor(true); finit->generate(func, block, allocblock); From 40f8eb9948aef096a6341d0d40212449a833a68d Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 23 Jun 2024 17:06:11 -0300 Subject: [PATCH 064/117] Fix PropagateTypes on FunctionCall parameters. --- src/FunctionCall.cpp | 20 +++++++++++--------- src/FunctionCall.h | 5 ++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index e7f77b4..8c7e842 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -18,7 +18,7 @@ DataType FunctionCall::getDataType() { if (dt == BuildTypes::undefinedType) { // is a constructor? this can occur while running PropagateTypes. dt = buildTypes->getType(ident.getFullName()); - if (parameters->getNumParams() <= 1 && dt != BuildTypes::undefinedType) { + if (node_children.size() <= 1 && dt != BuildTypes::undefinedType) { return dt; } @@ -56,10 +56,10 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock } } - if (fsymbol->getNumCodedParams() != parameters->getNumParams()) { + if (fsymbol->getNumCodedParams() != node_children.size()) { yyerrorcpp(string_format("Function %s has %d argument(s) but was called with %d.", name.c_str(), fsymbol->getNumCodedParams(), - parameters->getNumParams()), this); + node_children.size()), this); yywarncpp("The function declaration is here.", symbol); return NULL; } @@ -85,11 +85,11 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock vector args; vector dataTypes; - for (int i = 0; i < parameters->getNumParams(); i++) { - Node *param = parameters->getParamElement(i); + int paramId = 0; + for (Node *param : node_children) { DataType call_dt = param->getDataType(); - DataType def_dt = fsymbol->getParameters().getParamType(i); - string argName = fsymbol->getParameters().getParamName(i); + DataType def_dt = fsymbol->getParameters().getParamType(paramId); + string argName = fsymbol->getParameters().getParamName(paramId); Value *valor = param->generate(func, block, allocblock); if (!valor) { @@ -131,8 +131,8 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock valor = ptr; } - args.insert(args.begin() + i, valor); - dataTypes.insert(dataTypes.begin() + i, def_dt); + args.insert(args.begin() + paramId, valor); + dataTypes.insert(dataTypes.begin() + paramId, def_dt); // add a size parameter after each array, or .rows and .cols for matrixes if (buildTypes->isArrayOrMatrix(call_dt)) { @@ -154,6 +154,8 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock dataTypes.push_back(coerced->getDataType()); } } + + paramId++; } // this parameter diff --git a/src/FunctionCall.h b/src/FunctionCall.h index 28d3b43..040c8a3 100644 --- a/src/FunctionCall.h +++ b/src/FunctionCall.h @@ -9,16 +9,15 @@ class FunctionCall: public Node { private: Identifier ident; - ParamsCall *parameters; Node *symbol = NULL; Variable *leftValue = NULL; public: FunctionCall(const string& name, ParamsCall *pc, location_t loc): Node(loc), ident(name, loc) { - parameters = pc; node_children.reserve(pc->getNumParams()); node_children.insert(end(node_children), pc->getParameters().begin(), pc->getParameters().end()); + delete pc; } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; @@ -30,7 +29,7 @@ class FunctionCall: public Node { } std::vector& getParameters() { - return parameters->getParameters(); + return node_children; } Node* accept(Visitor& v) override; From c4029d933ea1dd3f2821dae14b43810c60db4606 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Mon, 24 Jun 2024 08:44:08 -0300 Subject: [PATCH 065/117] Fixes avr linking with naked functions and implements string constant as an array of int. --- lib/arch/avr/avr5mcu.rob | 21 +- lib/atmega328p.svd | 3510 ++++++++++++++++++++++++++++++++++++++ lib/avr328p.rob | 57 +- lib/avr5.S | 36 - lib/avr5.ld | 24 +- src/Array.cpp | 6 +- src/Array.h | 9 +- src/BackLLVM.cpp | 1 + src/BuildTypes.cpp | 25 +- src/BuildTypes.h | 2 + src/FunctionAttributes.h | 2 +- src/FunctionCall.cpp | 20 +- src/FunctionDecl.cpp | 6 + src/FunctionImpl.cpp | 5 +- src/Header.h | 1 + src/Identifier.h | 2 +- src/Language.l | 1 + src/Language.y | 2 + src/LanguageHeader.y | 2 +- src/LanguageUse.y | 1 + src/NamedConst.h | 8 +- src/Pointer.cpp | 13 +- src/PropagateTypes.cpp | 7 + src/SourceLocation.h | 2 +- src/StringConst.cpp | 13 +- src/StringConst.h | 36 +- src/Variable.h | 4 + test/avr328p/runtest.sh | 6 +- 28 files changed, 3703 insertions(+), 119 deletions(-) create mode 100644 lib/atmega328p.svd diff --git a/lib/arch/avr/avr5mcu.rob b/lib/arch/avr/avr5mcu.rob index 7f4b530..b2c51f7 100644 --- a/lib/arch/avr/avr5mcu.rob +++ b/lib/arch/avr/avr5mcu.rob @@ -151,7 +151,7 @@ type avr5mcu implements mcu { UCSR0A.U2X0 = false; multipl = 16u; - if UCSR0A.U2X0 == true { + if UCSR0A.U2X0 { multipl = 8u; } @@ -184,33 +184,32 @@ type avr5mcu implements mcu { UCSR0B.TXEN0 = false; } - void write(uint8 b) { - while UCSR0A.UDRE0 == false; + void write(uint8 b) inline { + while !UCSR0A.UDRE0; UDR0 = b; } void write_array(int8[] data) { i = 0u; while i < data.size { - while UCSR0A.UDRE0 == false; - UDR0 = uint8(data[i]); + write(uint8(data[i])); i++; } } - uint8 read() { - while UCSR0A.RXC0 == false; + uint8 read() inline { + while !UCSR0A.RXC0; return UDR0; } - bool has_data() { + bool has_data() inline { return UCSR0A.RXC0; } - bool start_transaction(uint16 address) { return true; } - void end_transaction() { return; } + bool start_transaction(uint16 address) inline { return true; } + void end_transaction() { } - databus_protocol get_protocol() { + databus_protocol get_protocol() inline { return databus_protocol.UART; } } diff --git a/lib/atmega328p.svd b/lib/atmega328p.svd new file mode 100644 index 0000000..5bca166 --- /dev/null +++ b/lib/atmega328p.svd @@ -0,0 +1,3510 @@ + + + Atmel + ATmega328P + 8 + 8 + read-write + 0 + 0xff + + + AC + Analog Comparator + 0x50 + + 0 + 0x100 + registers + + + + ACSR + Analog Comparator Control And Status Register + 0x0 + read-only + + + ACIS + Analog Comparator Interrupt Mode Select bits + [1:0] + + true + + + + VAL_0x00 + Interrupt on Toggle + 0 + + + VAL_0x01 + Reserved + 1 + + + VAL_0x02 + Interrupt on Falling Edge + 2 + + + VAL_0x03 + Interrupt on Rising Edge + 3 + + + + + ACIC + Analog Comparator Input Capture Enable + [2:2] + + + ACIE + Analog Comparator Interrupt Enable + [3:3] + + + ACI + Analog Comparator Interrupt Flag + [4:4] + + + ACO + Analog Compare Output + [5:5] + + + ACBG + Analog Comparator Bandgap Select + [6:6] + + + ACD + Analog Comparator Disable + [7:7] + + + + + DIDR1 + Digital Input Disable Register 1 + 0x2F + + + AIN0D + AIN0 Digital Input Disable + [0:0] + + + AIN1D + AIN1 Digital Input Disable + [1:1] + + + + + + + ADC + Analog-to-Digital Converter + 0x78 + + 0 + 0x100 + registers + + + + ADC + ADC Data Register Bytes + 0x0 + 16 + + + 0 + 65535 + + + + + ADCSRA + The ADC Control and Status register A + 0x2 + read-only + + + ADPS + ADC Prescaler Select Bits + [2:0] + + true + + + + VAL_0x00 + 2 + 0 + + + VAL_0x01 + 2 + 1 + + + VAL_0x02 + 4 + 2 + + + VAL_0x03 + 8 + 3 + + + VAL_0x04 + 16 + 4 + + + VAL_0x05 + 32 + 5 + + + VAL_0x06 + 64 + 6 + + + VAL_0x07 + 128 + 7 + + + + + ADIE + ADC Interrupt Enable + [3:3] + + + ADIF + ADC Interrupt Flag + [4:4] + + + ADATE + ADC Auto Trigger Enable + [5:5] + + + ADSC + ADC Start Conversion + [6:6] + + + ADEN + ADC Enable + [7:7] + + + + + ADCSRB + The ADC Control and Status register B + 0x3 + + + ADTS + ADC Auto Trigger Source bits + [2:0] + + true + + + + VAL_0x00 + Free Running mode + 0 + + + VAL_0x01 + Analog Comparator + 1 + + + VAL_0x02 + External Interrupt Request 0 + 2 + + + VAL_0x03 + Timer/Counter0 Compare Match A + 3 + + + VAL_0x04 + Timer/Counter0 Overflow + 4 + + + VAL_0x05 + Timer/Counter1 Compare Match B + 5 + + + VAL_0x06 + Timer/Counter1 Overflow + 6 + + + VAL_0x07 + Timer/Counter1 Capture Event + 7 + + + + + ACME + <TBD> + [6:6] + + + + + ADMUX + The ADC multiplexer Selection Register + 0x4 + + + MUX + Analog Channel Selection Bits + [3:0] + + true + + + + ADC0 + ADC Single Ended Input pin 0 + 0 + + + ADC1 + ADC Single Ended Input pin 1 + 1 + + + ADC2 + ADC Single Ended Input pin 2 + 2 + + + ADC3 + ADC Single Ended Input pin 3 + 3 + + + ADC4 + ADC Single Ended Input pin 4 + 4 + + + ADC5 + ADC Single Ended Input pin 5 + 5 + + + ADC6 + ADC Single Ended Input pin 6 + 6 + + + ADC7 + ADC Single Ended Input pin 7 + 7 + + + TEMPSENS + Temperature sensor + 8 + + + ADC_VBG + Internal Reference (VBG) + 14 + + + ADC_GND + 0V (GND) + 15 + + + + + ADLAR + Left Adjust Result + [5:5] + + + REFS + Reference Selection Bits + [7:6] + + true + + + + VAL_0x00 + AREF, Internal Vref turned off + 0 + + + VAL_0x01 + AVCC with external capacitor at AREF pin + 1 + + + VAL_0x02 + Reserved + 2 + + + VAL_0x03 + Internal 1.1V Voltage Reference with external capacitor at AREF pin + 3 + + + + + + + DIDR0 + Digital Input Disable Register + 0x6 + + + ADC0D + <TBD> + [0:0] + + + ADC1D + <TBD> + [1:1] + + + ADC2D + <TBD> + [2:2] + + + ADC3D + <TBD> + [3:3] + + + ADC4D + <TBD> + [4:4] + + + ADC5D + <TBD> + [5:5] + + + + + + + CPU + CPU Registers + 0x3E + + 0 + 0x100 + registers + + + + CLKPR + Clock Prescale Register + 0x23 + read-only + + + CLKPS + Clock Prescaler Select Bits + [3:0] + + true + + + + VAL_0x00 + 1 + 0 + + + VAL_0x01 + 2 + 1 + + + VAL_0x02 + 4 + 2 + + + VAL_0x03 + 8 + 3 + + + VAL_0x04 + 16 + 4 + + + VAL_0x05 + 32 + 5 + + + VAL_0x06 + 64 + 6 + + + VAL_0x07 + 128 + 7 + + + VAL_0x08 + 256 + 8 + + + + + CLKPCE + Clock Prescaler Change Enable + [7:7] + + + + + GPIOR0 + General Purpose I/O Register 0 + 0x0 + + + 0 + 255 + + + + + GPIOR1 + General Purpose I/O Register 1 + 0xC + + + 0 + 255 + + + + + GPIOR2 + General Purpose I/O Register 2 + 0xD + + + 0 + 255 + + + + + MCUCR + MCU Control Register + 0x17 + + + IVCE + <TBD> + [0:0] + + + IVSEL + <TBD> + [1:1] + + + PUD + <TBD> + [4:4] + + + BODSE + BOD Sleep Enable + [5:5] + + + BODS + BOD Sleep + [6:6] + + + + + MCUSR + MCU Status Register + 0x16 + + + PORF + Power-on reset flag + [0:0] + + + EXTRF + External Reset Flag + [1:1] + + + BORF + Brown-out Reset Flag + [2:2] + + + WDRF + Watchdog Reset Flag + [3:3] + + + + + OSCCAL + Oscillator Calibration Value + 0x28 + read-only + + + OSCCAL + Oscillator Calibration + [7:0] + + + 0 + 255 + + + + + + + PRR + Power Reduction Register + 0x26 + + 0 + 0x100 + registers + + read-only + + + PRADC + Power Reduction ADC + [0:0] + + + PRUSART0 + Power Reduction USART + [1:1] + + + PRSPI + Power Reduction Serial Peripheral Interface + [2:2] + + + PRTIM1 + Power Reduction Timer/Counter1 + [3:3] + + + PRTIM0 + Power Reduction Timer/Counter0 + [5:5] + + + PRTIM2 + Power Reduction Timer/Counter2 + [6:6] + + + PRTWI + Power Reduction TWI + [7:7] + + + + + SMCR + Sleep Mode Control Register + 0x15 + + + SE + Sleep Enable + [0:0] + + + SM + Sleep Mode Select Bits + [3:1] + + true + + + + IDLE + Idle + 0 + + + ADC + ADC Noise Reduction (If Available) + 1 + + + PDOWN + Power Down + 2 + + + PSAVE + Power Save + 3 + + + VAL_0x04 + Reserved + 4 + + + VAL_0x05 + Reserved + 5 + + + STDBY + Standby + 6 + + + ESTDBY + Extended Standby + 7 + + + + + + + SPMCSR + Store Program Memory Control and Status Register + 0x19 + + + SPMEN + Store Program Memory + [0:0] + + + PGERS + Page Erase + [1:1] + + + PGWRT + Page Write + [2:2] + + + BLBSET + Boot Lock Bit Set + [3:3] + + + RWWSRE + Read-While-Write section read enable + [4:4] + + + SIGRD + Signature Row Read + [5:5] + + + RWWSB + Read-While-Write Section Busy + [6:6] + + + SPMIE + SPM Interrupt Enable + [7:7] + + + + + + RESET + 0 + External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset + + + INT0 + 1 + External Interrupt Request 0 + + + INT1 + 2 + External Interrupt Request 1 + + + PCINT0 + 3 + Pin Change Interrupt Request 0 + + + PCINT1 + 4 + Pin Change Interrupt Request 1 + + + PCINT2 + 5 + Pin Change Interrupt Request 2 + + + WDT + 6 + Watchdog Time-out Interrupt + + + TIMER2_COMPA + 7 + Timer/Counter2 Compare Match A + + + TIMER2_COMPB + 8 + Timer/Counter2 Compare Match B + + + TIMER2_OVF + 9 + Timer/Counter2 Overflow + + + TIMER1_CAPT + 10 + Timer/Counter1 Capture Event + + + TIMER1_COMPA + 11 + Timer/Counter1 Compare Match A + + + TIMER1_COMPB + 12 + Timer/Counter1 Compare Match B + + + TIMER1_OVF + 13 + Timer/Counter1 Overflow + + + TIMER0_COMPA + 14 + TimerCounter0 Compare Match A + + + TIMER0_COMPB + 15 + TimerCounter0 Compare Match B + + + TIMER0_OVF + 16 + Timer/Couner0 Overflow + + + SPI_STC + 17 + SPI Serial Transfer Complete + + + USART_RX + 18 + USART Rx Complete + + + USART_UDRE + 19 + USART, Data Register Empty + + + USART_TX + 20 + USART Tx Complete + + + ADC + 21 + ADC Conversion Complete + + + EE_READY + 22 + EEPROM Ready + + + ANALOG_COMP + 23 + Analog Comparator + + + TWI + 24 + Two-wire Serial Interface + + + SPM_Ready + 25 + Store Program Memory Read + + + + EEPROM + EEPROM + 0x3F + + 0 + 0x100 + registers + + + + EEAR + EEPROM Address Register Bytes + 0x2 + 16 + + + 0 + 65535 + + + + + EECR + EEPROM Control Register + 0x0 + + + EERE + EEPROM Read Enable + [0:0] + + + EEPE + EEPROM Write Enable + [1:1] + + + EEMPE + EEPROM Master Write Enable + [2:2] + + + EERIE + EEPROM Ready Interrupt Enable + [3:3] + + + EEPM + EEPROM Programming Mode Bits + [5:4] + + true + + + + VAL_0x00 + Erase and Write in one operation + 0 + + + VAL_0x01 + Erase Only + 1 + + + VAL_0x02 + Write Only + 2 + + + + + + + EEDR + EEPROM Data Register + 0x1 + + + 0 + 255 + + + + + + + EXINT + External Interrupts + 0x3B + + 0 + 0x100 + registers + + + + EICRA + External Interrupt Control Register + 0x2E + + + ISC0 + External Interrupt Sense Control 0 Bits + [1:0] + + true + + + + VAL_0x00 + Low Level of INTX + 0 + + + VAL_0x01 + Any Logical Change of INTX + 1 + + + VAL_0x02 + Falling Edge of INTX + 2 + + + VAL_0x03 + Rising Edge of INTX + 3 + + + + + ISC1 + External Interrupt Sense Control 1 Bits + [3:2] + + true + + + + VAL_0x00 + Low Level of INTX + 0 + + + VAL_0x01 + Any Logical Change of INTX + 1 + + + VAL_0x02 + Falling Edge of INTX + 2 + + + VAL_0x03 + Rising Edge of INTX + 3 + + + + + + + EIFR + External Interrupt Flag Register + 0x1 + read-only + + + INTF + External Interrupt Flags + [1:0] + + + 0 + 3 + + + + + + + EIMSK + External Interrupt Mask Register + 0x2 + + + INT + External Interrupt Request 1 Enable + [1:0] + + + 0 + 3 + + + + + + + PCICR + Pin Change Interrupt Control Register + 0x2D + + + PCIE + Pin Change Interrupt Enables + [2:0] + + + 0 + 7 + + + + + + + PCIFR + Pin Change Interrupt Flag Register + 0x0 + read-only + + + PCIF + Pin Change Interrupt Flags + [2:0] + + + 0 + 7 + + + + + + + PCMSK0 + Pin Change Mask Register 0 + 0x30 + + + PCINT + Pin Change Enable Masks + [7:0] + + + 0 + 255 + + + + + + + PCMSK1 + Pin Change Mask Register 1 + 0x31 + + + PCINT + Pin Change Enable Masks + [6:0] + + + 0 + 127 + + + + + + + PCMSK2 + Pin Change Mask Register 2 + 0x32 + + + PCINT + Pin Change Enable Masks + [7:0] + + + 0 + 255 + + + + + + + + + FUSE + Fuses + 0x0 + + 0 + 0x100 + registers + + + + EXTENDED + <TBD> + 0x2 + + + BODLEVEL + Brown-out Detector trigger level + [2:0] + + true + + + + 4V3 + Brown-out detection at VCC=4.3 V + 4 + + + 2V7 + Brown-out detection at VCC=2.7 V + 5 + + + 1V8 + Brown-out detection at VCC=1.8 V + 6 + + + DISABLED + Brown-out detection disabled + 7 + + + + + + + HIGH + <TBD> + 0x1 + + + BOOTRST + Boot Reset vector Enabled + [0:0] + + + BOOTSZ + Select boot size + [2:1] + + true + + + + 2048W_3800 + Boot Flash size=2048 words start address=$3800 + 0 + + + 1024W_3C00 + Boot Flash size=1024 words start address=$3C00 + 1 + + + 512W_3E00 + Boot Flash size=512 words start address=$3E00 + 2 + + + 256W_3F00 + Boot Flash size=256 words start address=$3F00 + 3 + + + + + EESAVE + Preserve EEPROM through the Chip Erase cycle + [3:3] + + + WDTON + Watch-dog Timer always on + [4:4] + + + SPIEN + Serial program downloading (SPI) enabled + [5:5] + + + DWEN + Debug Wire enable + [6:6] + + + RSTDISBL + Reset Disabled (Enable PC6 as i/o pin) + [7:7] + + + + + LOW + <TBD> + 0x0 + + + SUT_CKSEL + Select Clock Source + [5:0] + + true + + + + EXTCLK_6CK_14CK_0MS + Ext. Clock; Start-up time PWRDWN/RESET: 6 CK/14 CK + 0 ms + 0 + + + INTRCOSC_8MHZ_6CK_14CK_0MS + Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 0 ms + 2 + + + INTRCOSC_128KHZ_6CK_14CK_0MS + Int. RC Osc. 128kHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 0 ms + 3 + + + EXTLOFXTAL_1KCK_14CK_0MS + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 1K CK/14 CK + 0 ms + 4 + + + EXTLOFXTAL_32KCK_14CK_0MS + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 32K CK/14 CK + 0 ms + 5 + + + EXTFSXTAL_258CK_14CK_4MS1 + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 258 CK/14 CK + 4.1 ms + 6 + + + EXTFSXTAL_1KCK_14CK_65MS + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 1K CK /14 CK + 65 ms + 7 + + + EXTXOSC_0MHZ4_0MHZ9_258CK_14CK_4MS1 + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 4.1 ms + 8 + + + EXTXOSC_0MHZ4_0MHZ9_1KCK_14CK_65MS + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 65 ms + 9 + + + EXTXOSC_0MHZ9_3MHZ_258CK_14CK_4MS1 + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 4.1 ms + 10 + + + EXTXOSC_0MHZ9_3MHZ_1KCK_14CK_65MS + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 65 ms + 11 + + + EXTXOSC_3MHZ_8MHZ_258CK_14CK_4MS1 + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 4.1 ms + 12 + + + EXTXOSC_3MHZ_8MHZ_1KCK_14CK_65MS + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 65 ms + 13 + + + EXTXOSC_8MHZ_XX_258CK_14CK_4MS1 + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 4.1 ms + 14 + + + EXTXOSC_8MHZ_XX_1KCK_14CK_65MS + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 65 ms + 15 + + + EXTCLK_6CK_14CK_4MS1 + Ext. Clock; Start-up time PWRDWN/RESET: 6 CK/14 CK + 4.1 ms + 16 + + + INTRCOSC_8MHZ_6CK_14CK_4MS1 + Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 4.1 ms + 18 + + + INTRCOSC_128KHZ_6CK_14CK_4MS1 + Int. RC Osc. 128kHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 4.1 ms + 19 + + + EXTLOFXTAL_1KCK_14CK_4MS1 + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 1K CK/14 CK + 4.1 ms + 20 + + + EXTLOFXTAL_32KCK_14CK_4MS1 + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 32K CK/14 CK + 4.1 ms + 21 + + + EXTFSXTAL_258CK_14CK_65MS + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 258 CK/14 CK + 65 ms + 22 + + + EXTFSXTAL_16KCK_14CK_0MS + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 16K CK/14 CK + 0 ms + 23 + + + EXTXOSC_0MHZ4_0MHZ9_258CK_14CK_65MS + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 65 ms + 24 + + + EXTXOSC_0MHZ4_0MHZ9_16KCK_14CK_0MS + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 0 ms + 25 + + + EXTXOSC_0MHZ9_3MHZ_258CK_14CK_65MS + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 65 ms + 26 + + + EXTXOSC_0MHZ9_3MHZ_16KCK_14CK_0MS + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 0 ms + 27 + + + EXTXOSC_3MHZ_8MHZ_258CK_14CK_65MS + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 65 ms + 28 + + + EXTXOSC_3MHZ_8MHZ_16KCK_14CK_0MS + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 0 ms + 29 + + + EXTXOSC_8MHZ_XX_258CK_14CK_65MS + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 258 CK/14 CK + 65 ms + 30 + + + EXTXOSC_8MHZ_XX_16KCK_14CK_0MS + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 0 ms + 31 + + + EXTCLK_6CK_14CK_65MS + Ext. Clock; Start-up time PWRDWN/RESET: 6 CK/14 CK + 65 ms + 32 + + + INTRCOSC_8MHZ_6CK_14CK_65MS + Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 65 ms + 34 + + + INTRCOSC_128KHZ_6CK_14CK_65MS + Int. RC Osc. 128kHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 65 ms + 35 + + + EXTLOFXTAL_1KCK_14CK_65MS + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 1K CK/14 CK + 65 ms + 36 + + + EXTLOFXTAL_32KCK_14CK_65MS + Ext. Low-Freq. Crystal; Start-up time PWRDWN/RESET: 32K CK/14 CK + 65 ms + 37 + + + EXTFSXTAL_1KCK_14CK_0MS + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 1K CK /14 CK + 0 ms + 38 + + + EXTFSXTAL_16KCK_14CK_4MS1 + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 16K CK/14 CK + 4.1 ms + 39 + + + EXTXOSC_0MHZ4_0MHZ9_1KCK_14CK_0MS + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 0 ms + 40 + + + EXTXOSC_0MHZ4_0MHZ9_16KCK_14CK_4MS1 + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 4.1 ms + 41 + + + EXTXOSC_0MHZ9_3MHZ_1KCK_14CK_0MS + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 0 ms + 42 + + + EXTXOSC_0MHZ9_3MHZ_16KCK_14CK_4MS1 + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 4.1 ms + 43 + + + EXTXOSC_3MHZ_8MHZ_1KCK_14CK_0MS + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 0 ms + 44 + + + EXTXOSC_3MHZ_8MHZ_16KCK_14CK_4MS1 + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 4.1 ms + 45 + + + EXTXOSC_8MHZ_XX_1KCK_14CK_0MS + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 0 ms + 46 + + + EXTXOSC_8MHZ_XX_16KCK_14CK_4MS1 + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 4.1 ms + 47 + + + EXTFSXTAL_1KCK_14CK_4MS1 + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 1K CK /14 CK + 4.1 ms + 54 + + + EXTFSXTAL_16KCK_14CK_65MS + Ext. Full-swing Crystal; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms + 55 + + + EXTXOSC_0MHZ4_0MHZ9_1KCK_14CK_4MS1 + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 4.1 ms + 56 + + + EXTXOSC_0MHZ4_0MHZ9_16KCK_14CK_65MS + Ext. Crystal Osc. 0.4-0.9 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms + 57 + + + EXTXOSC_0MHZ9_3MHZ_1KCK_14CK_4MS1 + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 4.1 ms + 58 + + + EXTXOSC_0MHZ9_3MHZ_16KCK_14CK_65MS + Ext. Crystal Osc. 0.9-3.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms + 59 + + + EXTXOSC_3MHZ_8MHZ_1KCK_14CK_4MS1 + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 4.1 ms + 60 + + + EXTXOSC_3MHZ_8MHZ_16KCK_14CK_65MS + Ext. Crystal Osc. 3.0-8.0 MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms + 61 + + + EXTXOSC_8MHZ_XX_1KCK_14CK_4MS1 + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 1K CK /14 CK + 4.1 ms + 62 + + + EXTXOSC_8MHZ_XX_16KCK_14CK_65MS + Ext. Crystal Osc. 8.0- MHz; Start-up time PWRDWN/RESET: 16K CK/14 CK + 65 ms + 63 + + + + + CKOUT + Clock output on PORTB0 + [6:6] + + + CKDIV8 + Divide clock by 8 internally + [7:7] + + + + + + + LOCKBIT + Lockbits + 0x0 + + 0 + 0x100 + registers + + + + LOCKBIT + <TBD> + 0x0 + + + LB + Memory Lock + [1:0] + + true + + + + PROG_VER_DISABLED + Further programming and verification disabled + 0 + + + PROG_DISABLED + Further programming disabled + 2 + + + NO_LOCK + No memory lock features enabled + 3 + + + + + BLB0 + Boot Loader Protection Mode + [3:2] + + true + + + + LPM_SPM_DISABLE + LPM and SPM prohibited in Application Section + 0 + + + LPM_DISABLE + LPM prohibited in Application Section + 1 + + + SPM_DISABLE + SPM prohibited in Application Section + 2 + + + NO_LOCK + No lock on SPM and LPM in Application Section + 3 + + + + + BLB1 + Boot Loader Protection Mode + [5:4] + + true + + + + LPM_SPM_DISABLE + LPM and SPM prohibited in Boot Section + 0 + + + LPM_DISABLE + LPM prohibited in Boot Section + 1 + + + SPM_DISABLE + SPM prohibited in Boot Section + 2 + + + NO_LOCK + No lock on SPM and LPM in Boot Section + 3 + + + + + + + + + PORTB + I/O Port + read-write + 8 + 0x23 + + 0 + 0x100 + registers + + + + DDRB + Port B Data Direction Register + 0x1 + + + PB0 + Pin B0 + [0:0] + + + PB1 + Pin B1 + [1:1] + + + PB2 + Pin B2 + [2:2] + + + PB3 + Pin B3 + [3:3] + + + PB4 + Pin B4 + [4:4] + + + PB5 + Pin B5 + [5:5] + + + PB6 + Pin B6 + [6:6] + + + PB7 + Pin B7 + [7:7] + + + + + PINB + Port B Input Pins + 0x0 + + + PB0 + Pin B0 + [0:0] + + + PB1 + Pin B1 + [1:1] + + + PB2 + Pin B2 + [2:2] + + + PB3 + Pin B3 + [3:3] + + + PB4 + Pin B4 + [4:4] + + + PB5 + Pin B5 + [5:5] + + + PB6 + Pin B6 + [6:6] + + + PB7 + Pin B7 + [7:7] + + + + + PORTB + Port B Data Register + 0x2 + + + PB0 + Pin B0 + [0:0] + + + PB1 + Pin B1 + [1:1] + + + PB2 + Pin B2 + [2:2] + + + PB3 + Pin B3 + [3:3] + + + PB4 + Pin B4 + [4:4] + + + PB5 + Pin B5 + [5:5] + + + PB6 + Pin B6 + [6:6] + + + PB7 + Pin B7 + [7:7] + + + + + + + PORTC + I/O Port + read-write + 8 + 0x26 + + 0 + 0x100 + registers + + + + DDRC + Port C Data Direction Register + 0x1 + + + PC0 + Pin C0 + [0:0] + + + PC1 + Pin C1 + [1:1] + + + PC2 + Pin C2 + [2:2] + + + PC3 + Pin C3 + [3:3] + + + PC4 + Pin C4 + [4:4] + + + PC5 + Pin C5 + [5:5] + + + PC6 + Pin C6 + [6:6] + + + + + PINC + Port C Input Pins + 0x0 + + + PC0 + Pin C0 + [0:0] + + + PC1 + Pin C1 + [1:1] + + + PC2 + Pin C2 + [2:2] + + + PC3 + Pin C3 + [3:3] + + + PC4 + Pin C4 + [4:4] + + + PC5 + Pin C5 + [5:5] + + + PC6 + Pin C6 + [6:6] + + + + + PORTC + Port C Data Register + 0x2 + + + PC0 + Pin C0 + [0:0] + + + PC1 + Pin C1 + [1:1] + + + PC2 + Pin C2 + [2:2] + + + PC3 + Pin C3 + [3:3] + + + PC4 + Pin C4 + [4:4] + + + PC5 + Pin C5 + [5:5] + + + PC6 + Pin C6 + [6:6] + + + + + + + PORTD + I/O Port + read-write + 8 + 0x29 + + 0 + 0x100 + registers + + + + DDRD + Port D Data Direction Register + 0x1 + + + PD0 + Pin D0 + [0:0] + + + PD1 + Pin D1 + [1:1] + + + PD2 + Pin D2 + [2:2] + + + PD3 + Pin D3 + [3:3] + + + PD4 + Pin D4 + [4:4] + + + PD5 + Pin D5 + [5:5] + + + PD6 + Pin D6 + [6:6] + + + PD7 + Pin D7 + [7:7] + + + + + PIND + Port D Input Pins + 0x0 + + + PD0 + Pin D0 + [0:0] + + + PD1 + Pin D1 + [1:1] + + + PD2 + Pin D2 + [2:2] + + + PD3 + Pin D3 + [3:3] + + + PD4 + Pin D4 + [4:4] + + + PD5 + Pin D5 + [5:5] + + + PD6 + Pin D6 + [6:6] + + + PD7 + Pin D7 + [7:7] + + + + + PORTD + Port D Data Register + 0x2 + + + PD0 + Pin D0 + [0:0] + + + PD1 + Pin D1 + [1:1] + + + PD2 + Pin D2 + [2:2] + + + PD3 + Pin D3 + [3:3] + + + PD4 + Pin D4 + [4:4] + + + PD5 + Pin D5 + [5:5] + + + PD6 + Pin D6 + [6:6] + + + PD7 + Pin D7 + [7:7] + + + + + + + SPI + Serial Peripheral Interface + 0x4C + + 0 + 0x100 + registers + + + + SPCR + SPI Control Register + 0x0 + + + SPR + SPI Clock Rate Selects + [1:0] + + true + + + + VAL_0x00 + fosc/4 + 0 + + + VAL_0x01 + fosc/16 + 1 + + + VAL_0x02 + fosc/64 + 2 + + + VAL_0x03 + fosc/128 + 3 + + + + + CPHA + Clock Phase + [2:2] + + + CPOL + Clock polarity + [3:3] + + + MSTR + Master/Slave Select + [4:4] + + + DORD + Data Order + [5:5] + + + SPE + SPI Enable + [6:6] + + + SPIE + SPI Interrupt Enable + [7:7] + + + + + SPDR + SPI Data Register + 0x2 + + + 0 + 255 + + + + + SPSR + SPI Status Register + 0x1 + read-only + + + SPI2X + Double SPI Speed Bit + [0:0] + + + WCOL + Write Collision Flag + [6:6] + + + SPIF + SPI Interrupt Flag + [7:7] + + + + + + + TC0 + Timer/Counter, 8-bit + 0x35 + + 0 + 0x100 + registers + + + + GTCCR + General Timer/Counter Control Register + 0xE + + + PSRSYNC + Prescaler Reset Timer/Counter1 and Timer/Counter0 + [0:0] + + + TSM + Timer/Counter Synchronization Mode + [7:7] + + + + + OCR0A + Timer/Counter0 Output Compare Register + 0x12 + + + 0 + 255 + + + + + OCR0B + Timer/Counter0 Output Compare Register + 0x13 + + + 0 + 255 + + + + + TCCR0A + Timer/Counter Control Register A + 0xF + + + WGM0 + Waveform Generation Mode + [1:0] + + + 0 + 3 + + + + + COM0B + Compare Output Mode, Fast PWm + [5:4] + + + 0 + 3 + + + + + COM0A + Compare Output Mode, Phase Correct PWM Mode + [7:6] + + + 0 + 3 + + + + + + + TCCR0B + Timer/Counter Control Register B + 0x10 + + + CS0 + Clock Select + [2:0] + + true + + + + VAL_0x00 + No Clock Source (Stopped) + 0 + + + VAL_0x01 + Running, No Prescaling + 1 + + + VAL_0x02 + Running, CLK/8 + 2 + + + VAL_0x03 + Running, CLK/64 + 3 + + + VAL_0x04 + Running, CLK/256 + 4 + + + VAL_0x05 + Running, CLK/1024 + 5 + + + VAL_0x06 + Running, ExtClk Tx Falling Edge + 6 + + + VAL_0x07 + Running, ExtClk Tx Rising Edge + 7 + + + + + WGM02 + <TBD> + [3:3] + + + FOC0B + Force Output Compare B + [6:6] + + + FOC0A + Force Output Compare A + [7:7] + + + + + TCNT0 + Timer/Counter0 + 0x11 + + + 0 + 255 + + + + + TIFR0 + Timer/Counter0 Interrupt Flag register + 0x0 + read-only + + + TOV0 + Timer/Counter0 Overflow Flag + [0:0] + + + OCF0A + Timer/Counter0 Output Compare Flag 0A + [1:1] + + + OCF0B + Timer/Counter0 Output Compare Flag 0B + [2:2] + + + + + TIMSK0 + Timer/Counter0 Interrupt Mask Register + 0x39 + + + TOIE0 + Timer/Counter0 Overflow Interrupt Enable + [0:0] + + + OCIE0A + Timer/Counter0 Output Compare Match A Interrupt Enable + [1:1] + + + OCIE0B + Timer/Counter0 Output Compare Match B Interrupt Enable + [2:2] + + + + + + + TC1 + Timer/Counter, 16-bit + 0x36 + + 0 + 0x100 + registers + + + + GTCCR + General Timer/Counter Control Register + 0xD + + + PSRSYNC + Prescaler Reset Timer/Counter1 and Timer/Counter0 + [0:0] + + + TSM + Timer/Counter Synchronization Mode + [7:7] + + + + + ICR1 + Timer/Counter1 Input Capture Register Bytes + 0x50 + 16 + + + 0 + 65535 + + + + + OCR1A + Timer/Counter1 Output Compare Register Bytes + 0x52 + 16 + + + 0 + 65535 + + + + + OCR1B + Timer/Counter1 Output Compare Register Bytes + 0x54 + 16 + + + 0 + 65535 + + + + + TCCR1A + Timer/Counter1 Control Register A + 0x4A + + + WGM1 + Waveform Generation Mode + [1:0] + + + 0 + 3 + + + + + COM1B + Compare Output Mode 1B, bits + [5:4] + + + 0 + 3 + + + + + COM1A + Compare Output Mode 1A, bits + [7:6] + + + 0 + 3 + + + + + + + TCCR1B + Timer/Counter1 Control Register B + 0x4B + + + CS1 + Prescaler source of Timer/Counter 1 + [2:0] + + true + + + + VAL_0x00 + No Clock Source (Stopped) + 0 + + + VAL_0x01 + Running, No Prescaling + 1 + + + VAL_0x02 + Running, CLK/8 + 2 + + + VAL_0x03 + Running, CLK/64 + 3 + + + VAL_0x04 + Running, CLK/256 + 4 + + + VAL_0x05 + Running, CLK/1024 + 5 + + + VAL_0x06 + Running, ExtClk Tx Falling Edge + 6 + + + VAL_0x07 + Running, ExtClk Tx Rising Edge + 7 + + + + + WGM1 + Waveform Generation Mode + [4:3] + + + 0 + 3 + + + + + ICES1 + Input Capture 1 Edge Select + [6:6] + + + ICNC1 + Input Capture 1 Noise Canceler + [7:7] + + + + + TCCR1C + Timer/Counter1 Control Register C + 0x4C + + + FOC1B + <TBD> + [6:6] + + + FOC1A + <TBD> + [7:7] + + + + + TCNT1 + Timer/Counter1 Bytes + 0x4E + 16 + + + 0 + 65535 + + + + + TIFR1 + Timer/Counter Interrupt Flag register + 0x0 + read-only + + + TOV1 + Timer/Counter1 Overflow Flag + [0:0] + + + OCF1A + Output Compare Flag 1A + [1:1] + + + OCF1B + Output Compare Flag 1B + [2:2] + + + ICF1 + Input Capture Flag 1 + [5:5] + + + + + TIMSK1 + Timer/Counter Interrupt Mask Register + 0x39 + + + TOIE1 + Timer/Counter1 Overflow Interrupt Enable + [0:0] + + + OCIE1A + Timer/Counter1 Output CompareA Match Interrupt Enable + [1:1] + + + OCIE1B + Timer/Counter1 Output CompareB Match Interrupt Enable + [2:2] + + + ICIE1 + Timer/Counter1 Input Capture Interrupt Enable + [5:5] + + + + + + + TC2 + Timer/Counter, 8-bit Async + 0x37 + + 0 + 0x100 + registers + + + + ASSR + Asynchronous Status Register + 0x7F + + + TCR2BUB + Timer/Counter Control Register2 Update Busy + [0:0] + + + TCR2AUB + Timer/Counter Control Register2 Update Busy + [1:1] + + + OCR2BUB + Output Compare Register 2 Update Busy + [2:2] + + + OCR2AUB + Output Compare Register2 Update Busy + [3:3] + + + TCN2UB + Timer/Counter2 Update Busy + [4:4] + + + AS2 + Asynchronous Timer/Counter2 + [5:5] + + + EXCLK + Enable External Clock Input + [6:6] + + + + + GTCCR + General Timer Counter Control register + 0xC + + + PSRASY + Prescaler Reset Timer/Counter2 + [1:1] + + + TSM + Timer/Counter Synchronization Mode + [7:7] + + + + + OCR2A + Timer/Counter2 Output Compare Register A + 0x7C + + + 0 + 255 + + + + + OCR2B + Timer/Counter2 Output Compare Register B + 0x7D + + + 0 + 255 + + + + + TCCR2A + Timer/Counter2 Control Register A + 0x79 + + + WGM2 + Waveform Genration Mode + [1:0] + + + 0 + 3 + + + + + COM2B + Compare Output Mode bits + [5:4] + + + 0 + 3 + + + + + COM2A + Compare Output Mode bits + [7:6] + + + 0 + 3 + + + + + + + TCCR2B + Timer/Counter2 Control Register B + 0x7A + + + CS2 + Clock Select bits + [2:0] + + true + + + + VAL_0x00 + No Clock Source (Stopped) + 0 + + + VAL_0x01 + Running, No Prescaling + 1 + + + VAL_0x02 + Running, CLK/8 + 2 + + + VAL_0x03 + Running, CLK/32 + 3 + + + VAL_0x04 + Running, CLK/64 + 4 + + + VAL_0x05 + Running, CLK/128 + 5 + + + VAL_0x06 + Running, CLK/256 + 6 + + + VAL_0x07 + Running, CLK/1024 + 7 + + + + + WGM22 + Waveform Generation Mode + [3:3] + + + FOC2B + Force Output Compare B + [6:6] + + + FOC2A + Force Output Compare A + [7:7] + + + + + TCNT2 + Timer/Counter2 + 0x7B + + + 0 + 255 + + + + + TIFR2 + Timer/Counter Interrupt Flag Register + 0x0 + read-only + + + TOV2 + Timer/Counter2 Overflow Flag + [0:0] + + + OCF2A + Output Compare Flag 2A + [1:1] + + + OCF2B + Output Compare Flag 2B + [2:2] + + + + + TIMSK2 + Timer/Counter Interrupt Mask register + 0x39 + + + TOIE2 + Timer/Counter2 Overflow Interrupt Enable + [0:0] + + + OCIE2A + Timer/Counter2 Output Compare Match A Interrupt Enable + [1:1] + + + OCIE2B + Timer/Counter2 Output Compare Match B Interrupt Enable + [2:2] + + + + + + + TWI + Two Wire Serial Interface + 0xB8 + + 0 + 0x100 + registers + + + + TWAMR + TWI (Slave) Address Mask Register + 0x5 + + + TWAM + <TBD> + [7:1] + + + 0 + 127 + + + + + + + TWAR + TWI (Slave) Address register + 0x2 + + + TWGCE + TWI General Call Recognition Enable Bit + [0:0] + + + TWA + TWI (Slave) Address register Bits + [7:1] + + + 0 + 127 + + + + + + + TWBR + TWI Bit Rate register + 0x0 + + + 0 + 255 + + + + + TWCR + TWI Control Register + 0x4 + read-only + + + TWIE + TWI Interrupt Enable + [0:0] + + + TWEN + TWI Enable Bit + [2:2] + + + TWWC + TWI Write Collition Flag + [3:3] + + + TWSTO + TWI Stop Condition Bit + [4:4] + + + TWSTA + TWI Start Condition Bit + [5:5] + + + TWEA + TWI Enable Acknowledge Bit + [6:6] + + + TWINT + TWI Interrupt Flag + [7:7] + + + + + TWDR + TWI Data register + 0x3 + + + 0 + 255 + + + + + TWSR + TWI Status Register + 0x1 + + + TWPS + TWI Prescaler + [1:0] + + true + + + + VAL_0x00 + 1 + 0 + + + VAL_0x01 + 4 + 1 + + + VAL_0x02 + 16 + 2 + + + VAL_0x03 + 64 + 3 + + + + + TWS + TWI Status + [7:3] + + + 0 + 31 + + + + + + + + + USART0 + USART + 0xC0 + + 0 + 0x100 + registers + + + + UBRR0 + USART Baud Rate Register Bytes + 0x4 + 16 + + + 0 + 65535 + + + + + UCSR0A + USART Control and Status Register A + 0x0 + read-only + + + MPCM0 + Multi-processor Communication Mode + [0:0] + + + U2X0 + Double the USART transmission speed + [1:1] + + + UPE0 + Parity Error + [2:2] + + + DOR0 + Data overRun + [3:3] + + + FE0 + Framing Error + [4:4] + + + UDRE0 + USART Data Register Empty + [5:5] + + + TXC0 + USART Transmitt Complete + [6:6] + + + RXC0 + USART Receive Complete + [7:7] + + + + + UCSR0B + USART Control and Status Register B + 0x1 + + + TXB80 + Transmit Data Bit 8 + [0:0] + + + RXB80 + Receive Data Bit 8 + [1:1] + + + UCSZ02 + Character Size + [2:2] + + + TXEN0 + Transmitter Enable + [3:3] + + + RXEN0 + Receiver Enable + [4:4] + + + UDRIE0 + USART Data register Empty Interrupt Enable + [5:5] + + + TXCIE0 + TX Complete Interrupt Enable + [6:6] + + + RXCIE0 + RX Complete Interrupt Enable + [7:7] + + + + + UCSR0C + USART Control and Status Register C + 0x2 + + + UCPOL0 + Clock Polarity + [0:0] + + + UCSZ0 + Character Size + [2:1] + + + 0 + 3 + + + + + USBS0 + Stop Bit Select + [3:3] + + true + + + + VAL_0x00 + 1-bit + 0 + + + VAL_0x01 + 2-bit + 1 + + + + + UPM0 + Parity Mode Bits + [5:4] + + true + + + + VAL_0x00 + Disabled + 0 + + + VAL_0x01 + Reserved + 1 + + + VAL_0x02 + Enabled, Even Parity + 2 + + + VAL_0x03 + Enabled, Odd Parity + 3 + + + + + UMSEL0 + USART Mode Select + [7:6] + + true + + + + VAL_0x00 + Asynchronous USART + 0 + + + VAL_0x01 + Synchronous USART + 1 + + + VAL_0x03 + Master SPI + 3 + + + + + + + UDR0 + USART I/O Data Register + 0x6 + + + 0 + 255 + + + + + + + WDT + Watchdog Timer + 0x60 + + 0 + 0x100 + registers + + + + WDTCSR + Watchdog Timer Control Register + 0x0 + read-only + + + WDP + Watchdog Timer Prescaler Bits + [5:0] + + true + + + + VAL_0x00 + Oscillator Cycles 2K + 0 + + + VAL_0x01 + Oscillator Cycles 4K + 1 + + + VAL_0x02 + Oscillator Cycles 8K + 2 + + + VAL_0x03 + Oscillator Cycles 16K + 3 + + + VAL_0x04 + Oscillator Cycles 32K + 4 + + + VAL_0x05 + Oscillator Cycles 64K + 5 + + + VAL_0x06 + Oscillator Cycles 128K + 6 + + + VAL_0x07 + Oscillator Cycles 256K + 7 + + + + + WDE + Watch Dog Enable + [3:3] + + + WDCE + Watchdog Change Enable + [4:4] + + + WDIE + Watchdog Timeout Interrupt Enable + [6:6] + + + WDIF + Watchdog Timeout Interrupt Flag + [7:7] + + + + + + + \ No newline at end of file diff --git a/lib/avr328p.rob b/lib/avr328p.rob index 6f8e8d1..4778d35 100644 --- a/lib/avr328p.rob +++ b/lib/avr328p.rob @@ -2,21 +2,52 @@ * Robcmp interruptions vector for atmega328p */ - void main(); - void __vectors(); - - // implemented in avr5.S - void __do_copy_data(); - void __do_clear_bss(); +int8 main(); + +void __do_copy_data() naked { +asm " + ldi r17, hi8(__data_end) + ldi r26, lo8(__data_start) + ldi r27, hi8(__data_start) + ldi r30, lo8(__data_load_start) + ldi r31, hi8(__data_load_start) + rjmp __do_copy_data_start + __do_copy_data_loop: + lpm r0, Z+ + st X+, r0 + __do_copy_data_start: + cpi r26, lo8(__data_end) + cpc r27, r17 + brne __do_copy_data_loop + ret"; +} + +void __do_clear_bss() naked { +asm " + ldi r17, hi8(__bss_end) + ldi r26, lo8(__bss_start) + ldi r27, hi8(__bss_start) + rjmp __do_clear_bss_start + __do_clear_bss_loop: + st X+, r1 + __do_clear_bss_start: + cpi r26, lo8(__bss_end) + cpc r27, r17 + brne __do_clear_bss_loop + ret"; +} - void __delay_us() { - asm "ldi r18, 5"; - asm "__delay_ms_loop: dec r18"; - asm "brne __delay_ms_loop"; - asm "nop"; - } +void __delay_us() naked { +asm " + ldi r18, 5 + __delay_ms_loop: + dec r18 + brne __delay_ms_loop + nop + ret"; +} - void __vectors() section __isr { +void __vectors() naked, section __isr { /* FIXME: provide proper interrupt functions instead of __vectors * after implementing "weak" attribute for functions */ diff --git a/lib/avr5.S b/lib/avr5.S index c469ce1..b456ae0 100644 --- a/lib/avr5.S +++ b/lib/avr5.S @@ -326,42 +326,6 @@ __divmodhi4_exit: ENDF __divmodhi4 -/* - * Copy data and clear bss - */ - -DEFUN __do_copy_data - ldi r17, hi8(__data_end) - ldi r26, lo8(__data_start) - ldi r27, hi8(__data_start) - ldi r30, lo8(__data_load_start) - ldi r31, hi8(__data_load_start) - rjmp __do_copy_data_start -__do_copy_data_loop: - lpm r0, Z+ - st X+, r0 -__do_copy_data_start: - cpi r26, lo8(__data_end) - cpc r27, r17 - brne __do_copy_data_loop - ret -ENDF __do_copy_data - -DEFUN __do_clear_bss - ldi r17, hi8(__bss_end) - ldi r26, lo8(__bss_start) - ldi r27, hi8(__bss_start) - rjmp __do_clear_bss_start -__do_clear_bss_loop: - st X+, __zero_reg__ -__do_clear_bss_start: - cpi r26, lo8(__bss_end) - cpc r27, r17 - brne __do_clear_bss_loop - ret -ENDF __do_clear_bss - - /* memset function for avr, based on avr libc */ #define dest_hi r25 #define dest_lo r24 diff --git a/lib/avr5.ld b/lib/avr5.ld index 71018e2..6e64a17 100644 --- a/lib/avr5.ld +++ b/lib/avr5.ld @@ -8,9 +8,11 @@ OUTPUT_ARCH(avr:5) SECTIONS { .text : { - KEEP(*(__isr)) - . = ALIGN(2); - __text_start = .; + _start = .; + *(__isr) + KEEP(*(__isr)) + . = ALIGN(2); + __text_start = .; *(.progmem*) . = ALIGN(2); *(.text) @@ -23,25 +25,17 @@ SECTIONS .data : { __data_start = .; *(.data) - *(.data*) - . = ALIGN(16); - *(.rodata) /* We need to include .rodata here if gcc is used */ - *(.rodata*) /* with -fdata-sections. */ - . = ALIGN(2); + *(.data.*) + KEEP(*(.rodata)) + KEEP(*(.rodata.*)) __data_end = .; } > data AT> text .bss ADDR(.data) + SIZEOF(.data) : AT (ADDR (.bss)) { __bss_start = .; *(.bss) - . = ALIGN(2); - KEEP(*(.bss)) - *(.bss*) - . = ALIGN(2); - KEEP(*(.bss*)) + *(.bss.*) *(COMMON) - . = ALIGN(2); - KEEP(*(COMMON)) __bss_end = .; } > data diff --git a/src/Array.cpp b/src/Array.cpp index 820a455..1be8341 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -10,7 +10,11 @@ Array::Array(const string& n, ArrayElements *aes, location_t loc) : Variable(n, loc), elements(aes) { NamedConst *nc = new NamedConst("size", getNodeForUIntConst(aes->getArraySize(), loc), loc); addChild(nc); - addSymbol("size", nc); + addSymbol(nc); +} + +Array::Array(const string& n, location_t loc) : Variable(n, loc) { + elements = new ArrayElements(getLoc()); } DataType Array::getDataType() { diff --git a/src/Array.h b/src/Array.h index 44aad99..d1619f2 100644 --- a/src/Array.h +++ b/src/Array.h @@ -32,13 +32,14 @@ class Array: public Variable { public: Array(const string& n, ArrayElements *aes, location_t loc); + Array(const string& n, location_t loc); virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; static Node *getElementIndex(Node *p1, Node *p2, const string& name, int p1size = -1, int p2size = -1, Node *columnNumber = NULL); - std::vector getElements() { + virtual std::vector& getElements() { return elements->getElements(); } @@ -46,13 +47,13 @@ class Array: public Variable { virtual Type *getLLVMType() override; - DataType getDataType() override; + virtual DataType getDataType() override; - DataType getElementDataType() { + virtual DataType getElementDataType() { return element_dt; } - int getSize() const { + virtual int getSize() const { return size; } }; diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 5e101d7..e7510c0 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -105,6 +105,7 @@ void setup_target_machine(char opt_level) { TargetOptions opt; opt.FunctionSections = true; opt.DataSections = true; + opt.ExceptionModel = ExceptionHandling::None; auto reloc = Reloc::PIC_; if (ai.backend == rb_arm) diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index b3fd092..19de532 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -201,9 +201,12 @@ void BuildTypes::generateDebugInfoForUserType(DataTypeInfo &info, Node *userType // search the injections string fieldName = info.name; fieldName.append("." + m->getName()); - string injType = injections[fieldName].first; - Node *symbol = Identifier(injType, userType->getLoc()).getSymbol(program, false); - mdt = symbol->getDataType(); + if (injections.find(fieldName) != injections.end()) { + string injType = injections[fieldName].first; + Node *symbol = Identifier(injType, userType->getLoc()).getSymbol(program, false); + if (symbol) + mdt = symbol->getDataType(); + } } if (mdt == -1 || tinfo[mdt].bitWidth == 0) { continue; @@ -270,3 +273,19 @@ void BuildTypes::generateDebugInfoForTypes() { generateDebugInfoForUserType(info, userType); } } + +bool BuildTypes::isArrayCompatible(DataType srcDt, DataType destDt) { + if (isArray(srcDt) ^ isArray(destDt)) + return false; + if (tinfo[srcDt].arrayDimensions != tinfo[destDt].arrayDimensions) + return false; + DataType elSrc = getArrayElementType(srcDt); + DataType elDest = getArrayElementType(destDt); + if (elSrc != elDest) { + if ((elSrc == tint8 || elSrc == tint8u || elSrc == tchar) && + (elDest == tint8 || elDest == tint8u || elDest == tchar)) { + return true; + } + } + return true; +} \ No newline at end of file diff --git a/src/BuildTypes.h b/src/BuildTypes.h index 5d08617..2c839cf 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -251,6 +251,8 @@ class BuildTypes { } void generateDebugInfoForTypes(); + + bool isArrayCompatible(DataType srcDt, DataType destDt); }; // TODO: Replace all places with buildType::name diff --git a/src/FunctionAttributes.h b/src/FunctionAttributes.h index c5584d4..eee7197 100644 --- a/src/FunctionAttributes.h +++ b/src/FunctionAttributes.h @@ -1,7 +1,7 @@ #pragma once -enum FunctionAttributeType {fa_weak, fa_inline, fa_noinline, fa_section}; +enum FunctionAttributeType {fa_weak, fa_inline, fa_noinline, fa_section, fa_naked}; typedef pair FunctionAttribute; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 8c7e842..b2130b9 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -117,7 +117,7 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock } } } else if (buildTypes->isArrayOrMatrix(call_dt)) { - if (call_dt != def_dt) { + if (!buildTypes->isArrayCompatible(call_dt, def_dt)) { yyerrorcpp(string_format("Argument %s expects '%s' but '%s' was provided.", argName.c_str(), buildTypes->name(def_dt), @@ -145,11 +145,19 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock } for(const string& p: params) { - string pname = param->getName() + p; - Load ld(Identifier(pname, param->getLoc())); - ld.setScope(func); - Node *coerced = PropagateTypes::coerceTo(&ld, tint32u); - Value *value = coerced->generate(func, block, allocblock); + Node *coerced; + Value *value; + if (param->isConstExpr()) { + Node *size = param->findMember("size"); + coerced = PropagateTypes::coerceTo(size, tint32u); + value = coerced->generate(func, block, allocblock); + } else { + string pname = param->getName() + p; + Load ld(Identifier(pname, param->getLoc())); + ld.setScope(func); + coerced = PropagateTypes::coerceTo(&ld, tint32u); + value = coerced->generate(func, block, allocblock); + } args.push_back(value); dataTypes.push_back(coerced->getDataType()); } diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 3f49521..51fbb41 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -1,6 +1,7 @@ #include "FunctionDecl.h" #include "BackLLVM.h" +#include "FunctionAttributes.h" #include "Matrix.h" void FunctionBase::addThisArgument(DataType dt) { @@ -102,6 +103,11 @@ void FunctionBase::addFunctionAttributes(Function *func) { case fa_section: func->setSection(attr->second); break; + case fa_naked: + func->addFnAttr(Attribute::Naked); + func->addFnAttr(Attribute::NoInline); + func->addFnAttr(Attribute::OptimizeNone); + break; } } } diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index dd7dedc..2aa7fa4 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -155,7 +155,10 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo } } - BranchInst::Create(fblock, falloc); + if (falloc->empty()) + falloc->removeFromParent(); + else + BranchInst::Create(fblock, falloc); if (debug_info) RobDbgInfo.pop_scope(); diff --git a/src/Header.h b/src/Header.h index 5499a94..07221a5 100644 --- a/src/Header.h +++ b/src/Header.h @@ -41,6 +41,7 @@ #include "UpdateArray.h" #include "UpdateMatrix.h" #include "Array.h" +#include "StringConst.h" #include "While.h" #include "Loop.h" #include "Pointer.h" diff --git a/src/Identifier.h b/src/Identifier.h index bf7581e..68889f2 100644 --- a/src/Identifier.h +++ b/src/Identifier.h @@ -20,7 +20,7 @@ class Identifier: public SourceLocation { return ident; } - bool isComplex() { + bool isComplex() const { return complex; } diff --git a/src/Language.l b/src/Language.l index 4075328..67848e4 100644 --- a/src/Language.l +++ b/src/Language.l @@ -48,6 +48,7 @@ EXP ([Ee][-+]?[0-9]+)? "noinline" { return TOK_NOINLINE; } "weak" { return TOK_WEAK; } "section" { return TOK_SECTION; } +"naked" { return TOK_NAKED; } "bind" { return TOK_BIND; } "to" { return TOK_TO; } diff --git a/src/Language.y b/src/Language.y index 19e1a04..4d838e6 100644 --- a/src/Language.y +++ b/src/Language.y @@ -148,6 +148,7 @@ function_attribute : TOK_WEAK { $$ = new FunctionAttribute(fa_weak, ""); } | TOK_INLINE { $$ = new FunctionAttribute(fa_inline, ""); } | TOK_NOINLINE { $$ = new FunctionAttribute(fa_noinline, ""); } + | TOK_NAKED { $$ = new FunctionAttribute(fa_naked, ""); } | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } event : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { @@ -436,6 +437,7 @@ factor : '(' expr ')' { $$ = $2; } | TOK_FLOAT { $$ = new Float($1, @1); } | TOK_DOUBLE { $$ = new Double($1, @1); } | TOK_LDOUBLE { $$ = new Float128($1, @1); } + | TOK_STRING { $$ = new StringConst("conststr", $1, @1); } | ident_or_xident[id] '[' expr ']' { $$ = new LoadArray($1, $3, @id);} | ident_or_xident[id] '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6, @id);} | call_or_cast diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index eb2a2f2..6b3fd3b 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -35,7 +35,7 @@ %token TOK_QUANDO TOK_ESTA %token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT -%token TOK_INLINE TOK_NOINLINE TOK_WEAK TOK_SECTION +%token TOK_INLINE TOK_NOINLINE TOK_WEAK TOK_SECTION TOK_NAKED %union { char *ident; diff --git a/src/LanguageUse.y b/src/LanguageUse.y index aff3573..80cba72 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -156,6 +156,7 @@ function_attribute : TOK_WEAK { $$ = new FunctionAttribute(fa_weak, ""); } | TOK_INLINE { $$ = new FunctionAttribute(fa_inline, ""); } | TOK_NOINLINE { $$ = new FunctionAttribute(fa_noinline, ""); } + | TOK_NAKED { $$ = new FunctionAttribute(fa_naked, ""); } | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } qualifier : TOK_CONST { $$ = qconst; } diff --git a/src/NamedConst.h b/src/NamedConst.h index 1b7cd9f..8f6e566 100644 --- a/src/NamedConst.h +++ b/src/NamedConst.h @@ -10,12 +10,16 @@ class NamedConst: public NamedNode { public: NamedConst(const char *name, location_t loc) : NamedNode(name, loc) {} - NamedConst(const char *name, Node *value, location_t loc) : NamedNode(name, loc), value(value) { + NamedConst(const char *name, Node *v, location_t loc) : NamedNode(name, loc), value(v) { dt = value->getDataType(); } + Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + return value->generate(NULL, NULL, NULL); + } + virtual Value *getLLVMValue(Node *stem) override { - return value->generate(NULL, NULL, NULL); //FIXME + return value->generate(NULL, NULL, NULL); } virtual bool isConstExpr() override { diff --git a/src/Pointer.cpp b/src/Pointer.cpp index 197a7fd..f86900a 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -38,18 +38,7 @@ Value *Pointer::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo // as a ConstantExpr. This limits pointer arithmetic. Constant *addr_num = dyn_cast(addr); assert(addr_num && "FIXME: global pointer defined without constant address."); - Constant *calloc = ConstantExpr::getIntToPtr(addr_num, targetPointerType); - alloc = calloc; - - extern bool build_dependencies; - if (debug_info && build_dependencies) { - // we add a global variable associated with the pointer - // to easy debugging - GlobalVariable *gv = new GlobalVariable(*mainmodule, targetPointerType, false, - GlobalValue::ExternalLinkage, calloc, name); - RobDbgInfo.declareGlobalVar(this, gv, allocblock); - } - + alloc = ConstantExpr::getIntToPtr(addr_num, targetPointerType); return alloc; } diff --git a/src/PropagateTypes.cpp b/src/PropagateTypes.cpp index 43a65dd..aeb9966 100644 --- a/src/PropagateTypes.cpp +++ b/src/PropagateTypes.cpp @@ -405,6 +405,13 @@ Node* PropagateTypes::visit(Variable& n) { bool checkCoercion = false; DataType destDt = BuildTypes::undefinedType; + + // Verify if a complex identifier exists + Identifier& id = n.getIdent(); + if (id.isComplex()) { + if (!id.getSymbol(&n, true)) + return NULL; + } Node *firstDecl = n.getScope()->findSymbol(n.getName()); DataType sameNameDt = buildTypes->getType(n.getName()); diff --git a/src/SourceLocation.h b/src/SourceLocation.h index 03b38ec..5c49de6 100644 --- a/src/SourceLocation.h +++ b/src/SourceLocation.h @@ -49,7 +49,7 @@ class SourceLocation { return buildStack[fileNo]; } - bool hasSemanticError() { + bool hasSemanticError() const { return semanticError; } diff --git a/src/StringConst.cpp b/src/StringConst.cpp index 499f0ea..774c17d 100644 --- a/src/StringConst.cpp +++ b/src/StringConst.cpp @@ -1,6 +1,15 @@ #include "StringConst.h" +#include "NamedConst.h" -Value *StringConst::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - return ConstantDataArray::getString(global_context, str, true);; +StringConst::StringConst(const string& name, const string& str, location_t loc) : + Array(name, loc), str(str) { + NamedConst *nc = new NamedConst("size", getNodeForUIntConst(str.size(), loc), loc); + addChild(nc); + addSymbol(nc); +} + +Value* StringConst::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + Builder->SetInsertPoint(block); + return Builder->CreateGlobalStringPtr(str, name); } diff --git a/src/StringConst.h b/src/StringConst.h index 70d55a0..3fc4ae9 100644 --- a/src/StringConst.h +++ b/src/StringConst.h @@ -1,12 +1,36 @@ #pragma once -#include "Node.h" +#include "Array.h" +#include "HeaderGlobals.h" -class StringConst: public Node { -private: - string str; +class StringConst: public Array { +protected: + string str; public: - StringConst(const char *s, location_t loc): Node(loc), str(s) {} - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); + StringConst(const string& name, const string& str, location_t loc); + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual DataType getDataType() override { + if (dt == BuildTypes::undefinedType) + dt = buildTypes->getArrayType(buildTypes->name(tchar), getLoc(), 1, true); + return dt; + } + + virtual DataType getElementDataType() override { + return tchar; + } + + virtual int getSize() const override { + return str.size(); + } + + virtual Type *getLLVMType() override { + return buildTypes->llvmType(dt); + } + + virtual bool isConstExpr() override { + return true; + } }; diff --git a/src/Variable.h b/src/Variable.h index 216e252..8d725b9 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -47,4 +47,8 @@ class Variable: public NamedNode { } virtual void setExpr(Node *e) {} + + Identifier& getIdent() { + return ident; + } }; diff --git a/test/avr328p/runtest.sh b/test/avr328p/runtest.sh index 3bf0af9..435d7c9 100755 --- a/test/avr328p/runtest.sh +++ b/test/avr328p/runtest.sh @@ -13,11 +13,11 @@ if [ "$?" -eq 0 ]; then else timeout 10s ${CMD} &> /dev/null fi - #./$2 &> /dev/null - if [ "$?" -eq 0 ]; then + STATUS=$? + if [ "${STATUS}" -eq 0 ]; then echo -e \\r${GREEN}[PASS]\\t\\t${NC} else - echo -e \\r${RED}[FAILED]\\t${NC} + echo -e \\r${RED}[FAILED] ${STATUS}\\t${NC} fi else echo -e \\r${RED}[BUILD FAILED]\\t${NC} From 28de518544cc0e4e66ae589d394ce45da051a2ef Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Tue, 25 Jun 2024 09:15:56 -0300 Subject: [PATCH 066/117] Improves injections error messages --- lib/stm32f1.ld | 1 + src/BackLLVM.cpp | 2 +- src/BackLLVM.h | 4 ++-- src/BuildTypes.cpp | 2 +- src/Injections.h | 19 +++++++++++++++++++ src/Language.y | 2 +- src/Program.cpp | 20 ++++++++------------ 7 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 src/Injections.h diff --git a/lib/stm32f1.ld b/lib/stm32f1.ld index 02532f4..8e4552c 100644 --- a/lib/stm32f1.ld +++ b/lib/stm32f1.ld @@ -9,6 +9,7 @@ __reset_stack_pointer = ORIGIN(RAM) + LENGTH(RAM); SECTIONS { .isr_vector : { + _start = .; LONG(__reset_stack_pointer); LONG(__isr_reset | 1); LONG(__isr_nmi | 1); diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index e7510c0..ec3ce7e 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -44,7 +44,7 @@ unsigned int dataAddrSpace = 0; // Injections -map> injections; +map injections; enum SupportedTargets currentTargetId; extern char *build_outputfilename; diff --git a/src/BackLLVM.h b/src/BackLLVM.h index 8ccc163..3b3724a 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -2,6 +2,7 @@ #pragma once #include "BuildTypes.h" +#include "Injections.h" extern std::unique_ptr> Builder; @@ -28,5 +29,4 @@ const TargetInfo& currentTarget(); class Variable; -enum BindScope {bs_singleton, bs_transient}; -extern map> injections; +extern map injections; diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 19de532..ba0bcdf 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -202,7 +202,7 @@ void BuildTypes::generateDebugInfoForUserType(DataTypeInfo &info, Node *userType string fieldName = info.name; fieldName.append("." + m->getName()); if (injections.find(fieldName) != injections.end()) { - string injType = injections[fieldName].first; + string injType = injections[fieldName]->bind; Node *symbol = Identifier(injType, userType->getLoc()).getSymbol(program, false); if (symbol) mdt = symbol->getDataType(); diff --git a/src/Injections.h b/src/Injections.h new file mode 100644 index 0000000..bafbbf9 --- /dev/null +++ b/src/Injections.h @@ -0,0 +1,19 @@ + +#pragma once + +#include + +enum BindScope {bs_singleton, bs_transient}; + +struct Injection { + string bind; + string to; + BindScope scope; + SourceLocation loc; + Injection(const string& bind, const string& to, + BindScope scope, const SourceLocation& loc): loc(loc) { + this->bind = bind; + this->to = to; + this->scope = scope; + } +}; diff --git a/src/Language.y b/src/Language.y index 4d838e6..4e5eeec 100644 --- a/src/Language.y +++ b/src/Language.y @@ -264,7 +264,7 @@ simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array, @id simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix, @id); } bind : TOK_BIND ident_or_xident[id] TOK_TO ident_or_xident[to] bind_scope[scope] ';' { - injections.insert({$to, make_pair(string($id), BindScope($scope))}); + injections.insert({$to, new Injection($id, $to, BindScope($scope), @id)}); $$ = NULL; } diff --git a/src/Program.cpp b/src/Program.cpp index 37b24ae..3b302ae 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -63,16 +63,15 @@ void Program::generateInjectionSetup(SourceLocation *sl) { vector finjects; for (auto &[key, itype] : injections) { Identifier to(key, loc); - Identifier bind(itype.first, loc); - BindScope scope(itype.second); + Identifier bind(itype->bind, loc); // injection validation auto subTypeName = regex_replace(bind.getFullName(), regex("\\."), ":"); //internal types use : Identifier bindSubtypes(subTypeName, loc); - Node *injectType = bindSubtypes.getSymbol(this); + Node *injectType = bindSubtypes.getSymbol(this, false); if (!injectType) { yyerrorcpp(string_format("Injection symbol %s not found.", - bind.getFullName().c_str()), this); + bind.getFullName().c_str()), &itype->loc); continue; } @@ -81,20 +80,20 @@ void Program::generateInjectionSetup(SourceLocation *sl) { UserType *bindUserTy = dynamic_cast(injectType); if (!bindUserTy) { yyerrorcpp(string_format("Bind symbol %s is not of a bindable type.", - bind.getFullName().c_str()), this); + bind.getFullName().c_str()), &itype->loc); continue; } else { - Node *nodeTo = to.getSymbol(this); + Node *nodeTo = to.getSymbol(this, false); if (!nodeTo) { yyerrorcpp(string_format("Injection destination %s not found.", - bind.getFullName().c_str()), this); + to.getFullName().c_str()), &itype->loc); continue; } else { destinationTy = nodeTo->getDataType(); destinationTyName = buildTypes->name(destinationTy); if (!bindUserTy->implementsInterface(destinationTyName)) { yyerrorcpp(string_format("Bind symbol %s does not implements %s.", - bind.getFullName().c_str(), destinationTyName.c_str()), this); + bind.getFullName().c_str(), destinationTyName.c_str()), bindUserTy); continue; } } @@ -109,7 +108,7 @@ void Program::generateInjectionSetup(SourceLocation *sl) { finject->setScope(this); finject->setAttributes(new FunctionAttributes(fa_inline)); - if (scope == bs_singleton) { + if (itype->scope == bs_singleton) { string globalVarName; if (bind.isComplex()) { globalVarName = ":var_injection_for_" + bind.getFullName(); @@ -168,9 +167,6 @@ void Program::generateInjectionSetup(SourceLocation *sl) { vector args; for(auto& arg : aliasFunc->args()) { - //Value *alloc = Builder->CreateAlloca(arg.getType()); - //Value *store = Builder->CreateStore(&arg, alloc); - //Value *load = Builder->CreateLoad(arg.getType(), alloc); args.push_back(&arg); } From edf53e02943e298a95768f498ef52deeb7ce8f49 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 30 Jun 2024 10:01:20 -0300 Subject: [PATCH 067/117] Add int9 type to support some registers in stm32. --- src/BuildTypes.cpp | 1 + src/BuildTypes.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index ba0bcdf..7ae8e2e 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -30,6 +30,7 @@ BuildTypes::BuildTypes(DataType targetPointerType) : tinfo[tint6u] = {"uint6", 6, Type::getIntNTy(global_context, 6), dwarf::DW_ATE_unsigned}; tinfo[tint7u] = {"uint7", 7, Type::getIntNTy(global_context, 7), dwarf::DW_ATE_unsigned}; tinfo[tint8u] = {"uint8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint9u] = {"uint9", 8, Type::getIntNTy(global_context, 9), dwarf::DW_ATE_unsigned}; tinfo[tint12u] = {"uint12", 12, Type::getIntNTy(global_context, 12),dwarf::DW_ATE_unsigned}; tinfo[tint16u] = {"uint16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tint32u] = {"uint32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; diff --git a/src/BuildTypes.h b/src/BuildTypes.h index 2c839cf..f659e19 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -13,7 +13,7 @@ typedef int DataType; enum BasicDataType {tvoid, tbool, tchar, tint8, tint16, tint32, tint64, tint2u, tint3u, tint4u, tint5u, tint6u, tint7u, - tint8u, tint12u, tint16u, tint32u, tint64u, + tint8u, tint9u, tint12u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, /* new types here! */ __bdt_last}; From c5bacea4a12e77b75bdd51a169554f46180c753b Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 30 Jun 2024 12:32:12 -0300 Subject: [PATCH 068/117] Fixes injection to use the interface dispatcher. This solves errors when calling interface functions in vars derived from injected fields. --- src/FunctionCall.cpp | 30 ++++++++---------------------- src/Program.cpp | 40 ++++------------------------------------ 2 files changed, 12 insertions(+), 58 deletions(-) diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index b2130b9..bd95773 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -97,9 +97,7 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock return NULL; } - if (buildTypes->isInterface(call_dt)) { - valor = Builder->CreateLoad(valor->getType()->getPointerTo(), valor, "defer"); - } else if (buildTypes->isComplex(call_dt)) { + if (buildTypes->isComplex(call_dt)) { //we don't support cohercion between user types yet if (call_dt != def_dt) { Node *utnode = findSymbol(buildTypes->name(call_dt)); @@ -193,30 +191,18 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock // function being called), so we emit location again RobDbgInfo.emitLocation(this); - // when calling an interface function, we generate a larger function name, - // including the type name. This enable binding the correct function implementattion - // at the end of the build, according to the given hardware .spec + // calling an interface function; will use the dispatcher if (stemSymbol && buildTypes->isInterface(stemSymbol->getDataType())) { - string inject_name; + string func_full_name; - if (UserType *ut = dynamic_cast(stemSymbol->getScope())) { - inject_name = stemSymbol->getScope()->getName(); - inject_name.append(":" + stemSymbol->getName() + ":"); - } - else if (buildTypes->isUserType(stemSymbol->getScope()->getDataType())) { - inject_name = buildTypes->name(stemSymbol->getScope()->getDataType()); - inject_name.append(":" + stemSymbol->getName() + ":"); - } - else if (buildTypes->isInterface(stemSymbol->getDataType())) { - inject_name = buildTypes->name(stemSymbol->getDataType()); - inject_name.append(":"); - } + func_full_name = buildTypes->name(stemSymbol->getDataType()); + func_full_name.append(":"); + func_full_name.append(ident.getLastName()); - inject_name.append(ident.getLastName()); - Function *intf_cfunc = mainmodule->getFunction(inject_name); + Function *intf_cfunc = mainmodule->getFunction(func_full_name); if (!intf_cfunc) { intf_cfunc = Function::Create(cfunc->getFunctionType(), Function::ExternalLinkage, - codeAddrSpace, inject_name, mainmodule); + codeAddrSpace, func_full_name, mainmodule); intf_cfunc->setCallingConv(CallingConv::C); intf_cfunc->addFnAttr(Attribute::AlwaysInline); } diff --git a/src/Program.cpp b/src/Program.cpp index 3b302ae..fa9bca2 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -99,6 +99,10 @@ void Program::generateInjectionSetup(SourceLocation *sl) { } } + // setup dispatcher to resolv from destinationTy to bindUserTy + program->getDispatcher()->addDataTypeImplementation(destinationTy, + bindUserTy->getDataType()); + // generate injection stuff const string functionName = ":get_injection_for_" + to.getFullName(); @@ -142,42 +146,6 @@ void Program::generateInjectionSetup(SourceLocation *sl) { } else { // bs_transient assert(false && "TODO: implement bs_transient scope."); } - - // generate injection function aliases - for(const auto & [key, symbol] : bindUserTy->getSymbols()) { - if (FunctionImpl *impl = dynamic_cast(symbol)) { - Identifier destTyIntfName(destinationTyName, loc); - Node *destIntf = destTyIntfName.getSymbol(this); - if (destIntf && destIntf->findMember(symbol->getName())) { - // is a interface member implementation, let add an alias to it - string to_name = regex_replace(to.getFullName(), regex("\\."), ":") + ":" + symbol->getName(); - Function *implFunc = impl->getLLVMFunction(); - - // if the function is declared in this module, FunctionCall already create it - Function *aliasFunc = mainmodule->getFunction(to_name); - if (!aliasFunc) { - aliasFunc = Function::Create(implFunc->getFunctionType(), Function::ExternalLinkage, - codeAddrSpace, to_name, mainmodule); - aliasFunc->setCallingConv(CallingConv::C); - } - aliasFunc->addFnAttr(Attribute::AlwaysInline); - - auto fblock = BasicBlock::Create(global_context, "", aliasFunc); - Builder->SetInsertPoint(fblock); - - vector args; - for(auto& arg : aliasFunc->args()) { - args.push_back(&arg); - } - - Value *call = Builder->CreateCall(implFunc, args); - if (call->getType()->isVoidTy()) - Builder->CreateRetVoid(); - else - Builder->CreateRet(call); - } - } - } } for(auto *finject : finjects) From 53afcd57716eeceebba36d9706778243d373bebf Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 30 Jun 2024 12:40:40 -0300 Subject: [PATCH 069/117] Improved debug info, add & and | operators to matrix update, allow logicexpr in function params, and allow consts in type definition. - Renames :this to _this (vscode and lldb doesn't support : prefix); - Fix debug info for globals vars --- src/DebugInfo.cpp | 8 ++++---- src/FunctionDecl.cpp | 8 ++++---- src/FunctionImpl.cpp | 4 ++-- src/FunctionParams.cpp | 4 ++-- src/Language.y | 13 +++++++++++-- src/Load.cpp | 6 ++++-- src/LoadArray.cpp | 17 +++++++++++------ src/LoadArray.h | 4 ++++ src/PropagateTypes.cpp | 26 +++++++++++++++++++------- src/PropagateTypes.h | 1 + src/Scalar.cpp | 3 +++ src/SymbolizeTree.h | 21 ++++++++++++--------- src/UserType.cpp | 13 +++++++------ src/Variable.cpp | 12 ++++++++---- 14 files changed, 92 insertions(+), 48 deletions(-) diff --git a/src/DebugInfo.cpp b/src/DebugInfo.cpp index 24be3ee..3caea4f 100644 --- a/src/DebugInfo.cpp +++ b/src/DebugInfo.cpp @@ -48,14 +48,14 @@ DIScope* DebugInfo::currScope() { DIExpression *DebugInfo::getFixedOffsetExpression() { // TODO: For some unknown reason (to me), we need to offset // the var declaration by one to see its actual value - /*if (currentTarget().backend == rb_avr) { + if (currentTarget().backend == rb_avr) { SmallVector Ops; DIExpression *ex = DBuilder->createExpression(); ex->appendOffset(Ops, 1); return DIExpression::prependOpcodes(ex, Ops, false); - } else {*/ + } else { return DBuilder->createExpression(); - //} + } } void DebugInfo::declareVar(Node *n, Value *alloc, BasicBlock *allocblock) { @@ -86,7 +86,7 @@ void DebugInfo::declareGlobalVar(Node *n, GlobalVariable *gv, BasicBlock *allocb } auto sp = RobDbgInfo.currScope(); auto funit = RobDbgInfo.currFile(); - auto *d = DBuilder->createGlobalVariableExpression(sp, n->getName(), "", + auto *d = DBuilder->createGlobalVariableExpression(sp, gv->getName(), "", funit, n->getLineNo(), dty, false); gv->addDebugInfo(d); } \ No newline at end of file diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 51fbb41..d33f101 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -6,7 +6,7 @@ void FunctionBase::addThisArgument(DataType dt) { thisArgDt = dt; - Variable *fp = new Variable(":this", dt, this->getLoc()); + Variable *fp = new Variable("_this", dt, this->getLoc()); fp->setScope(this); parameters->append(fp); symbols[fp->getName()] = fp; @@ -38,7 +38,7 @@ bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { void FunctionBase::addParentArgument(DataType dt) { parentArgDt = dt; - Variable *fp = new Variable(":parent", dt, this->getLoc()); + Variable *fp = new Variable("_parent", dt, this->getLoc()); fp->setScope(this); parameters->append(fp); symbols[fp->getName()] = fp; @@ -146,9 +146,9 @@ Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocbloc Arg.addAttr(Attribute::ZExt); const string& argname = fp->getName(); - if (argname == ":this") { + if (argname == "_this") { thisArg = &Arg; - } else if (argname == ":parent") { + } else if (argname == "_parent") { parentArg = &Arg; } diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 2aa7fa4..23aee81 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -87,9 +87,9 @@ bool FunctionImpl::preGenerate() { } Value *variable = Builder->CreateAlloca(talloc, dataAddrSpace, 0, argname); - if (argname == ":this") { + if (argname == "_this") { thisArg = variable; - } else if (argname == ":parent") { + } else if (argname == "_parent") { parentArg = variable; } diff --git a/src/FunctionParams.cpp b/src/FunctionParams.cpp index 189c319..397a0c0 100644 --- a/src/FunctionParams.cpp +++ b/src/FunctionParams.cpp @@ -14,9 +14,9 @@ void FunctionParams::insert(int at, Variable *fp) { unsigned FunctionParams::getNumCodedParams() { unsigned num = 0; for(auto p : parameters) { - // don't count parameters :this, :parent, and other pseudo + // don't count parameters _this, _parent, and other pseudo // parameters like _any_.size, _any_.cols - if (p->getName().find(':') == string::npos && + if (p->getName() != "_this" && p->getName() != "_parent" && p->getName().find('.') == string::npos) num++; } diff --git a/src/Language.y b/src/Language.y index 4e5eeec..654effd 100644 --- a/src/Language.y +++ b/src/Language.y @@ -323,7 +323,16 @@ stmt : ident_or_xident '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Lo | ident_or_xident '&' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '&', $4)); } | ident_or_xident '^' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '^', $4)); } | ident_or_xident '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6, @1);} + | ident_or_xident '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9, @1); } + | ident_or_xident[id] '[' expr[e1] ']' '[' expr[e2] ']' '&' '=' expr[e3] ';' { + Node *bop = new BinaryOp(new LoadMatrix($id, $e1, $e2, @id), '&', $e3); + $$ = new UpdateMatrix($id, $e1, $e2, bop, @1); + } + | ident_or_xident[id] '[' expr[e1] ']' '[' expr[e2] ']' '|' '=' expr[e3] ';' { + Node *bop = new BinaryOp(new LoadMatrix($id, $e1, $e2, @id), '|', $e3); + $$ = new UpdateMatrix($id, $e1, $e2, bop, @1); + } | asminline ';' { $$ = new InlineAssembly($1, @1); } | qualifier simplevar_decl ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } | simplevar_decl ';' @@ -459,12 +468,12 @@ call_or_cast : ident_or_xident[id] '(' paramscall ')' { $$->setLocation(@id); } -paramscall : paramscall ',' expr { +paramscall : paramscall ',' logicexpr { $1->append($3); $$ = $1; } -paramscall : expr { +paramscall : logicexpr { ParamsCall *pc = new ParamsCall(); pc->append($1); $$ = pc; diff --git a/src/Load.cpp b/src/Load.cpp index 4b71fdd..6143f5a 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -99,9 +99,11 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl alloc = symbol->getLLVMValue(func); } - if (!alloc) + if (!alloc) { + assert(alloc && "There's no alloc to load from."); return NULL; // Caused by an error on previous statement that defines the symbol - + } + DataType sdt = symbol->getDataType(); if (buildTypes->isComplex(sdt) || buildTypes->isArrayOrMatrix(sdt)) { if (symbol->isPointerToPointer()) { diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index d7e4ece..b450d79 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -11,9 +11,16 @@ LoadArray::LoadArray(const string &i, Node *pos, location_t loc): BaseArrayOper( DataType LoadArray::getDataType() { if (dt == BuildTypes::undefinedType) { Node *symbol = ident.getSymbol(getScope()); - if (symbol && buildTypes->isArrayOrMatrix(symbol->getDataType())) - dt = buildTypes->getArrayElementType(symbol->getDataType()); - else + if (symbol) { + if (getDimensions() == 1 && !buildTypes->isArray(symbol->getDataType())) { + yyerrorcpp("Symbol " + ident.getFullName() + " is not an array.", this); + setSemanticError(); + } else if (getDimensions() == 2 && !buildTypes->isMatrix(symbol->getDataType())) { + yyerrorcpp("Symbol " + ident.getFullName() + " is not a matrix.", this); + setSemanticError(); + } else + dt = buildTypes->getArrayElementType(symbol->getDataType()); + } else setSemanticError(); } return dt; @@ -25,10 +32,8 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al if (!symbol) return NULL; - if (!buildTypes->isArrayOrMatrix(symbol->getDataType())) { - yyerrorcpp("Variable " + ident.getFullName() + " is not an array or matrix.", this); + if (!buildTypes->isArrayOrMatrix(symbol->getDataType())) return NULL; - } RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); diff --git a/src/LoadArray.h b/src/LoadArray.h index d7d4cf7..d234990 100644 --- a/src/LoadArray.h +++ b/src/LoadArray.h @@ -26,6 +26,10 @@ class BaseArrayOper: public Node { const string getIdent() { return ident.getFullName(); } + + const int getDimensions() { + return children().size(); + } }; class LoadArray: public BaseArrayOper { diff --git a/src/PropagateTypes.cpp b/src/PropagateTypes.cpp index aeb9966..e58f08e 100644 --- a/src/PropagateTypes.cpp +++ b/src/PropagateTypes.cpp @@ -164,11 +164,14 @@ DataType PropagateTypes::coerceArithOrCmp(Node &n, Node *lNode, Node *rNode) { } } else { - yywarncpp("The unsigned operand was converted to signed.", &n); - if (lUnsigned) + if (lUnsigned) { + yywarncpp("The left operand was converted to signed.", lNode); lTy = buildTypes->unsignedToSigned(lTy); - else + } + else { + yywarncpp("The right operand was converted to signed.", rNode); rTy = buildTypes->unsignedToSigned(rTy); + } } } @@ -388,6 +391,15 @@ Node* PropagateTypes::visit(UpdateArray& n) { } Node* PropagateTypes::visit(UserType& n) { + // Visit variables first, to propagate their types + for (auto it = n.node_children.begin(); it != n.node_children.end(); ++it) { + if (Variable *v = dynamic_cast(*it)) { + Node *replace = (*it)->accept(*this); + if (replace) { + *it = replace; + } + } + } n.dt = n.getDataType(); propagateChildren(n); return NULL; @@ -457,7 +469,7 @@ Node* PropagateTypes::visit(Scalar& n) { Node *result = visit((Variable&)n); // although this should be done on SymbolizeTree, - // some type propagarion in the tree change symbols + // some type propagation in the tree changes symbols // for scalars (e.g. FunctionCall -> ConstructorCall) auto& exprSymbols = n.getExpr()->getSymbols(); if (exprSymbols.size() > 0) @@ -468,11 +480,11 @@ Node* PropagateTypes::visit(Scalar& n) { Node* PropagateTypes::visit(Load& n) { // skip the :parent field. For nested user types, // the parameter doesn't exists at this point - if (n.getName() == ":parent") + if (n.getName() == "_parent") return NULL; // although this should be done on SymbolizeTree, - // some type propagarion in the tree change symbols + // some type propagation in the tree changes symbols // for scalars (e.g. FunctionCall -> ConstructorCall) visit((Node&)n); Node *identSymbol = n.getIdentSymbol(false); @@ -483,7 +495,7 @@ Node* PropagateTypes::visit(Load& n) { Node* PropagateTypes::visit(MemCopy& n) { // although this should be done on SymbolizeTree, - // some type propagarion in the tree change symbols + // some type propagation in the tree changes symbols // for scalars (e.g. FunctionCall -> ConstructorCall) visit((Node&)n); if (n.children().size() > 0) diff --git a/src/PropagateTypes.h b/src/PropagateTypes.h index 7ab61b7..810ca14 100644 --- a/src/PropagateTypes.h +++ b/src/PropagateTypes.h @@ -64,6 +64,7 @@ class ZExtInt: public CoercionBase { virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { Value *v = node->generate(func, block, allocblock); + assert(v && "Node must generate a value to ZExt."); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); return Builder->CreateZExt(v, buildTypes->llvmType(dt), "zext"); diff --git a/src/Scalar.cpp b/src/Scalar.cpp index bfd87a4..b4da911 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -56,6 +56,9 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc return NULL; DataType exprv_dt = expr->getDataType(); + if (hasQualifier(qconst)) + return exprv; + Builder->SetInsertPoint(block); if (!alloc) alloc = symbol->getLLVMValue(func); diff --git a/src/SymbolizeTree.h b/src/SymbolizeTree.h index 883f5f2..ade24c7 100644 --- a/src/SymbolizeTree.h +++ b/src/SymbolizeTree.h @@ -6,12 +6,9 @@ #include "UserType.h" #include "Matrix.h" #include "Array.h" +#include "UpdateArray.h" #include "FunctionImpl.h" #include "Scalar.h" -#include "Load.h" -#include "FunctionCall.h" -#include "ConstructorCall.h" -#include "MemCopy.h" #include "Enum.h" class SymbolizeTree: public Visitor { @@ -22,7 +19,6 @@ class SymbolizeTree: public Visitor { for(auto* c : n.children()) { c->setScope(&n); if (c->hasName()) { - //fprintf(stderr, "%s\n", c->getName().c_str()); n.addSymbol(dynamic_cast(c)); } } @@ -60,10 +56,17 @@ class SymbolizeTree: public Visitor { return NULL; } - virtual Node* visit(FunctionCall& n) override { - for(Node *p: n.getParameters()) { - p->setScope(&n); - p->accept(*this); + virtual Node* visit(UpdateArray& n) override { + for(auto* c : n.children()) { + c->accept(*this); + } + // for operation assignment (eg. +=, -=, etc.), the indexes + // are used twice, in the load and in the attribution. + // so we check if they already has a scope before setting + for(auto* c : n.children()) { + if (!c->getScope()) { + c->setScope(&n); + } } return NULL; } diff --git a/src/UserType.cpp b/src/UserType.cpp index 9b60b05..3171f1c 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -16,12 +16,13 @@ #include "Int8.h" #include "Scalar.h" #include "Program.h" +#include "PropagateTypes.h" class ParentScalar: public Scalar { public: ParentScalar(DataType parentDt, location_t loc) : Scalar(Identifier("parent", loc), NULL) { - Load *load = new Load(":parent", loc); + Load *load = new Load("_parent", loc); load->setDataType(parentDt); load->setScope(this); setExpr(load); @@ -96,11 +97,10 @@ bool UserType::createDataType() { v = dynamic_cast(child); } - if (v) { - DataType vdt = v->getDataType(); - if (vdt == BuildTypes::undefinedType) { + if (v && !v->isConstExpr()) { + if (PropagateTypes::isUndefined(v)) { return false; - } else if (buildTypes->isInterface(vdt)) { + } else if (buildTypes->isInterface(v->getDataType())) { v->setPointer(pm_pointer); v->setPointerToPointer(true); } else if (v->getPointerMode() == pm_unknown) @@ -162,7 +162,8 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all vector fields; for(auto & [key, stmt] : getSymbols()) { if (Variable *c = dynamic_cast(stmt)) { - fields.push_back(c); + if (!c->isConstExpr()) + fields.push_back(c); } } diff --git a/src/Variable.cpp b/src/Variable.cpp index 9cc1c20..89157f5 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -11,17 +11,17 @@ Value *Variable::getLLVMValue(Node *stem) { FunctionImpl *func = dynamic_cast(stem); if (func && func->getThisArg()) { - // generating a function of a type: get the gep on :this or :parent parameters + // generating a function of a type: get the gep on _this or :parent parameters DataType thisDt = func->getThisArgDt(); Type *thisTy = buildTypes->llvmType(thisDt); Value *thisptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); if (!stem->getScope() || this->getScope() == stem->getScope()) { // the var is being accessed in global scope (!stem->getScope()) or - // in a method of the type itself. Thus, we :this and gep the field + // in a method of the type itself. Thus, we _this and gep the field alloc = Builder->CreateStructGEP(thisTy, thisptr, gepidx, "gepthis"); } else { - // this var is in the parent scope. :this is an nested type. - // Thus, we access :parent in :this and gep the field + // this var is in the parent scope. _this is an nested type. + // Thus, we access parent in _this and gep the field DataType parentDt = this->getScope()->getDataType(); Type *parentTy = buildTypes->llvmType(parentDt); int idxParentInThis = static_cast(symbols["parent"])->getGEPIndex(); @@ -39,5 +39,9 @@ Value *Variable::getLLVMValue(Node *stem) { alloc = Builder->CreateStructGEP(udt, ptr, gepidx, "gepu"); // FIXME } } + + if (!alloc && isConstExpr()) + return generate(NULL, NULL, NULL); + return alloc; } From fa4be3e42814d7272cbae1540c49d941877a758e Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 30 Jun 2024 12:45:54 -0300 Subject: [PATCH 070/117] Add two test cases that we should support. Still failing. --- test/general/bool.rob | 9 +++++++++ test/general/scalar-in-two-contexts.rob | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 test/general/scalar-in-two-contexts.rob diff --git a/test/general/bool.rob b/test/general/bool.rob index 92c27f0..46b126e 100644 --- a/test/general/bool.rob +++ b/test/general/bool.rob @@ -1,4 +1,7 @@ +void func(bool x) { +} + int16 main() { a = 1 > 7; b = 2 <= 3; @@ -8,6 +11,12 @@ int16 main() { f = a and c; g = a or b and c; + h = {true:2}; + x = !h[0]; + func(x); + func(!h[0]); + h[0] = !h[0]; + if !(2+1 == 3) or !(2+2 == 4) or d { return 1; } diff --git a/test/general/scalar-in-two-contexts.rob b/test/general/scalar-in-two-contexts.rob new file mode 100644 index 0000000..b61d538 --- /dev/null +++ b/test/general/scalar-in-two-contexts.rob @@ -0,0 +1,17 @@ + +int8 main() { + block = {true:2}; + i = 2; + while (i > 0) { + row = i; + block[row] = false; + } + + row = 0; + while row < block.size { + block[row] = true; + } + + return 0; +} + From f1e053e5c4ec176fe8b985597bc3c83abaa6517c Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 30 Jun 2024 21:54:32 -0300 Subject: [PATCH 071/117] Implements boolean short-circuit evaluation. --- src/BinaryOp.cpp | 31 ++++++++++++++++++++++++++----- src/If.cpp | 6 ++++-- src/Return.cpp | 2 ++ src/While.cpp | 8 +++++--- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index 543a20a..2326a60 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -2,6 +2,7 @@ #include "Language_gen_y.hpp" #include "BinaryOp.h" +#include "FunctionImpl.h" BinaryOp::BinaryOp(Node *l, int op, Node *r) : Node(l->getLoc()) { this->op = op; @@ -11,20 +12,40 @@ BinaryOp::BinaryOp(Node *l, int op, Node *r) : Node(l->getLoc()) { Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + + // The code below implements boolean short-circuit evaluation + // See https://en.wikipedia.org/wiki/Short-circuit_evaluation + // left Value *lhs = lhsn()->generate(func, block, allocblock); - Value *rhs = rhsn()->generate(func, block, allocblock); - + BasicBlock *newlblock = dyn_cast(lhs)->getParent(); Type *lhsty = lhs->getType(); - Type *rhsty = rhs->getType(); + BasicBlock *fullev = BasicBlock::Create(global_context, "fullev", func->getLLVMFunction()); + BasicBlock *phiblock = BasicBlock::Create(global_context, "phiblock", func->getLLVMFunction()); + PHINode *phi = PHINode::Create(lhsty, 0, "phi", phiblock); + phi->addIncoming(lhs, newlblock); + + if (op == Instruction::BinaryOps::Or) + BranchInst::Create(phiblock, fullev, lhs, newlblock); + else // and + BranchInst::Create(fullev, phiblock, lhs, newlblock); + + // right + Value *rhs = rhsn()->generate(func, fullev, allocblock); + BasicBlock *newrblock = dyn_cast(rhs)->getParent(); + Builder->SetInsertPoint(newrblock); + Value *binop = Builder->CreateBinOp(op, lhs, rhs, "logicop"); + BranchInst::Create(phiblock, newrblock); + phi->addIncoming(binop, newrblock); + if (!lhsty->isIntegerTy() || !(lhsty->getIntegerBitWidth() == 1)) yyerrorcpp("The left side of the logical expression is not boolean.", this); + Type *rhsty = rhs->getType(); if (!rhsty->isIntegerTy() || !(rhsty->getIntegerBitWidth() == 1)) yyerrorcpp("The right side of the logical expression is not boolean.", this); - Builder->SetInsertPoint(block); - return Builder->CreateBinOp(op, lhs, rhs, "logicop"); + return phi; } Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, diff --git a/src/If.cpp b/src/If.cpp index 5cb943f..da9f01d 100644 --- a/src/If.cpp +++ b/src/If.cpp @@ -16,8 +16,9 @@ If::If(Node *e, vector &&tst, vector &&est, location_t loc): If(e, } Value *If::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - Value *exprv = expr->generate(func, block, allocblock); + Value *exprv = expr->generate(func, block, allocblock); + BasicBlock *thenb = BasicBlock::Create(global_context, "if_then", func->getLLVMFunction(), 0); Value *thennewb = thenst->generateChildren(func, thenb, allocblock); @@ -29,7 +30,8 @@ Value *If::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbloc elsenewb = elsest->generateChildren(func, elseb, allocblock); } - BranchInst::Create(thenb, elseb, exprv, block); + BasicBlock *newblock = dyn_cast(exprv)->getParent(); + BranchInst::Create(thenb, elseb, exprv, newblock); BasicBlock *mergb = BasicBlock::Create(global_context, "if_cont", func->getLLVMFunction(), 0); diff --git a/src/Return.cpp b/src/Return.cpp index 0725370..52cf2a7 100644 --- a/src/Return.cpp +++ b/src/Return.cpp @@ -6,6 +6,8 @@ Value *Return::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Value *retvalue = NULL; if (value()) { retvalue = value()->generate(func, block, allocblock); + if (Instruction *ins = dyn_cast(retvalue)) + block = ins->getParent(); } RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); diff --git a/src/While.cpp b/src/While.cpp index 2349658..ef1084e 100644 --- a/src/While.cpp +++ b/src/While.cpp @@ -15,8 +15,6 @@ While::While(Node *e, vector &&ss, location_t loc) : While(e, loc) { Value *While::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { Function *llvmf = func->getLLVMFunction(); BasicBlock *condwhile = BasicBlock::Create(global_context, "while_cond", llvmf, 0); - BasicBlock *bodywhile = BasicBlock::Create(global_context, "while_body", llvmf, 0); - BasicBlock *endwhile = BasicBlock::Create(global_context, "while_end", llvmf, 0); // go to condition RobDbgInfo.emitLocation(expr); @@ -24,10 +22,14 @@ Value *While::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb Builder->CreateBr(condwhile); Value *exprv = expr->generate(func, condwhile, allocblock); + BasicBlock *endcondwhile = dyn_cast(exprv)->getParent(); // check condition RobDbgInfo.emitLocation(expr); - Builder->SetInsertPoint(condwhile); + Builder->SetInsertPoint(endcondwhile); + + BasicBlock *bodywhile = BasicBlock::Create(global_context, "while_body", llvmf, 0); + BasicBlock *endwhile = BasicBlock::Create(global_context, "while_end", llvmf, 0); Builder->CreateCondBr(exprv, bodywhile, endwhile); // alloc instructions inside bodywhile should go to allocblock to prevent repeatedly allocation From 771ff4045771b3c211f5b22efd1d8292792fe6e9 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 30 Jun 2024 21:58:02 -0300 Subject: [PATCH 072/117] Enables accessing fields of a nested type in the parent; minor fixes. --- src/BuildTypes.cpp | 2 +- src/FunctionDecl.h | 2 +- src/FunctionImpl.cpp | 2 +- src/FunctionImpl.h | 2 +- src/Load.cpp | 2 +- src/NamedConst.h | 2 +- src/Node.h | 2 +- src/PropagateTypes.cpp | 5 ++--- src/PropagateTypes.h | 6 ++++-- src/UserType.cpp | 2 +- src/Variable.cpp | 4 ++-- src/Variable.h | 2 +- 12 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 7ae8e2e..912da72 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -30,7 +30,7 @@ BuildTypes::BuildTypes(DataType targetPointerType) : tinfo[tint6u] = {"uint6", 6, Type::getIntNTy(global_context, 6), dwarf::DW_ATE_unsigned}; tinfo[tint7u] = {"uint7", 7, Type::getIntNTy(global_context, 7), dwarf::DW_ATE_unsigned}; tinfo[tint8u] = {"uint8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; - tinfo[tint9u] = {"uint9", 8, Type::getIntNTy(global_context, 9), dwarf::DW_ATE_unsigned}; + tinfo[tint9u] = {"uint9", 9, Type::getIntNTy(global_context, 9), dwarf::DW_ATE_unsigned}; tinfo[tint12u] = {"uint12", 12, Type::getIntNTy(global_context, 12),dwarf::DW_ATE_unsigned}; tinfo[tint16u] = {"uint16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tint32u] = {"uint32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 8a73f9b..53f917b 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -52,7 +52,7 @@ class FunctionBase: public NamedNode { return *parameters; } - virtual Value *getLLVMValue(Node *) override { + virtual Value *getLLVMValue(Node *, FunctionImpl *) override { return func; } diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 23aee81..ed926ae 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -212,7 +212,7 @@ Node* FunctionImpl::accept(Visitor& v) { return v.visit(*this); } -Value* FunctionImpl::getLLVMValue(Node *) { +Value* FunctionImpl::getLLVMValue(Node *, FunctionImpl *) { if (!preGenerated) preGenerate(); return func; diff --git a/src/FunctionImpl.h b/src/FunctionImpl.h index 2eb434f..79bddc3 100644 --- a/src/FunctionImpl.h +++ b/src/FunctionImpl.h @@ -29,7 +29,7 @@ class FunctionImpl: public FunctionBase { virtual Node* accept(Visitor& v) override; - virtual Value *getLLVMValue(Node *) override; + virtual Value *getLLVMValue(Node *, FunctionImpl *) override; virtual Function *getLLVMFunction() override { if (!preGenerated) diff --git a/src/Load.cpp b/src/Load.cpp index 6143f5a..620335f 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -79,7 +79,7 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl v = Builder->CreateLShr(v, ConstantInt::get(req_eq_ty, bs)); return Builder->CreateTrunc(v, buildTypes->llvmType(symbol->getDataType())); } else { - alloc = symbol->getLLVMValue(stem); + alloc = symbol->getLLVMValue(stem, func); } if (stem->hasQualifier(qvolatile)) diff --git a/src/NamedConst.h b/src/NamedConst.h index 8f6e566..17b6b21 100644 --- a/src/NamedConst.h +++ b/src/NamedConst.h @@ -18,7 +18,7 @@ class NamedConst: public NamedNode { return value->generate(NULL, NULL, NULL); } - virtual Value *getLLVMValue(Node *stem) override { + virtual Value *getLLVMValue(Node *stem, FunctionImpl *gfunc = NULL) override { return value->generate(NULL, NULL, NULL); } diff --git a/src/Node.h b/src/Node.h index 599f302..8aff1eb 100644 --- a/src/Node.h +++ b/src/Node.h @@ -80,7 +80,7 @@ class Node : public SourceLocation { return qualifiers.count(dq) == 1; } - virtual Value* getLLVMValue(Node *stem) { + virtual Value* getLLVMValue(Node *stem, FunctionImpl *gfunc = NULL) { return NULL; } diff --git a/src/PropagateTypes.cpp b/src/PropagateTypes.cpp index e58f08e..a561d1b 100644 --- a/src/PropagateTypes.cpp +++ b/src/PropagateTypes.cpp @@ -456,9 +456,8 @@ Node* PropagateTypes::visit(Variable& n) { if (checkCoercion) { Node *result = NULL; result = coerceTo(expr, destDt); - n.setExpr(result); - if (!result) - yywarncpp(string_format("The symbol %s was first defined here.", n.getName().c_str()), firstDecl); + if (result) + n.setExpr(result); } return NULL; diff --git a/src/PropagateTypes.h b/src/PropagateTypes.h index 810ca14..c2efa3f 100644 --- a/src/PropagateTypes.h +++ b/src/PropagateTypes.h @@ -171,8 +171,10 @@ class PropagateTypes: public Visitor { return n.node_children[i]; } - static bool isUndefined(Node *n) { - if (n->getDataType() == BuildTypes::undefinedType) { + static bool isUndefined(Node *n, bool checkDefined = true) { + DataType dt = n->getDataType(); + if (dt == BuildTypes::undefinedType || + checkDefined && !buildTypes->isDefined(dt)) { string name = n->getName(); if (name != "") yyerrorcpp(string_format("The type of %s is undefined.", name.c_str()), n); diff --git a/src/UserType.cpp b/src/UserType.cpp index 3171f1c..a20fd0c 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -98,7 +98,7 @@ bool UserType::createDataType() { } if (v && !v->isConstExpr()) { - if (PropagateTypes::isUndefined(v)) { + if (PropagateTypes::isUndefined(v, false)) { return false; } else if (buildTypes->isInterface(v->getDataType())) { v->setPointer(pm_pointer); diff --git a/src/Variable.cpp b/src/Variable.cpp index 89157f5..96ecb17 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -2,7 +2,7 @@ #include "Variable.h" #include "FunctionImpl.h" -Value *Variable::getLLVMValue(Node *stem) { +Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { int gepidx = getGEPIndex(); if (gepidx != -1) { Value *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); @@ -32,7 +32,7 @@ Value *Variable::getLLVMValue(Node *stem) { } else { // accessing a var of a user type: get the gep in the scope (user type) of the scalar Type *udt = buildTypes->llvmType(stem->getDataType()); - Value *ptr = stem->getLLVMValue(NULL); + Value *ptr = stem->getLLVMValue(gfunc); if (stem->isPointerToPointer()) { ptr = Builder->CreateLoad(udt->getPointerTo(), ptr, "deref"); } diff --git a/src/Variable.h b/src/Variable.h index 8d725b9..06fee4b 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -20,7 +20,7 @@ class Variable: public NamedNode { this->dt = dt; } - virtual Value* getLLVMValue(Node *stem) override; + virtual Value* getLLVMValue(Node *stem, FunctionImpl *gfunc = NULL) override; virtual void setGEPIndex(int idx) { gepIndex = idx; From 8454aa7a95232f508f9d2cdafd94fb1767a4e867 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Mon, 1 Jul 2024 18:05:22 -0300 Subject: [PATCH 073/117] Improves the std lib for the breakout game (sending to ssd1306 only the bytes contained in the envelope of changed pixels). --- lib/display/ssd1306.rob | 39 ++++++++++++++++++---------- lib/graphic/canvas8.rob | 31 ++++++++++++++++++++++ lib/graphic/envelope.rob | 40 +++++++++++++++++++++++++++++ lib/math/abs.rob | 18 +++++++++++++ platformio/platform/builder/main.py | 9 +++++-- 5 files changed, 121 insertions(+), 16 deletions(-) create mode 100644 lib/graphic/envelope.rob create mode 100644 lib/math/abs.rob diff --git a/lib/display/ssd1306.rob b/lib/display/ssd1306.rob index 7af4925..112f72c 100644 --- a/lib/display/ssd1306.rob +++ b/lib/display/ssd1306.rob @@ -9,6 +9,8 @@ use intfs.databus; use intfs.buffer8; use intfs.display; +use graphic.envelope; + type ssd1306 implements display { mmcu = mcu(); @@ -25,6 +27,7 @@ type ssd1306 implements display { framebuffer implements buffer8 { buff = {{0u:128}:8}; + changes = envelope_u16(); uint16 height() inline { return buff.rows; } uint16 width() inline { return buff.cols; } @@ -47,6 +50,7 @@ type ssd1306 implements display { void set(uint16 row, uint16 col, uint8 v) inline { buff[row][col] = v; + changes.expand(col, row); } } @@ -166,11 +170,13 @@ type ssd1306 implements display { } void reset_display() { - reset.set(true); - mmcu.wait_ms(10); - reset.set(false); - mmcu.wait_ms(10); - reset.set(true); + if (dbus.get_protocol() == databus_protocol.SPI) { + reset.set(true); + mmcu.wait_ms(10); + reset.set(false); + mmcu.wait_ms(10); + reset.set(true); + } } void write_commands(int8[] cmds) { @@ -188,18 +194,18 @@ type ssd1306 implements display { select.set(true); } - void reset_cursor() { + void reset_cursor(uint8 lx, uint8 ly, uint8 ux, uint8 uy) { cmds = { // set page update range - commands.SET_PAGE_ADDR, 0x0, 0x7, + commands.SET_PAGE_ADDR, ly, uy, // set column update range - commands.SET_COLUMN_ADDRESS, 0x0, 127 + commands.SET_COLUMN_ADDRESS, lx, ux }; write_commands(cmds); } void clear() { - reset_cursor(); + reset_cursor(0, 0, columns()-1, rows()-1); datacmd.set(true); select.set(false); @@ -221,7 +227,11 @@ type ssd1306 implements display { } void update_frame() { - reset_cursor(); + ev = framebuffer.changes; + if ev.empty() { + return; + } + reset_cursor(ev.lx, ev.ly, ev.ux, ev.uy); datacmd.set(true); select.set(false); @@ -230,10 +240,10 @@ type ssd1306 implements display { dbus.write(i2c_control.DATA_STREAM); } - row = 0u; - while row < framebuffer.height() { - col = 0u; - while col < framebuffer.width() { + row = ev.ly; + while row <= ev.uy { + col = ev.lx; + while col <= ev.ux { v = framebuffer.get(row, col); dbus.write(v); col++; @@ -243,5 +253,6 @@ type ssd1306 implements display { dbus.end_transaction(); select.set(true); + ev.clear(); } } diff --git a/lib/graphic/canvas8.rob b/lib/graphic/canvas8.rob index fc777f1..c641db2 100644 --- a/lib/graphic/canvas8.rob +++ b/lib/graphic/canvas8.rob @@ -35,4 +35,35 @@ type canvas8 { buffer.set(rowb, col, v & ~(1 << uint8(row & 7))); } } + + void fill_rect(uint16 x1, uint16 y1, uint16 x2, uint16 y2, bool v) { + if x1 >= width() { return; } + if y1 >= height() { return; } + if x2 >= width() { x2 = width()-1; } + if y2 >= height() { y2 = height()-1; } + first_bank = y1 >> 3; + last_bank = y2 >> 3; + bank = first_bank; + while bank <= last_bank { + mask = 0xFF; + if first_bank == last_bank { // all bits in the same bank + mask = (mask >> ((y1 & 7) + 7 - (y2 & 7))) << (y1 & 7); + } else if bank == first_bank { + mask = (mask << (y1 & 7)); + } else if bank == last_bank { + mask = (mask >> (7 - (y2 & 7))); + } + b = x1; + while b <= x2 { + bv = buffer.get(bank, b); + bv &= ~mask; + if v { + bv |= mask; + } + buffer.set(bank, b, bv); + b++; + } + bank++; + } + } } diff --git a/lib/graphic/envelope.rob b/lib/graphic/envelope.rob new file mode 100644 index 0000000..a505914 --- /dev/null +++ b/lib/graphic/envelope.rob @@ -0,0 +1,40 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +use math.limits; + +type envelope_u16 { + + lx = uint16_max; + ly = uint16_max; + ux = uint16(0); + uy = uint16(0); + + void set(uint16 lxx, uint16 lyy, uint16 uxx, uint16 uyy) { + lx = lxx; + ly = lyy; + ux = uxx; + uy = uyy; + } + + bool empty() { + return ux < lx or uy < ly; + } + + void clear() { + lx = uint16_max; + ly = uint16_max; + ux = uint16(0); + uy = uint16(0); + } + + void expand(uint16 x, uint16 y) { + if lx > x { lx = x; } + if ux < x { ux = x; } + if ly > y { ly = y; } + if uy < y { uy = y; } + } + +} diff --git a/lib/math/abs.rob b/lib/math/abs.rob new file mode 100644 index 0000000..63f4cdc --- /dev/null +++ b/lib/math/abs.rob @@ -0,0 +1,18 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* Abs functions without branch */ + +int8 abs8(int8 value) inline { + mask = value >> 7; + value = (value ^ mask) - mask; + return value; +} + +int16 abs16(int16 value) inline { + mask = value >> 15; + value = (value ^ mask) - mask; + return value; +} diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 14c7c4c..cde47b4 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -40,7 +40,8 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 hardware_spec = None pass -ldflags = ["-nostdlib", "-entry=main", "-L", stdlib_folder, "-Bstatic"] +#ldflags = ["-nostdlib", "-entry=main", "-L", stdlib_folder, "-Bstatic"] +ldflags = ["-nostdlib", "-L", stdlib_folder, "-Bstatic"] if mcu.startswith("stm32f1"): ldflags.append("-Tstm32f1.ld") auxsources += Glob(join(stdlib_folder, "stm32f1.rob")) @@ -62,6 +63,7 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 robcmp_args.append("-g") robcmp_args.append("-O0") elif build_type == "release": + #robcmp_args.append("-g") robcmp_args.append("-Oz") hardware_spec_args = [] @@ -109,7 +111,10 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 target_objs = [] for f in sources: - target_objs += env.RobDep(join("$BUILD_DIR", f.name + ".o"), f) + robdep = env.RobDep(join("$BUILD_DIR", f.name + ".o"), f) + # Always building while not proper detect dependencies changes (use inside .rob) + AlwaysBuild(robdep) + target_objs += robdep for f in auxsources: target_objs += env.Rob(join("$BUILD_DIR", f.name + ".o"), f) From 78f9e2778c9c26b705fa8aa524d6911858d05b5c Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 6 Jul 2024 14:27:24 -0300 Subject: [PATCH 074/117] Fixes short-circuit boolean evaluation for constants. --- src/If.cpp | 13 +++++++++++-- src/While.cpp | 6 +++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/If.cpp b/src/If.cpp index da9f01d..3f6101b 100644 --- a/src/If.cpp +++ b/src/If.cpp @@ -18,6 +18,11 @@ If::If(Node *e, vector &&tst, vector &&est, location_t loc): If(e, Value *If::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { Value *exprv = expr->generate(func, block, allocblock); + if (!exprv) { + // This occurs when loading a var still not defined, so + // we let it be False to recovery from the error + exprv = ConstantInt::get(Type::getInt1Ty(global_context), 0); + } BasicBlock *thenb = BasicBlock::Create(global_context, "if_then", func->getLLVMFunction(), 0); @@ -29,8 +34,12 @@ Value *If::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbloc if (elsest != 0) { elsenewb = elsest->generateChildren(func, elseb, allocblock); } - - BasicBlock *newblock = dyn_cast(exprv)->getParent(); + + BasicBlock *newblock = block; + // A distinct block can return from boolean short-circuit evaluation + Instruction* instr = dyn_cast(exprv); + if (instr) + newblock = instr->getParent(); BranchInst::Create(thenb, elseb, exprv, newblock); BasicBlock *mergb = BasicBlock::Create(global_context, "if_cont", diff --git a/src/While.cpp b/src/While.cpp index ef1084e..c8182b7 100644 --- a/src/While.cpp +++ b/src/While.cpp @@ -22,7 +22,11 @@ Value *While::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb Builder->CreateBr(condwhile); Value *exprv = expr->generate(func, condwhile, allocblock); - BasicBlock *endcondwhile = dyn_cast(exprv)->getParent(); + BasicBlock *endcondwhile = condwhile; + // A distinct block can return from boolean short-circuit evaluation + Instruction* instr = dyn_cast(exprv); + if (instr) + endcondwhile = instr->getParent(); // check condition RobDbgInfo.emitLocation(expr); From 39f55a6c1453cc454d30461bee52afd9e775e8ff Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 6 Jul 2024 14:31:43 -0300 Subject: [PATCH 075/117] Add signal attribute to functions. This is part of interruptions handling. --- src/FunctionAttributes.h | 18 +++++++++--------- src/FunctionDecl.cpp | 12 +++++++----- src/Language.l | 1 + src/Language.y | 1 + src/LanguageHeader.y | 2 +- src/LanguageUse.y | 1 + 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/FunctionAttributes.h b/src/FunctionAttributes.h index eee7197..f3df96a 100644 --- a/src/FunctionAttributes.h +++ b/src/FunctionAttributes.h @@ -1,29 +1,29 @@ #pragma once -enum FunctionAttributeType {fa_weak, fa_inline, fa_noinline, fa_section, fa_naked}; +enum FunctionAttributeType {fa_weak, fa_inline, fa_noinline, fa_section, fa_naked, fa_signal}; typedef pair FunctionAttribute; class FunctionAttributes { protected: - vector attributes; + map attributes; public: FunctionAttributes() {} FunctionAttributes(FunctionAttributeType attr, const string& value = "") { addAttribute(attr, value); } - ~FunctionAttributes() { - for(auto *attr : attributes) - delete attr; - } void addAttribute(FunctionAttributeType attr, const string& value = "") { - attributes.push_back(new FunctionAttribute(attr, value)); + attributes[attr] = value; } void addAttribute(FunctionAttribute *attr) { - attributes.push_back(attr); + attributes[attr->first] = attr->second; + delete attr; } - const vector& getAttributes() { + const map& getAttributes() { return attributes; } + bool hasAttribute(FunctionAttributeType attr) { + return attributes.find(attr) != attributes.end(); + } }; diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index d33f101..8e486b2 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -89,10 +89,10 @@ void FunctionBase::addFunctionAttributes(Function *func) { if (!attributes) return; - for(auto *attr : attributes->getAttributes()) { - switch (attr->first) { + for(auto &[attr, value] : attributes->getAttributes()) { + switch (attr) { case fa_weak: - func->setLinkage(GlobalValue::WeakAnyLinkage); + func->setLinkage(GlobalValue::ExternalWeakLinkage); break; case fa_inline: func->addFnAttr(Attribute::AlwaysInline); @@ -101,12 +101,14 @@ void FunctionBase::addFunctionAttributes(Function *func) { func->addFnAttr(Attribute::NoInline); break; case fa_section: - func->setSection(attr->second); + func->setSection(value); + break; + case fa_signal: + func->addFnAttr("signal"); //no break, share naked attrs break; case fa_naked: func->addFnAttr(Attribute::Naked); func->addFnAttr(Attribute::NoInline); - func->addFnAttr(Attribute::OptimizeNone); break; } } diff --git a/src/Language.l b/src/Language.l index 67848e4..b3b132f 100644 --- a/src/Language.l +++ b/src/Language.l @@ -49,6 +49,7 @@ EXP ([Ee][-+]?[0-9]+)? "weak" { return TOK_WEAK; } "section" { return TOK_SECTION; } "naked" { return TOK_NAKED; } +"signal" { return TOK_SIGNAL; } "bind" { return TOK_BIND; } "to" { return TOK_TO; } diff --git a/src/Language.y b/src/Language.y index 654effd..96f5fdb 100644 --- a/src/Language.y +++ b/src/Language.y @@ -149,6 +149,7 @@ function_attribute | TOK_INLINE { $$ = new FunctionAttribute(fa_inline, ""); } | TOK_NOINLINE { $$ = new FunctionAttribute(fa_noinline, ""); } | TOK_NAKED { $$ = new FunctionAttribute(fa_naked, ""); } + | TOK_SIGNAL { $$ = new FunctionAttribute(fa_signal, ""); } | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } event : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index 6b3fd3b..778d151 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -35,7 +35,7 @@ %token TOK_QUANDO TOK_ESTA %token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT -%token TOK_INLINE TOK_NOINLINE TOK_WEAK TOK_SECTION TOK_NAKED +%token TOK_INLINE TOK_NOINLINE TOK_WEAK TOK_SECTION TOK_NAKED TOK_SIGNAL %union { char *ident; diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 80cba72..8a3d35b 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -157,6 +157,7 @@ function_attribute | TOK_INLINE { $$ = new FunctionAttribute(fa_inline, ""); } | TOK_NOINLINE { $$ = new FunctionAttribute(fa_noinline, ""); } | TOK_NAKED { $$ = new FunctionAttribute(fa_naked, ""); } + | TOK_SIGNAL { $$ = new FunctionAttribute(fa_signal, ""); } | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } qualifier : TOK_CONST { $$ = qconst; } From cec8b786164f1438a360ef141c2d46945b7574d9 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 7 Jul 2024 17:16:57 -0300 Subject: [PATCH 076/117] Simplifies NamedConst creation by removing redundant location. --- src/Array.cpp | 2 +- src/Language.y | 6 +++--- src/LanguageUse.y | 6 +++--- src/Matrix.cpp | 4 ++-- src/NamedConst.h | 4 ++-- src/StringConst.cpp | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Array.cpp b/src/Array.cpp index 1be8341..699d261 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -8,7 +8,7 @@ #include "PropagateTypes.h" Array::Array(const string& n, ArrayElements *aes, location_t loc) : Variable(n, loc), elements(aes) { - NamedConst *nc = new NamedConst("size", getNodeForUIntConst(aes->getArraySize(), loc), loc); + NamedConst *nc = new NamedConst("size", getNodeForUIntConst(aes->getArraySize(), loc)); addChild(nc); addSymbol(nc); } diff --git a/src/Language.y b/src/Language.y index 96f5fdb..4fe2af4 100644 --- a/src/Language.y +++ b/src/Language.y @@ -100,15 +100,15 @@ enum_items : enum_item { } enum_item : TOK_IDENTIFIER[id] '=' TOK_INTEGER[intg] { - $$ = new NamedConst($id, new Int8($intg, @intg), @id); + $$ = new NamedConst($id, new Int8($intg, @id)); } enum_item : TOK_IDENTIFIER[id] '=' '-' TOK_INTEGER[intg] { - $$ = new NamedConst($id, new Int8($intg * -1, @intg), @id); + $$ = new NamedConst($id, new Int8($intg * -1, @id)); } enum_item : TOK_IDENTIFIER[id] '=' TOK_UINTEGER[intg] { - $$ = new NamedConst($id, new UInt8($intg, @intg), @id); + $$ = new NamedConst($id, new UInt8($intg, @id)); } enum_item : TOK_IDENTIFIER[id] { diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 8a3d35b..37f4e98 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -105,15 +105,15 @@ enum_items : enum_item { } enum_item : TOK_IDENTIFIER[id] '=' TOK_INTEGER[intg] { - $$ = new NamedConst($id, new Int8($intg, @intg), @id); + $$ = new NamedConst($id, new Int8($intg, @id)); } enum_item : TOK_IDENTIFIER[id] '=' '-' TOK_INTEGER[intg] { - $$ = new NamedConst($id, new Int8($intg * -1, @intg), @id); + $$ = new NamedConst($id, new Int8($intg * -1, @id)); } enum_item : TOK_IDENTIFIER[id] '=' TOK_UINTEGER[intg] { - $$ = new NamedConst($id, new UInt8($intg, @intg), @id); + $$ = new NamedConst($id, new UInt8($intg, @id)); } enum_item : TOK_IDENTIFIER[id] { diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 88d2581..3cf471e 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -6,8 +6,8 @@ #include "NamedConst.h" Matrix::Matrix(const char *n, MatrixElements *me, location_t loc) : Variable(n, loc), melements(me) { - NamedConst *rows = new NamedConst("rows", getNodeForUIntConst(me->getRowCount(), this->getLoc()), loc); - NamedConst *cols = new NamedConst("cols", getNodeForUIntConst(me->getColumnCount(), this->getLoc()), loc); + NamedConst *rows = new NamedConst("rows", getNodeForUIntConst(me->getRowCount(), this->getLoc())); + NamedConst *cols = new NamedConst("cols", getNodeForUIntConst(me->getColumnCount(), this->getLoc())); addChild(rows); addSymbol("rows", rows); addChild(cols); diff --git a/src/NamedConst.h b/src/NamedConst.h index 17b6b21..e795433 100644 --- a/src/NamedConst.h +++ b/src/NamedConst.h @@ -8,9 +8,9 @@ class NamedConst: public NamedNode { Node *value = NULL; public: - NamedConst(const char *name, location_t loc) : NamedNode(name, loc) {} + NamedConst(const string& name, location_t loc) : NamedNode(name, loc) {} - NamedConst(const char *name, Node *v, location_t loc) : NamedNode(name, loc), value(v) { + NamedConst(const string& name, Node *v) : NamedNode(name, v->getLoc()), value(v) { dt = value->getDataType(); } diff --git a/src/StringConst.cpp b/src/StringConst.cpp index 774c17d..fa06ba4 100644 --- a/src/StringConst.cpp +++ b/src/StringConst.cpp @@ -4,7 +4,7 @@ StringConst::StringConst(const string& name, const string& str, location_t loc) : Array(name, loc), str(str) { - NamedConst *nc = new NamedConst("size", getNodeForUIntConst(str.size(), loc), loc); + NamedConst *nc = new NamedConst("size", getNodeForUIntConst(str.size(), loc)); addChild(nc); addSymbol(nc); } From f24fdeb59b5d596e50017a28ca77556d642fcd22 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 7 Jul 2024 17:26:25 -0300 Subject: [PATCH 077/117] Add language feature: provide a builtin function typeid to check object type at runtime. --- src/BuildTypes.cpp | 11 +++++++++-- src/BuildTypes.h | 5 ++++- src/Program.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++- src/Program.h | 2 ++ 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 912da72..24fe6cb 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -13,9 +13,11 @@ #include "BackLLVM.h" #include "Int8.h" -BuildTypes::BuildTypes(DataType targetPointerType) : +BuildTypes::BuildTypes(DataType targetPointerType, Program *program) : targetPointerType(targetPointerType) { + unsigned pts = tinfo[targetPointerType].bitWidth; + tinfo[tvoid] = {"void", 0, Type::getVoidTy(global_context), dwarf::DW_ATE_address}; tinfo[tbool] = {"bool", 1, Type::getInt1Ty(global_context), dwarf::DW_ATE_boolean}; tinfo[tchar] = {"char", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned_char}; @@ -39,7 +41,9 @@ BuildTypes::BuildTypes(DataType targetPointerType) : tinfo[tdouble] = {"double", 64, Type::getDoubleTy(global_context), dwarf::DW_ATE_float}; tinfo[tldouble] = {"ldouble", 128, Type::getFP128Ty(global_context), dwarf::DW_ATE_float}; - unsigned pts = tinfo[targetPointerType].bitWidth; + // a generic internal pointer + tinfo[tobject] = {"object", pts, Type::getVoidTy(global_context)->getPointerTo(), dwarf::DW_ATE_address}; + tinfo[tobject].isComplex = true; const DataLayout &dl = mainmodule->getDataLayout(); for(int t = 0; t < __bdt_last; t++) { @@ -52,6 +56,9 @@ BuildTypes::BuildTypes(DataType targetPointerType) : info.diType = DBuilder->createBasicType(info.name, bitWidth, info.dwarfEnc); info.diPointerType = DBuilder->createPointerType(info.diType, pts); } + + NamedConst *typeidConst = new NamedConst(info.name, new Int8(t, program->getLoc())); + program->addSymbol(typeidConst); } } diff --git a/src/BuildTypes.h b/src/BuildTypes.h index f659e19..beba83c 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -16,6 +16,7 @@ enum BasicDataType {tvoid, tbool, tchar, tint8u, tint9u, tint12u, tint16u, tint32u, tint64u, tfloat, tdouble, tldouble, /* new types here! */ + tobject, __bdt_last}; enum DataQualifier {qnone, qconst, qvolatile}; @@ -59,6 +60,8 @@ struct DataTypeInfo { isInterface(false), isEnum(false), arrayDimensions(0) {}; }; +class Program; + class BuildTypes { private: map tinfo; @@ -79,7 +82,7 @@ class BuildTypes { public: static const DataType undefinedType = -1; - BuildTypes(DataType targetPointerType); + BuildTypes(DataType targetPointerType, Program *program); DataType addDataType(Node* userType, Type* llvmType, unsigned typeBitWidth = 0, bool isEnum = false); diff --git a/src/Program.cpp b/src/Program.cpp index fa9bca2..0fcf98e 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -29,7 +29,7 @@ Program::Program() : Node({0,0,0,0}) { RobDbgInfo.push_scope(RobDbgInfo.cunit); } - buildTypes = make_unique(currentTarget().pointerType); + buildTypes = make_unique(currentTarget().pointerType, this); global_alloc = BasicBlock::Create(global_context, "global"); dispatch = new Dispatch(); @@ -154,11 +154,56 @@ void Program::generateInjectionSetup(SourceLocation *sl) { funcInitGlobals->generate(NULL, NULL, global_alloc); } +void Program::declareBuiltins() { + + // typeid function + FunctionParams *typeid_params = new FunctionParams(); + typeid_params->append(new Variable("object", tobject, this->getLoc())); + FunctionDecl *typeid_decl = new FunctionDecl(tint8u, "typeid", typeid_params, this->getLoc()); + typeid_decl->setLinkage(GlobalValue::LinkOnceODRLinkage); + addChild(typeid_decl); + addSymbol(typeid_decl); +} + +void Program::generateBuiltins() { + // generate the typeid declaration + Node *decl = findSymbol("typeid"); + Value *typeidValue = decl->generate(NULL, NULL, global_alloc); + Function *typeidFunc = dyn_cast(typeidValue); + + // generate the typeid implementation + BasicBlock *body = BasicBlock::Create(global_context, "", typeidFunc); + Builder->SetInsertPoint(body); + auto& Arg = *typeidFunc->args().begin(); + Arg.addAttr(Attribute::ReadOnly); + auto *CmpVoid = Builder->CreateCmp(FCmpInst::ICMP_EQ, &Arg, ConstantPointerNull::get(Arg.getType()->getPointerTo())); + + // if pointer is not set, return zero/void + BasicBlock *returnVoid = BasicBlock::Create(global_context, "", typeidFunc); + Builder->SetInsertPoint(returnVoid); + Builder->CreateRet(ConstantInt::get(typeidFunc->getReturnType(), 0)); + + // else, return the object typeid + BasicBlock *returnTypeid = BasicBlock::Create(global_context, "", typeidFunc); + Builder->SetInsertPoint(returnTypeid); + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); + Value *indexList[2] = {zero, zero}; + Type *idType = Type::getInt8Ty(global_context); + Value *idValue = Builder->CreateLoad(typeidFunc->getReturnType(), &Arg); + Builder->CreateRet(idValue); + + Builder->SetInsertPoint(body); + Builder->CreateCondBr(CmpVoid, returnVoid, returnTypeid); + +} + extern bool parseIsCompleted; void Program::doSemanticAnalysis() { parseIsCompleted = true; + declareBuiltins(); + // instrumentation passes SymbolizeTree st; st.visit(*this); @@ -178,6 +223,8 @@ void Program::generate() { Node *mainFunc = NULL; + generateBuiltins(); + for(auto n: children()) { if (FunctionImpl *func = dynamic_cast(n)) { if (func->getName() == "main" || func->getName() == "__main") { diff --git a/src/Program.h b/src/Program.h index 015d41e..186cca8 100644 --- a/src/Program.h +++ b/src/Program.h @@ -16,6 +16,8 @@ class Program : public Node { Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); void generate(); void generateInjectionSetup(SourceLocation *sl); + void declareBuiltins(); + void generateBuiltins(); void doSemanticAnalysis(); Dispatch* getDispatcher() { From c000e399fab34b7bff3de04255e7a4deaf7c3a93 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 7 Jul 2024 17:34:47 -0300 Subject: [PATCH 078/117] Fixes the access of parent fields from nested types; remove : prefix from internal functions to improve debugging. --- src/ConstructorCall.cpp | 2 +- src/Program.cpp | 10 +++++----- src/Variable.cpp | 30 +++++++++++++++++++++++------- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/ConstructorCall.cpp b/src/ConstructorCall.cpp index 59a206e..039a9b7 100644 --- a/src/ConstructorCall.cpp +++ b/src/ConstructorCall.cpp @@ -34,7 +34,7 @@ Value* ConstructorCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlo parent->getName() + "." + leftValue->getName() : leftValue->getName(); - const string injectFuncName = ":get_injection_for_" + toInjection; + const string injectFuncName = "__get_injection_for_" + toInjection; Node *funcNode = findSymbol(injectFuncName); FunctionBase *funcDecl = dynamic_cast(funcNode); if (!funcDecl) { diff --git a/src/Program.cpp b/src/Program.cpp index 0fcf98e..7b0af10 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -49,7 +49,7 @@ void Program::generateInjectionSetup(SourceLocation *sl) { location_t loc = sl->getLoc(); // a function to init global vars for singleton injections - FunctionImpl *funcInitGlobals = new FunctionImpl((DataType)tvoid, ":injections_init", + FunctionImpl *funcInitGlobals = new FunctionImpl((DataType)tvoid, "__injections_init", new FunctionParams(), vector(), loc, loc, false); funcInitGlobals->setScope(this); addSymbol(funcInitGlobals); @@ -105,7 +105,7 @@ void Program::generateInjectionSetup(SourceLocation *sl) { // generate injection stuff - const string functionName = ":get_injection_for_" + to.getFullName(); + const string functionName = "__get_injection_for_" + to.getFullName(); FunctionImpl *finject = new FunctionImpl(destinationTy, functionName, new FunctionParams(), vector(), loc, loc, false); finject->setReturnIsPointer(true); @@ -115,9 +115,9 @@ void Program::generateInjectionSetup(SourceLocation *sl) { if (itype->scope == bs_singleton) { string globalVarName; if (bind.isComplex()) { - globalVarName = ":var_injection_for_" + bind.getFullName(); + globalVarName = "__var_injection_for_" + bind.getFullName(); } else { - globalVarName = ":var_injection_for_" + bind.getFullName(); + globalVarName = "__var_injection_for_" + bind.getFullName(); Node *var = findSymbol(globalVarName); if (!var) { // alloc the global var @@ -240,7 +240,7 @@ void Program::generate() { if (mainFunc && injections.size() > 0) { generateInjectionSetup(mainFunc); - FunctionCall *fc = new FunctionCall(":injections_init", new ParamsCall(), mainFunc->getLoc()); + FunctionCall *fc = new FunctionCall("__injections_init", new ParamsCall(), mainFunc->getLoc()); fc->setScope(mainFunc); mainFunc->addChild(fc, true); } diff --git a/src/Variable.cpp b/src/Variable.cpp index 96ecb17..8c82824 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -11,23 +11,39 @@ Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { FunctionImpl *func = dynamic_cast(stem); if (func && func->getThisArg()) { - // generating a function of a type: get the gep on _this or :parent parameters + // generating a function of a type: get the gep on _this or _parent parameters DataType thisDt = func->getThisArgDt(); Type *thisTy = buildTypes->llvmType(thisDt); Value *thisptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + if (!stem->getScope() || this->getScope() == stem->getScope()) { // the var is being accessed in global scope (!stem->getScope()) or - // in a method of the type itself. Thus, we _this and gep the field - alloc = Builder->CreateStructGEP(thisTy, thisptr, gepidx, "gepthis"); - } else { - // this var is in the parent scope. _this is an nested type. + // in a method of the type itself. Thus, we gep the field in _this argument + return Builder->CreateStructGEP(thisTy, thisptr, gepidx, "gep" + getName()); + + } else if (symbols.find("parent") != symbols.end()) { + // the symbol being accessed has a parent (acessing a nested type var or method) // Thus, we access parent in _this and gep the field DataType parentDt = this->getScope()->getDataType(); Type *parentTy = buildTypes->llvmType(parentDt); int idxParentInThis = static_cast(symbols["parent"])->getGEPIndex(); Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, idxParentInThis, "gepthis"); Value *parentptr = Builder->CreateLoad(parentTy->getPointerTo(), parentAlloc, "derefparent"); - alloc = Builder->CreateStructGEP(parentTy, parentptr, gepidx, "gepparent"); + return Builder->CreateStructGEP(parentTy, parentptr, gepidx, "gep" + getName()); + + } else { + // stem is a nested type and the var is in the parent scope. + // Thus, we access parent in stem and gep the field + Node *nestedType = stem->getScope(); + auto nestedSymbols = nestedType->getSymbols(); + Node *parentField = nestedSymbols.find("parent")->second; + Variable *parentFieldVar = static_cast(parentField); + assert(parentField && "Parent field must exists and have a gepIndex!"); + int idxParentInThis = parentFieldVar->getGEPIndex(); + Type *parentTy = buildTypes->llvmType(parentFieldVar->getDataType()); + Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, idxParentInThis, "gepparent"); + Value *parentptr = Builder->CreateLoad(parentTy->getPointerTo(), parentAlloc, "derefparent"); + return Builder->CreateStructGEP(parentTy, parentptr, gepidx, "gep" + getName()); } } else { // accessing a var of a user type: get the gep in the scope (user type) of the scalar @@ -36,7 +52,7 @@ Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { if (stem->isPointerToPointer()) { ptr = Builder->CreateLoad(udt->getPointerTo(), ptr, "deref"); } - alloc = Builder->CreateStructGEP(udt, ptr, gepidx, "gepu"); // FIXME + return Builder->CreateStructGEP(udt, ptr, gepidx, "gepu"); } } From 23d6e133f4ef805336fa79978f7470478854f4bb Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 7 Jul 2024 20:16:54 -0300 Subject: [PATCH 079/117] Fixes short-circuit boolean for boolean expressions in variables and parameters of function calls --- src/FunctionCall.cpp | 7 +++++++ src/FunctionImpl.cpp | 2 +- src/Node.cpp | 11 +++++++++-- src/Scalar.cpp | 6 ++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index bd95773..19021a3 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -95,6 +95,13 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock if (!valor) { yyerrorcpp(string_format("The value for argument %s is undefined.", argName.c_str()), param); return NULL; + } else { + // A distinct block can return from boolean short-circuit evaluation + Instruction* instr = dyn_cast(valor); + if (instr && instr->getParent() != allocblock) { + block = instr->getParent(); + Builder->SetInsertPoint(block); + } } if (buildTypes->isComplex(call_dt)) { diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index ed926ae..7bcc8ca 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -138,7 +138,7 @@ Value *FunctionImpl::generate(FunctionImpl *, BasicBlock *, BasicBlock *allocblo last_block = fblock; // prevent mallformed block at the end without proper return instruction - if (last_block && last_block->getValueID() == Value::BasicBlockVal) { + if (last_block->getValueID() == Value::BasicBlockVal) { BasicBlock *lb = (BasicBlock*)last_block; Builder->SetInsertPoint(lb); RobDbgInfo.emitLocation(&endfunction); diff --git a/src/Node.cpp b/src/Node.cpp index 2ff73a1..b197563 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -87,8 +87,15 @@ Value* Node::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl Value* Node::generateChildren(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { for(Node *n: children()) { Value *b = n->generate(func, block, allocblock); - if (b && b->getValueID() == Value::BasicBlockVal) - block = (BasicBlock*)b; + if (b) { + if (b->getValueID() == Value::BasicBlockVal) + block = (BasicBlock*)b; + else if (Instruction* instr = dyn_cast(b)) { + // A distinct block can return from boolean short-circuit evaluation + if (instr->getParent() != allocblock) + block = instr->getParent(); + } + } } return block; } diff --git a/src/Scalar.cpp b/src/Scalar.cpp index b4da911..7c0f9d5 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -54,6 +54,12 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Value *exprv = expr->generate(func, block, allocblock); if (!exprv) return NULL; + else { + // A distinct block can return from boolean short-circuit evaluation + Instruction* instr = dyn_cast(exprv); + if (instr && instr->getParent() != allocblock) + block = instr->getParent(); + } DataType exprv_dt = expr->getDataType(); if (hasQualifier(qconst)) From 48edbe43cbd6025ac1efa3d1fcd1fbdd2fbb6aac Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 7 Jul 2024 20:26:02 -0300 Subject: [PATCH 080/117] Fixes to support interface global variables. --- src/ConstructorCall.cpp | 28 ++++++++++++++++++------ src/Dispatch.cpp | 28 +++++++++++++++++++----- src/Dispatch.h | 1 + src/Interface.cpp | 3 +++ src/Program.cpp | 47 ++++++++++++++++++++++++++++++++++++++++- src/Scalar.cpp | 10 ++++++--- 6 files changed, 102 insertions(+), 15 deletions(-) diff --git a/src/ConstructorCall.cpp b/src/ConstructorCall.cpp index 039a9b7..48dad0d 100644 --- a/src/ConstructorCall.cpp +++ b/src/ConstructorCall.cpp @@ -12,16 +12,32 @@ Value* ConstructorCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlo // alloc RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); + GlobalVariable *gv = NULL; Value *var = leftValue->getLLVMValue(func); if (var == NULL) { // is a new left var + Type *vty = buildTypes->llvmType(dt); + if (buildTypes->isInterface(dt)) { + vty = vty->getPointerTo(); + leftValue->setPointerToPointer(true); + } Builder->SetInsertPoint(allocblock); - var = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, 0, - leftValue->getName()); + if (allocblock == global_alloc) { + //Constant *init = ConstantAggregateZero::get(buildTypes->llvmType(dt)); + Constant *init = ConstantPointerNull::get(buildTypes->llvmType(dt)->getPointerTo()); + gv = new GlobalVariable(*mainmodule, vty, hasQualifier(qconst), + GlobalValue::ExternalLinkage, init, leftValue->getName()); + var = gv; + } else { + var = Builder->CreateAlloca(vty, dataAddrSpace, 0, + leftValue->getName()); + } leftValue->setAlloca(var); leftValue->setDataType(dt); - if (debug_info) - RobDbgInfo.declareVar(leftValue, var, allocblock); + if (debug_info) { + if (allocblock != global_alloc) + RobDbgInfo.declareVar(leftValue, var, allocblock); + } } vector args; args.push_back(var); @@ -47,7 +63,7 @@ Value* ConstructorCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlo program->addSymbol(funcDecl); } RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(block); + Builder->SetInsertPoint(allocblock == global_alloc ? global_alloc : block); return Builder->CreateCall(funcDecl->getLLVMFunction()); } else { @@ -63,7 +79,7 @@ Value* ConstructorCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlo FunctionBase *initfunc = dynamic_cast(fsymbol); RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(block); + Builder->SetInsertPoint(allocblock == global_alloc ? global_alloc : block); if (initfunc->needsParent()) { Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); diff --git a/src/Dispatch.cpp b/src/Dispatch.cpp index 428110d..36cb4f2 100644 --- a/src/Dispatch.cpp +++ b/src/Dispatch.cpp @@ -46,6 +46,19 @@ void Dispatch::generateDispatchFunctions(Node *scope) { auto fblock = BasicBlock::Create(global_context, "", dispatchFunc); Builder->SetInsertPoint(fblock); + if (impls.size() == 0) { + // provide an empty implementation for the dispatcher + + Type *retTy = dispatchFunc->getReturnType(); + if (retTy->isVoidTy()) { + Builder->CreateRetVoid(); + } else { + // this returns zero for integers and floats + Builder->CreateRet(Constant::getNullValue(retTy)); + } + continue; + } + // the first field of arg this is the object type id Type *thisTy = buildTypes->llvmType(functionDecl->getThisArgDt()); Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); @@ -55,7 +68,7 @@ void Dispatch::generateDispatchFunctions(Node *scope) { SwitchInst *switchi = Builder->CreateSwitch(idValue, NULL, impls.size()); - int caseid = 0; + bool hasDefault = false; for(DataType implDt : impls) { auto implDtBlock = BasicBlock::Create(global_context, "", dispatchFunc); Builder->SetInsertPoint(implDtBlock); @@ -83,15 +96,20 @@ void Dispatch::generateDispatchFunctions(Node *scope) { // add switch case Builder->SetInsertPoint(fblock); - if (caseid == 0) + if (!hasDefault && destTypeName.find("void_") == string::npos) { switchi->setDefaultDest(implDtBlock); - else { - ConstantInt *implDtId = ConstantInt::get(Type::getInt8Ty(global_context), implDt, true); // TODO: provide better ids, per baseType + hasDefault = true; + } else { + // TODO: provide better ids, per baseType + ConstantInt *implDtId = ConstantInt::get(Type::getInt8Ty(global_context), implDt, true); switchi->addCase(implDtId, implDtBlock); } - caseid++; } } } } +} + +void Dispatch::notifyInterface(DataType intf) { + dispatchHash[intf]; } \ No newline at end of file diff --git a/src/Dispatch.h b/src/Dispatch.h index d23baf5..29804bd 100644 --- a/src/Dispatch.h +++ b/src/Dispatch.h @@ -14,4 +14,5 @@ class Dispatch { public: void addDataTypeImplementation(DataType base, DataType impl); void generateDispatchFunctions(Node *scope); + void notifyInterface(DataType intf); }; diff --git a/src/Interface.cpp b/src/Interface.cpp index 213c1fe..5f0a7b4 100644 --- a/src/Interface.cpp +++ b/src/Interface.cpp @@ -3,6 +3,7 @@ #include "UserType.h" #include "FunctionImpl.h" #include "FunctionDecl.h" +#include "Program.h" void Interface::createDataType() { StructType *intftype = StructType::create(global_context, getName()); @@ -11,6 +12,8 @@ void Interface::createDataType() { if (dt == BuildTypes::undefinedType) { yyerrorcpp("Type " + name + " alread defined.", this); yyerrorcpp(name + " was first defined here.", buildTypes->location(dt)); + } else { + program->getDispatcher()->notifyInterface(dt); } } diff --git a/src/Program.cpp b/src/Program.cpp index 7b0af10..6c0660e 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -245,9 +245,54 @@ void Program::generate() { mainFunc->addChild(fc, true); } - if (mainFunc) + FunctionType *global_init_type = FunctionType::get(Type::getVoidTy(global_context), ArrayRef(), false); + Function *global_init = NULL; + if (mainFunc && global_alloc->size() > 0) { + // create a function named :global_init to init global vars by calling their constructors + global_init = Function::Create(global_init_type, Function::ExternalLinkage, codeAddrSpace, + "__globals_init", mainmodule); + global_init->setCallingConv(CallingConv::C); + + // clear debug information as we will move instructions to __globals_init + vector remove; + for (auto &a : *global_alloc) { + if (a.getOpcode() == Instruction::Call) { + CallInst *call = dyn_cast(&a); + if (call->getCalledFunction()->isDeclaration()) { + a.replaceAllUsesWith(UndefValue::get(call->getType())); + remove.push_back(call); + continue; + } + } + a.setDebugLoc(DebugLoc()); + } + for(auto *i : remove) { + i->dropAllReferences(); + i->removeFromParent(); + } + Builder->SetInsertPoint(global_alloc); + Builder->CreateRetVoid(); + global_init->insert(global_init->end(), global_alloc); + } + + if (mainFunc) { + // add naked attribute to main to prevent backend + // of emmiting prologue and epilogue, as it is the + // first call in the stack + /*if (currentTargetId != st_native) + if (FunctionImpl *fi = dynamic_cast(mainFunc)) + fi->getAttributes()->addAttribute(fa_naked);*/ + mainFunc->generate(NULL, NULL, global_alloc); + if (global_init) { + Function *mainf = mainmodule->getFunction("main"); + BasicBlock *entryBlock = &mainf->getEntryBlock(); + Builder->SetInsertPoint(entryBlock->end()->getPrevNode()); // before br + Builder->CreateCall(global_init_type, global_init); + } + } + dispatch->generateDispatchFunctions(program); if (debug_info) diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 7c0f9d5..f42d3ac 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -86,8 +86,10 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc ret = alloc = exprvc; else { Type *gty = buildTypes->llvmType(dt); - if (expr->isPointerToPointer()) + if (expr->isPointerToPointer()) { + setPointerToPointer(true); gty = gty->getPointerTo(); + } GlobalVariable *gv = new GlobalVariable(*mainmodule, gty, hasQualifier(qconst), GlobalValue::ExternalLinkage, exprvc, name); ret = alloc = gv; @@ -138,7 +140,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc currty = currty->getPointerTo(); RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(block); + Builder->SetInsertPoint(allocblock == global_alloc ? global_alloc : block); Value *nvalue = NULL; // Pointers need a custom procedure: load the stem, set the @@ -177,7 +179,9 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc } RobDbgInfo.emitLocation(this); - return Builder->CreateStore(nvalue, alloc, symbol->hasQualifier(qvolatile)); + const DataLayout &DL = mainmodule->getDataLayout(); + Align align = DL.getABITypeAlign(nvalue->getType()); + return Builder->CreateAlignedStore(nvalue, alloc, align, symbol->hasQualifier(qvolatile)); } } From e9f2c58d2a88ff3b4d8423ebd57cac1eab5da2a3 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 7 Jul 2024 20:30:48 -0300 Subject: [PATCH 081/117] Improves coercion/cast handling/messages. Disabling some unsigned <-> signed messages until we have a better solution. --- src/FunctionCall.cpp | 28 +------------- src/Load.cpp | 2 +- src/PropagateTypes.cpp | 85 +++++++++++++++++++++++++++++------------- src/PropagateTypes.h | 13 +++++-- 4 files changed, 72 insertions(+), 56 deletions(-) diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 19021a3..e85f9f2 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -104,38 +104,14 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock } } - if (buildTypes->isComplex(call_dt)) { - //we don't support cohercion between user types yet - if (call_dt != def_dt) { - Node *utnode = findSymbol(buildTypes->name(call_dt)); - UserType *ut = dynamic_cast(utnode); - - if (ut && ut->implementsInterface(buildTypes->name(def_dt))) { - program->getDispatcher()->addDataTypeImplementation(def_dt, call_dt); - - } else if (!ut || !ut->implementsInterface(buildTypes->name(def_dt))) { - yyerrorcpp(string_format("Argument %s expects '%s' but '%s' was provided.", - argName.c_str(), - buildTypes->name(def_dt), - buildTypes->name(call_dt)), this); - yywarncpp("The function declaration is here.", fsymbol); - } - } - } else if (buildTypes->isArrayOrMatrix(call_dt)) { - if (!buildTypes->isArrayCompatible(call_dt, def_dt)) { - yyerrorcpp(string_format("Argument %s expects '%s' but '%s' was provided.", - argName.c_str(), - buildTypes->name(def_dt), - buildTypes->name(call_dt)), this); - } - + if (buildTypes->isArrayOrMatrix(call_dt)) { // we pass the address of the first element Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); Value *indexList[2] = {zero, zero}; Value *ptr = Builder->CreateGEP(param->getLLVMType(), valor, ArrayRef(indexList), "gep"); valor = ptr; } - + args.insert(args.begin() + paramId, valor); dataTypes.insert(dataTypes.begin() + paramId, def_dt); diff --git a/src/Load.cpp b/src/Load.cpp index 620335f..5556e6a 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -100,7 +100,7 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl } if (!alloc) { - assert(alloc && "There's no alloc to load from."); + yyerrorcpp(string_format("Symbol %s is undefined at this point.", ident.getFullName().c_str()), this); return NULL; // Caused by an error on previous statement that defines the symbol } diff --git a/src/PropagateTypes.cpp b/src/PropagateTypes.cpp index a561d1b..d456a75 100644 --- a/src/PropagateTypes.cpp +++ b/src/PropagateTypes.cpp @@ -2,6 +2,7 @@ #include "PropagateTypes.h" #include "ConstructorCall.h" #include "Scalar.h" +#include "Program.h" void PropagateTypes::propagateChildren(Node& n, std::function lambda) { for (auto it = n.node_children.begin(); it != n.node_children.end(); ++it) { @@ -14,6 +15,30 @@ void PropagateTypes::propagateChildren(Node& n, std::function lambd } } +Node* PropagateTypes::coerceToUserTypes(Node *n, const DataType destTy) { + DataType ndt = n->getDataType(); + if (!buildTypes->isComplex(ndt) && !buildTypes->isArrayOrMatrix(ndt)) + return NULL; + + if (ndt != destTy) { + Node *utnode = n->getScope()->findSymbol(buildTypes->name(ndt)); + UserType *ut = dynamic_cast(utnode); + + if (ut && ut->implementsInterface(buildTypes->name(destTy))) { + program->getDispatcher()->addDataTypeImplementation(destTy, ndt); + return n; + } else if (buildTypes->isArrayOrMatrix(ndt)) { + if (buildTypes->isArrayCompatible(ndt, destTy)) + return n; + } else if (destTy == tobject && + (buildTypes->isComplex(ndt) || buildTypes->isInterface(ndt))) { + return n; + } + } + + return NULL; +} + Node* PropagateTypes::coerceTo(Node *n, const DataType destTy, bool warns) { if (isUndefined(n)) return NULL; @@ -23,10 +48,13 @@ Node* PropagateTypes::coerceTo(Node *n, const DataType destTy, bool warns) { bool lIsNumeric = buildTypes->isNumericDataType(destTy); bool rIsNumeric = buildTypes->isNumericDataType(valueTy); if (!lIsNumeric || !rIsNumeric) { - yyerrorcpp(string_format("Can not cast from '%s' to '%s'.", - buildTypes->name(valueTy), - buildTypes->name(destTy)), n); - return NULL; + Node *result = coerceToUserTypes(n, destTy); + if (!result) { + yyerrorcpp(string_format("Can not cast from '%s' to '%s'.", + buildTypes->name(valueTy), + buildTypes->name(destTy)), n); + return NULL; + } } bool destUnsigned = buildTypes->isUnsignedDataType(destTy); @@ -38,23 +66,21 @@ Node* PropagateTypes::coerceTo(Node *n, const DataType destTy, bool warns) { if (buildTypes->isIntegerDataType(destTy) && buildTypes->isIntegerDataType(valueTy)) { // if we have signed and unsigned operands, convert valueTy to destTy - if (warns) { - if ((destUnsigned ^ valueUnsigned) && valueTy != tbool) { - // if value is constant, convert it to the dest type - bool valueIsConstant = n->isConstExpr(); - if (valueIsConstant) { - valueTy = valueUnsigned ? buildTypes->unsignedToSigned(valueTy) : - buildTypes->signedToUnsigned(valueTy); - } else { - string name = n->getName(); - if (name == "") - name = "Value"; - if (destUnsigned) - yywarncpp(string_format("%s has been used as unsigned.", name.c_str()), n); - else - yywarncpp(string_format("%s has been used as signed.", name.c_str()), n); - } - } + if ((destUnsigned ^ valueUnsigned) && valueTy != tbool) { + // if value is constant, convert it to the dest type + bool valueIsConstant = n->isConstExpr(); + if (valueIsConstant) { + valueTy = valueUnsigned ? buildTypes->unsignedToSigned(valueTy) : + buildTypes->signedToUnsigned(valueTy); + } /*else if (warns) { + string name = n->getName(); + if (name == "") + name = "Value"; + if (destUnsigned) + yywarncpp(string_format("%s has been used as unsigned.", name.c_str()), n); + else + yywarncpp(string_format("%s has been used as signed.", name.c_str()), n); + }*/ } // if destTy is larger, SExtended or ZExtended value @@ -67,11 +93,20 @@ Node* PropagateTypes::coerceTo(Node *n, const DataType destTy, bool warns) { return expand; } else if (destBWidth < valueBWidth) { + if (n->isConstExpr()) { + // if the value is constant, check if the number of active bits + // fits in the dest bit width and prevent false trunc warnings + Value *nv = n->generate(NULL, NULL, NULL); + Constant *c = dyn_cast(nv); + unsigned bits = c->getUniqueInteger().getActiveBits(); + if (bits <= destBWidth) + warns = false; + } if (warns) { string name = n->getName(); if (name == "") name = "Value"; - yywarncpp(string_format("%s (%s) has been truncated to fit %s.", name.c_str(), + yywarncpp(string_format("%s (%s) has been truncated to %s.", name.c_str(), buildTypes->name(valueTy), buildTypes->name(destTy)), n); } return new TruncInt(n, destTy); @@ -165,11 +200,11 @@ DataType PropagateTypes::coerceArithOrCmp(Node &n, Node *lNode, Node *rNode) { } else { if (lUnsigned) { - yywarncpp("The left operand was converted to signed.", lNode); + //yywarncpp("The left operand was converted to signed.", lNode); lTy = buildTypes->unsignedToSigned(lTy); } else { - yywarncpp("The right operand was converted to signed.", rNode); + //yywarncpp("The right operand was converted to signed.", rNode); rTy = buildTypes->unsignedToSigned(rTy); } } @@ -323,7 +358,7 @@ Node* PropagateTypes::visit(FunctionCall& fc) { while (passedParam != fc.getParameters().end()) { DataType call_dt = (*passedParam)->getDataType(); DataType def_dt = (*calledFuncParam)->getDataType(); - if (buildTypes->isPrimitiveType(def_dt) && call_dt != def_dt) { + if (call_dt != def_dt) { Node *newParam = coerceTo((*passedParam), def_dt); *passedParam = newParam; } diff --git a/src/PropagateTypes.h b/src/PropagateTypes.h index c2efa3f..146b93d 100644 --- a/src/PropagateTypes.h +++ b/src/PropagateTypes.h @@ -64,10 +64,14 @@ class ZExtInt: public CoercionBase { virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { Value *v = node->generate(func, block, allocblock); - assert(v && "Node must generate a value to ZExt."); - RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(block); - return Builder->CreateZExt(v, buildTypes->llvmType(dt), "zext"); + if (!v) { + yyerrorcpp("There is no value to cast from (zext) ", node); + return NULL; + } else { + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateZExt(v, buildTypes->llvmType(dt), "zext"); + } } }; @@ -186,6 +190,7 @@ class PropagateTypes: public Visitor { } static Node *coerceTo(Node *n, const DataType destTy, bool warns = true); + static Node *coerceToUserTypes(Node *n, const DataType destTy); DataType coerceArithOrCmp(Node& n, Node *left, Node *right); virtual Node* visit(Node& n) override { From d1ea6ab97308aa25f5da593a138de0265ac8f53c Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 7 Jul 2024 20:43:26 -0300 Subject: [PATCH 082/117] Feature: debug only functions - support to assert. --- lib/assert.rob | 17 +++++++++++++++++ src/FunctionAttributes.h | 10 +++++++++- src/FunctionCall.cpp | 4 ++++ src/FunctionDecl.cpp | 14 +++++++++++++- src/FunctionDecl.h | 2 ++ src/Language.l | 1 + src/Language.y | 1 + src/LanguageHeader.y | 2 +- src/LanguageUse.y | 1 + 9 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 lib/assert.rob diff --git a/lib/assert.rob b/lib/assert.rob new file mode 100644 index 0000000..314cb94 --- /dev/null +++ b/lib/assert.rob @@ -0,0 +1,17 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +/* + * An assertion function that loops infinitely if the tested condition is false. + * The noinline attribute maintains the caller function in the stack + * (even for interrupts), easing the identification of the cause. + * The debugonly attribute ensures that the function is compiled only + * while debugging (-g) + */ + +void assert(bool a, char[] message) noinline, debugonly { + volatile x = message; + if (!a) { loop {} } +} \ No newline at end of file diff --git a/src/FunctionAttributes.h b/src/FunctionAttributes.h index f3df96a..8a203f8 100644 --- a/src/FunctionAttributes.h +++ b/src/FunctionAttributes.h @@ -1,7 +1,15 @@ #pragma once -enum FunctionAttributeType {fa_weak, fa_inline, fa_noinline, fa_section, fa_naked, fa_signal}; +enum FunctionAttributeType { + fa_weak, + fa_inline, + fa_noinline, + fa_section, + fa_naked, + fa_signal, + fa_debugonly, +}; typedef pair FunctionAttribute; diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index e85f9f2..5e766fa 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -64,6 +64,10 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock return NULL; } + // skip calling onlydebug functions when not debugging + if (!debug_info && fsymbol->getAttributes()->hasAttribute(fa_debugonly)) + return NULL; + dt = fsymbol->getDataType(); Node *stemSymbol = NULL; diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 8e486b2..9dec694 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -104,18 +104,23 @@ void FunctionBase::addFunctionAttributes(Function *func) { func->setSection(value); break; case fa_signal: - func->addFnAttr("signal"); //no break, share naked attrs + func->addFnAttr("signal"); break; case fa_naked: func->addFnAttr(Attribute::Naked); func->addFnAttr(Attribute::NoInline); break; + default: + break; } } } Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocblock) { + if (func) + return func; + Node *symbol = findSymbol(name); if (symbol != NULL && symbol != this) { yyerrorcpp("Function/symbol " + name + " already defined.", this); @@ -160,3 +165,10 @@ Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocbloc func = nfunc; return func; } + +Value* FunctionDecl::getLLVMValue(Node *, FunctionImpl *) { + if (!func) + generate(NULL, NULL, global_alloc); + return func; +} + diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 53f917b..65bdc0a 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -149,4 +149,6 @@ class FunctionDecl: public FunctionBase { } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; + + virtual Value *getLLVMValue(Node *, FunctionImpl *) override; }; diff --git a/src/Language.l b/src/Language.l index b3b132f..195cf7e 100644 --- a/src/Language.l +++ b/src/Language.l @@ -50,6 +50,7 @@ EXP ([Ee][-+]?[0-9]+)? "section" { return TOK_SECTION; } "naked" { return TOK_NAKED; } "signal" { return TOK_SIGNAL; } +"debugonly" { return TOK_DEBUGONLY; } "bind" { return TOK_BIND; } "to" { return TOK_TO; } diff --git a/src/Language.y b/src/Language.y index 4fe2af4..e342049 100644 --- a/src/Language.y +++ b/src/Language.y @@ -150,6 +150,7 @@ function_attribute | TOK_NOINLINE { $$ = new FunctionAttribute(fa_noinline, ""); } | TOK_NAKED { $$ = new FunctionAttribute(fa_naked, ""); } | TOK_SIGNAL { $$ = new FunctionAttribute(fa_signal, ""); } + | TOK_DEBUGONLY { $$ = new FunctionAttribute(fa_debugonly, ""); } | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } event : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index 778d151..5156e8d 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -35,7 +35,7 @@ %token TOK_QUANDO TOK_ESTA %token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT -%token TOK_INLINE TOK_NOINLINE TOK_WEAK TOK_SECTION TOK_NAKED TOK_SIGNAL +%token TOK_INLINE TOK_NOINLINE TOK_WEAK TOK_SECTION TOK_NAKED TOK_SIGNAL TOK_DEBUGONLY %union { char *ident; diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 37f4e98..42aeed3 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -158,6 +158,7 @@ function_attribute | TOK_NOINLINE { $$ = new FunctionAttribute(fa_noinline, ""); } | TOK_NAKED { $$ = new FunctionAttribute(fa_naked, ""); } | TOK_SIGNAL { $$ = new FunctionAttribute(fa_signal, ""); } + | TOK_DEBUGONLY { $$ = new FunctionAttribute(fa_debugonly, ""); } | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } qualifier : TOK_CONST { $$ = qconst; } From c119fccb5f1972cc5ed6554e431609126de4ae92 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 7 Jul 2024 20:59:42 -0300 Subject: [PATCH 083/117] Add Interrupts support and improvements in the standard lib. Renames avr328p to atmega328p. Breakout game! --- .gitignore | 2 +- CMakeLists.txt | 2 +- lib/arch/avr/avr5mcu.rob | 44 +- lib/{avr328p.ld => atmega328p.ld} | 0 lib/{avr328p.rob => atmega328p.rob} | 71 +-- lib/avr5.ld | 2 + lib/display/ssd1306.rob | 8 +- lib/graphic/canvas8.rob | 24 +- lib/intfs/databus.rob | 3 + lib/intfs/interrupt.rob | 20 + lib/intfs/ports.rob | 4 +- platformio/examples/blink/platformio.ini | 2 +- platformio/examples/breakout/.gitignore | 5 + .../examples/breakout/breakout.code-workspace | 11 + platformio/examples/breakout/platformio.ini | 38 ++ platformio/examples/breakout/specs/avr.spec | 19 + platformio/examples/breakout/specs/stm32.spec | 22 + platformio/examples/breakout/src/example.c | 403 ++++++++++++++++++ platformio/examples/breakout/src/game.rob | 241 +++++++++++ platformio/examples/breakout/src/main.rob | 68 +++ .../examples/old/avr328p-blink/platformio.ini | 2 +- .../examples/old/avr328p-ssd1306/genll.sh | 11 - .../old/avr328p-ssd1306/platformio.ini | 20 +- platformio/examples/ssd1306/platformio.ini | 4 +- platformio/examples/ssd1306/specs/avr.spec | 23 +- platformio/install | 2 +- .../boards/{avr328p.json => atmega328p.json} | 0 platformio/platform/builder/main.py | 24 +- platformio/platform/platform.py | 6 +- test/{avr328p => atmega328p}/Makefile | 20 +- .../bitstruct-field-i5.rob | 0 test/{avr328p => atmega328p}/bsscheck.rob | 0 test/{avr328p => atmega328p}/bssinjcheck.rob | 0 test/{avr328p => atmega328p}/datacheck.rob | 0 test/{avr328p => atmega328p}/globaldata.rob | 0 test/{avr328p => atmega328p}/globals.rob | 0 test/{avr328p => atmega328p}/itoa.rob | 0 test/{avr328p => atmega328p}/memcpycheck.rob | 0 .../robcmp-simavr-debug | 0 test/{avr328p => atmega328p}/runtest.sh | 0 test/{avr328p => atmega328p}/runtrace.sh | 0 test/{avr328p => atmega328p}/uart.rob | 0 test/{avr328p => atmega328p}/uartdata.rob | 0 test/avr328p/run_avr | 1 - test/debug/platformio.ini | 2 +- test/general/bsscheck.rob | 2 +- test/general/bssinjcheck.rob | 2 +- test/general/global-pointer.rob | 56 +++ test/general/memcpycheck.rob | 2 +- test/general/phior.rob | 22 + 50 files changed, 1067 insertions(+), 121 deletions(-) rename lib/{avr328p.ld => atmega328p.ld} (100%) rename lib/{avr328p.rob => atmega328p.rob} (54%) create mode 100644 lib/intfs/interrupt.rob create mode 100644 platformio/examples/breakout/.gitignore create mode 100644 platformio/examples/breakout/breakout.code-workspace create mode 100644 platformio/examples/breakout/platformio.ini create mode 100644 platformio/examples/breakout/specs/avr.spec create mode 100644 platformio/examples/breakout/specs/stm32.spec create mode 100644 platformio/examples/breakout/src/example.c create mode 100644 platformio/examples/breakout/src/game.rob create mode 100644 platformio/examples/breakout/src/main.rob delete mode 100755 platformio/examples/old/avr328p-ssd1306/genll.sh rename platformio/platform/boards/{avr328p.json => atmega328p.json} (100%) rename test/{avr328p => atmega328p}/Makefile (53%) rename test/{avr328p => atmega328p}/bitstruct-field-i5.rob (100%) rename test/{avr328p => atmega328p}/bsscheck.rob (100%) rename test/{avr328p => atmega328p}/bssinjcheck.rob (100%) rename test/{avr328p => atmega328p}/datacheck.rob (100%) rename test/{avr328p => atmega328p}/globaldata.rob (100%) rename test/{avr328p => atmega328p}/globals.rob (100%) rename test/{avr328p => atmega328p}/itoa.rob (100%) rename test/{avr328p => atmega328p}/memcpycheck.rob (100%) rename test/{avr328p => atmega328p}/robcmp-simavr-debug (100%) rename test/{avr328p => atmega328p}/runtest.sh (100%) rename test/{avr328p => atmega328p}/runtrace.sh (100%) rename test/{avr328p => atmega328p}/uart.rob (100%) rename test/{avr328p => atmega328p}/uartdata.rob (100%) delete mode 120000 test/avr328p/run_avr create mode 100644 test/general/global-pointer.rob create mode 100644 test/general/phior.rob diff --git a/.gitignore b/.gitignore index 890b52d..2ed40ef 100644 --- a/.gitignore +++ b/.gitignore @@ -65,7 +65,7 @@ refdatasheets build test/general/out test/general/temp.spec -test/avr328p/out +test/atmega328p/out platformio/toolchain-robcmp/bin platformio/toolchain-robcmp/lib platformio/avr-gdb-build diff --git a/CMakeLists.txt b/CMakeLists.txt index dc27b9e..e72bfe3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,4 +71,4 @@ target_link_libraries(robcmp ${llvm_libs}) set_target_properties(robcmp PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" - VS_DEBUGGER_COMMAND_ARGUMENTS "-a avr328p -Oz ../platformio/samples/avr328p-blink/src/main.rob") + VS_DEBUGGER_COMMAND_ARGUMENTS "-a atmega328p -Oz ../platformio/samples/atmega328p-blink/src/main.rob") diff --git a/lib/arch/avr/avr5mcu.rob b/lib/arch/avr/avr5mcu.rob index b2c51f7..1f57fc5 100644 --- a/lib/arch/avr/avr5mcu.rob +++ b/lib/arch/avr/avr5mcu.rob @@ -2,19 +2,35 @@ use intfs.mcu; use intfs.ports; use intfs.databus; - +use assert; use avr5regs; void __delay_us(); +int_usart_rx = interrupt_i8(); + +void check_irq_handler(uint8 h) { + assert(h != void, "IRQ enabled without setting the handler."); +} + +void irq_usart_rx() signal, section __irqs { + check_irq_handler(typeid(int_usart_rx)); + byte = UDR0; + int_usart_rx.handler(byte); +} + type avr5mcu implements mcu { uint32 clock() inline { return 16E6; } - void set_interruptions(bool enabled) { - SREG.I = enabled; + void set_interruptions(bool enabled) inline { + if enabled { + asm "sei"; + } else { + asm "cli"; + } } /* implement this idea later! @@ -71,16 +87,18 @@ type avr5mcu implements mcu { } void wait_us(uint16 us) { - while us > 0 { + volatile uus = us; + while uus > 0 { __delay_us(); - us--; + uus--; } } void wait_ms(uint16 ms) { - while ms > 0 { + volatile mms = ms; + while mms > 0 { wait_us(1000); - ms--; + mms--; } } @@ -104,6 +122,8 @@ type avr5mcu implements mcu { SPCR.CPHA = false; } + void async_read_to(interrupt_i8 i) {} + void enable() { SPCR.SPE = true; } @@ -146,6 +166,7 @@ type avr5mcu implements mcu { } uart0 implements databus { + void setup(uint32 baud) { // use 2x UCSR0A.U2X0 = false; @@ -172,6 +193,11 @@ type avr5mcu implements mcu { UCSR0C.USBS0 = false; } + void async_read_to(interrupt_i8 i) { + //int_usart_rx = i; + UCSR0B.RXCIE0 = true; + } + void enable() { // enable tx and rx UCSR0B.RXEN0 = true; @@ -182,6 +208,8 @@ type avr5mcu implements mcu { // disable tx and rx UCSR0B.RXEN0 = false; UCSR0B.TXEN0 = false; + // disable RX interruption + UCSR0B.RXCIE0 = false; } void write(uint8 b) inline { @@ -223,6 +251,8 @@ type avr5mcu implements mcu { TWSR.TWPS = 0; TWBR = uint8(((clock() / speed) - 16) / 2); } + + void async_read_to(interrupt_i8 i) {} void enable() { return; } diff --git a/lib/avr328p.ld b/lib/atmega328p.ld similarity index 100% rename from lib/avr328p.ld rename to lib/atmega328p.ld diff --git a/lib/avr328p.rob b/lib/atmega328p.rob similarity index 54% rename from lib/avr328p.rob rename to lib/atmega328p.rob index 4778d35..46ac806 100644 --- a/lib/avr328p.rob +++ b/lib/atmega328p.rob @@ -47,42 +47,43 @@ asm " ret"; } +void irq_usart_rx() naked, weak, section __irqs { } +void irq_usart_tx() naked, weak, section __irqs { } + +void __default_irq() naked, section __irqs { + asm "jmp __default_irq"; +} + void __vectors() naked, section __isr { - /* FIXME: provide proper interrupt functions instead of __vectors - * after implementing "weak" attribute for functions - */ - + /* atmega328p has 26 interruptions */ - asm "rjmp __init"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - asm "rjmp __default_irq"; - - asm "__default_irq:"; - asm "reti"; - + asm "jmp __init"; + asm "jmp __default_irq"; // IRQ0 + asm "jmp __default_irq"; // IRQ1 + asm "jmp __default_irq"; // PCINT0 + asm "jmp __default_irq"; // PCINT1 + asm "jmp __default_irq"; // PCINT2 + asm "jmp __default_irq"; // Watchdog Timer + asm "jmp __default_irq"; // Timer2 Compare A + asm "jmp __default_irq"; // Timer2 Compare B + asm "jmp __default_irq"; // Timer2 Overflow + asm "jmp __default_irq"; // Timer1 Capture + asm "jmp __default_irq"; // Timer1 Compare A + asm "jmp __default_irq"; // Timer1 Compare B + asm "jmp __default_irq"; // Timer1 Overflow + asm "jmp __default_irq"; // Timer0 Compare A + asm "jmp __default_irq"; // Timer0 Compare B + asm "jmp __default_irq"; // Timer0 Overflow + asm "jmp __default_irq"; // SPI Transfer Complete + asm "jmp irq_usart_rx"; // USART, RX Complete + asm "jmp __default_irq"; // USART, UDR Empty + asm "jmp irq_usart_tx"; // USART, TX Complete + asm "jmp __default_irq"; // ADC Conversion + asm "jmp __default_irq"; // EEPROM Ready + asm "jmp __default_irq"; // Analog Comparator + asm "jmp __default_irq"; // 2-wire Serial Interface + asm "jmp __default_irq"; // Store Program Memory Ready + asm "__init:"; // clear r1 (zero reg) asm "clr r1"; @@ -113,4 +114,4 @@ void __vectors() naked, section __isr { asm "cli"; asm "sleep"; } - \ No newline at end of file + diff --git a/lib/avr5.ld b/lib/avr5.ld index 6e64a17..af7cb1b 100644 --- a/lib/avr5.ld +++ b/lib/avr5.ld @@ -13,6 +13,8 @@ SECTIONS KEEP(*(__isr)) . = ALIGN(2); __text_start = .; + *(__irqs) + KEEP(*(__irqs)) *(.progmem*) . = ALIGN(2); *(.text) diff --git a/lib/display/ssd1306.rob b/lib/display/ssd1306.rob index 112f72c..66bb88d 100644 --- a/lib/display/ssd1306.rob +++ b/lib/display/ssd1306.rob @@ -26,8 +26,8 @@ type ssd1306 implements display { address = 0u; framebuffer implements buffer8 { - buff = {{0u:128}:8}; changes = envelope_u16(); + buff = {{0u:128}:8}; uint16 height() inline { return buff.rows; } uint16 width() inline { return buff.cols; } @@ -194,12 +194,12 @@ type ssd1306 implements display { select.set(true); } - void reset_cursor(uint8 lx, uint8 ly, uint8 ux, uint8 uy) { + void reset_cursor(uint16 lx, uint16 ly, uint16 ux, uint16 uy) { cmds = { // set page update range - commands.SET_PAGE_ADDR, ly, uy, + commands.SET_PAGE_ADDR, int8(ly), int8(uy), // set column update range - commands.SET_COLUMN_ADDRESS, lx, ux + commands.SET_COLUMN_ADDRESS, int8(lx), int8(ux) }; write_commands(cmds); } diff --git a/lib/graphic/canvas8.rob b/lib/graphic/canvas8.rob index c641db2..dcc41e6 100644 --- a/lib/graphic/canvas8.rob +++ b/lib/graphic/canvas8.rob @@ -3,6 +3,7 @@ * Apache License v2.0. */ +use assert; use intfs.buffer8; type canvas8 { @@ -22,18 +23,16 @@ type canvas8 { void set_pixel(uint16 row, uint16 col) { rowb = row/8; - if col < buffer.width() and rowb < buffer.height() { - v = buffer.get(rowb, col); - buffer.set(rowb, col, v | (1 << uint8(row & 7))); - } + assert(col < buffer.width() and rowb < buffer.height(), "outside buffer bounds"); + v = buffer.get(rowb, col); + buffer.set(rowb, col, v | (1 << uint8(row & 7))); } void clear_pixel(uint16 row, uint16 col) { rowb = row/8; - if col < buffer.width() and rowb < buffer.height() { - v = buffer.get(rowb, col); - buffer.set(rowb, col, v & ~(1 << uint8(row & 7))); - } + assert(col < buffer.width() and rowb < buffer.height(), "outside buffer bounds"); + v = buffer.get(rowb, col); + buffer.set(rowb, col, v & ~(1 << uint8(row & 7))); } void fill_rect(uint16 x1, uint16 y1, uint16 x2, uint16 y2, bool v) { @@ -46,12 +45,14 @@ type canvas8 { bank = first_bank; while bank <= last_bank { mask = 0xFF; + y1t = uint8(y1); + y2t = uint8(y2); if first_bank == last_bank { // all bits in the same bank - mask = (mask >> ((y1 & 7) + 7 - (y2 & 7))) << (y1 & 7); + mask = (mask >> ((y1t & 7) + 7 - (y2t & 7))) << (y1t & 7); } else if bank == first_bank { - mask = (mask << (y1 & 7)); + mask = (mask << (y1t & 7)); } else if bank == last_bank { - mask = (mask >> (7 - (y2 & 7))); + mask = (mask >> (7 - (y2t & 7))); } b = x1; while b <= x2 { @@ -67,3 +68,4 @@ type canvas8 { } } } + diff --git a/lib/intfs/databus.rob b/lib/intfs/databus.rob index c1bfd78..790087a 100644 --- a/lib/intfs/databus.rob +++ b/lib/intfs/databus.rob @@ -3,6 +3,8 @@ * Apache License v2.0. */ +use interrupt; + enum databus_protocol {SPI, I2C, UART, CAN} interface databus { @@ -16,4 +18,5 @@ interface databus { bool start_transaction(uint16 addr); void end_transaction(); databus_protocol get_protocol(); + void async_read_to(interrupt_i8 i); } diff --git a/lib/intfs/interrupt.rob b/lib/intfs/interrupt.rob new file mode 100644 index 0000000..ad95b8b --- /dev/null +++ b/lib/intfs/interrupt.rob @@ -0,0 +1,20 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +interface interrupt { + void handler(); +} + +interface interrupt_i8 { + void handler(uint8 i); +} + +type void_interrupt implements interrupt { + void handler() {} +} + +type void_interrupt_i8 implements interrupt_i8 { + void handler(uint8 i) {} +} diff --git a/lib/intfs/ports.rob b/lib/intfs/ports.rob index 714ec33..5fd6e13 100644 --- a/lib/intfs/ports.rob +++ b/lib/intfs/ports.rob @@ -17,13 +17,13 @@ interface analogport { uint16 get(); } -type null_digitalport implements digitalport { +type void_digitalport implements digitalport { void mode(port_mode m) inline {} void set(bool v) inline {} bool get() inline { return false; } } -type null_analogport implements analogport { +type void_analogport implements analogport { void mode(port_mode m) inline {} void set(uint16 v) inline {} uint16 get() inline { return 0; } diff --git a/platformio/examples/blink/platformio.ini b/platformio/examples/blink/platformio.ini index a72c72a..e1b1e3e 100644 --- a/platformio/examples/blink/platformio.ini +++ b/platformio/examples/blink/platformio.ini @@ -1,7 +1,7 @@ [avr] platform = robcmp -board = avr328p +board = atmega328p upload_protocol = serial board_hardware_spec = specs/avr.spec diff --git a/platformio/examples/breakout/.gitignore b/platformio/examples/breakout/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/platformio/examples/breakout/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/platformio/examples/breakout/breakout.code-workspace b/platformio/examples/breakout/breakout.code-workspace new file mode 100644 index 0000000..8dc689c --- /dev/null +++ b/platformio/examples/breakout/breakout.code-workspace @@ -0,0 +1,11 @@ +{ + "folders": [ + { + "path": "." + }, + { + "path": "../../../lib" + } + ], + "settings": {} +} \ No newline at end of file diff --git a/platformio/examples/breakout/platformio.ini b/platformio/examples/breakout/platformio.ini new file mode 100644 index 0000000..4751d49 --- /dev/null +++ b/platformio/examples/breakout/platformio.ini @@ -0,0 +1,38 @@ + +[avr] +platform = robcmp +board = atmega328p +upload_protocol = serial +board_hardware_spec = specs/avr.spec +debug_svd_path = /Users/thborges/projects/robcmp/lib/atmega328p.svd +monitor_port = /tmp/simavr-uart0 +#monitor_port = /dev/cu.usbserial-0001 +monitor_speed = 115200 +debug_tool = robcmp-ssd1306 +#debug_tool = robcmp-led + +[env:avr-release] +extends = avr +build_type = release + +[env:avr-debug] +extends = avr +build_type = debug + + + +[stm32] +platform = robcmp +board = stm32f1 +upload_protocol = stlink +board_hardware_spec = specs/stm32.spec +monitor_speed = 9600 +monitor_port = /dev/cu.usbserial-0001 +debug_svd_path = /Users/thborges/projects/robcmp/lib/arch/stm32/stm32f103/stm32f103.svd + +[env:stm32-release] +extends = stm32 + +[env:stm32-debug] +extends = stm32 +build_type = debug diff --git a/platformio/examples/breakout/specs/avr.spec b/platformio/examples/breakout/specs/avr.spec new file mode 100644 index 0000000..689f52d --- /dev/null +++ b/platformio/examples/breakout/specs/avr.spec @@ -0,0 +1,19 @@ + +use arch.avr.avr5mcu; +use display.ssd1306; +use graphic.canvas8; + +bind avr5mcu to globals.mmcu singleton; +bind avr5mcu to ssd1306.mmcu singleton; + +bind avr5mcu.uart0 to globals.dbus_uart singleton; + +// SPI display +bind avr5mcu.b0 to ssd1306.reset singleton; +bind avr5mcu.b1 to ssd1306.datacmd singleton; +bind avr5mcu.b2 to ssd1306.select singleton; +bind avr5mcu.spi to globals.dbus_display singleton; +bind avr5mcu.spi to ssd1306.dbus singleton; + +bind ssd1306 to globals.oled singleton; +bind ssd1306.framebuffer to canvas8.buffer singleton; diff --git a/platformio/examples/breakout/specs/stm32.spec b/platformio/examples/breakout/specs/stm32.spec new file mode 100644 index 0000000..1678cfa --- /dev/null +++ b/platformio/examples/breakout/specs/stm32.spec @@ -0,0 +1,22 @@ +/* + * Injections for a SSD1306 I2C display + * and an stm32f103 mcu + */ + +use arch.stm32.stm32f1; +use display.ssd1306; +use graphic.canvas8; + +bind stm32f1 to globals.mmcu singleton; +bind stm32f1 to ssd1306.mmcu singleton; +bind stm32f1.uart2 to globals.dbus_uart singleton; + +// I2C display +bind void_digitalport to ssd1306.reset singleton; +bind void_digitalport to ssd1306.datacmd singleton; +bind void_digitalport to ssd1306.select singleton; +bind stm32f1.i2c1 to globals.dbus_display singleton; +bind stm32f1.i2c1 to ssd1306.dbus singleton; + +bind ssd1306 to globals.oled singleton; +bind ssd1306.framebuffer to canvas8.buffer singleton; diff --git a/platformio/examples/breakout/src/example.c b/platformio/examples/breakout/src/example.c new file mode 100644 index 0000000..2fefc4c --- /dev/null +++ b/platformio/examples/breakout/src/example.c @@ -0,0 +1,403 @@ +/* 2014 + * Breakout game by Ilya Titov. Find building instructions on http://webboggles.com/ + * The code that does not fall under the licenses of sources listed below can be used non commercially with attribution. + * + * If you have problems uploading this sketch, this is probably due to sketch size - you need to update ld.exe in arduino\hardware\tools\avr\avr\bin + * https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC + * + * This sketch is using the screen control and font functions written by Neven Boyanov for the http://tinusaur.wordpress.com/ project + * Source code and font files available at: https://bitbucket.org/tinusaur/ssd1306xled + * + * Sleep code is based on this blog post by Matthew Little: + * http://www.re-innovation.co.uk/web12/index.php/en/blog-75/306-sleep-modes-on-attiny85 +*/ +#include +#include "font6x8.h" +#include +#include // needed for the additional interrupt + +volatile byte player = 0; //0 to 128-platformWidth - this is the position of the bounce platform +byte platformWidth = 16; +byte ballx = 62; // coordinate of the ball +byte bally = 50; // coordinate of the ball +int vdir = -1; // vertical direction and step distance +int hdir = -1; // horizontal direction and step distance +long lastFrame = 0; // time since the screen was updated last +boolean row1[16]; // on-off array of blocks +boolean row2[16]; +boolean row3[16]; +int score = 0; // score - counts the number of blocks hit and resets the array above when devisible by 48(total blocks) +ISR(PCINT0_vect){ // PB0 pin button interrupt + if (player >0){player--;} + return; +} +void playerInc(){ // PB2 pin button interrupt + if (player <128-platformWidth){player++;} +} + +void setup() { + resetGame(); + DDRB = 0b00000010; // set PB1 as output (for the speaker) + PCMSK = 0b00000001; // pin change mask: listen to portb bit 1 + GIMSK |= 0b00100000; // enable PCINT interrupt + sei(); // enable all interrupts + attachInterrupt(0,playerInc,CHANGE); + lastFrame = millis(); +} +void loop() { + delay(40); + noInterrupts(); + ssd1306_init(); + ssd1306_fillscreen(0x00); + ssd1306_char_f6x8(16, 4, "B R E A K O U T"); + ssd1306_char_f6x8(20, 6, "webboggles.com"); + beep(200,600); beep(300,200); beep(400,300); + delay(2000); + while (1==1) { + // continue moving after the interrupt + if (digitalRead(2)==1){if (player <128-platformWidth){player++;} if (player <128-platformWidth){player++;} if (player <128-platformWidth){player++;}} if (digitalRead(0)==1){if (player >0){player--;} if (player >0){player--;} if (player >0){player--;}} + + // bounce off the sides of the screen + if ((bally+vdir<54&&vdir==1)||(bally-vdir>1&&vdir==-1)){bally+=vdir;}else {vdir = vdir*-1;} + if ((ballx+hdir<127&&hdir==1)||(ballx-hdir>1&&hdir==-1)){ballx+=hdir;}else {hdir = hdir*-1;} + + // frame actions + if (lastFrame+1010&&bally+vdir>=54&&(ballxplayer+platformWidth)){ // game over if the ball misses the platform + int topScore = EEPROM.read(0); + topScore = topScore << 8; topScore = topScore | EEPROM.read(1); if (score>topScore){topScore = score; EEPROM.write(1,topScore & 0xFF); EEPROM.write(0,(topScore>>8) & 0xFF); } + ssd1306_fillscreen(0x00); + ssd1306_char_f6x8(32, 3, "Game Over"); + ssd1306_char_f6x8(32, 5, "score:"); + char temp[4] = {0,0,0,0}; + itoa(score,temp,10); + ssd1306_char_f6x8(70, 5, temp); + ssd1306_char_f6x8(32, 6, "top score:"); + itoa(topScore,temp,10); + ssd1306_char_f6x8(90, 6, temp); + for (int i = 0; i<1000; i++){ + beep(1,random(0,i*2)); + } + delay(1000); + system_sleep(); + resetGame(); + }else if (ballx10&&bally+vdir>=54){ // if the ball hits left of the platform bounce left + hdir=-1; beep(20,600); + }else if (ballx>player+platformWidth/2&&bally>10&&bally+vdir>=54){ // if the ball hits right of the platform bounce right + hdir=1; beep(20,600); + }else if (bally+vdir>=54){ + hdir=1; beep(20,600); + } + + collisionCheck: // go back to here if a collision was detected to prevent flying through a rigid + if (floor((bally+vdir)/8)==2){ + if (row3[ballx/8]==1){row3[ballx/8]=0; score++; + collision(); goto collisionCheck; // check collision for the new direction to prevent flying through a rigid + } + }else if (floor((bally+vdir)/8)==1){ + if (row2[ballx/8]==1){row2[ballx/8]=0; score++; + collision(); goto collisionCheck; + } + }else if (floor((bally+vdir)/8)==0){ + if (row1[ballx/8]==1){row1[ballx/8]=0; score++; + collision(); goto collisionCheck; + } + } + + // reset blocks if all have been hit + if (score%48==0){ + for (byte i =0; i<16;i++){ + row1[i]=1; row2[i]=1; row3[i]=1; + } + } + } + + // update whats on the screen + noInterrupts(); + + // blocks + ssd1306_setpos(0,0); + ssd1306_send_data_start(); + for (int bl = 0; bl <16; bl++){ + if(row1[bl]==1){ + sendBlock(1); + }else { + sendBlock(0); + } + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,1); + ssd1306_send_data_start(); + for (int bl = 0; bl <16; bl++){ + if(row2[bl]==1){ + sendBlock(1); + }else { + sendBlock(0); + } + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,2); + ssd1306_send_data_start(); + for (int bl = 0; bl <16; bl++){ + if(row3[bl]==1){ + sendBlock(1); + }else { + sendBlock(0); + } + } + ssd1306_send_data_stop(); + + // clear area below the blocks + ssd1306_setpos(0,3); + ssd1306_send_data_start(); + for (byte i =0; i<128; i++){ + ssd1306_send_byte(B00000000); + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,4); + ssd1306_send_data_start(); + for (byte i =0; i<128; i++){ + ssd1306_send_byte(B00000000); + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,5); + ssd1306_send_data_start(); + for (byte i =0; i<128; i++){ + ssd1306_send_byte(B00000000); + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,6); + ssd1306_send_data_start(); + for (byte i =0; i<128; i++){ + ssd1306_send_byte(B00000000); + } + ssd1306_send_data_stop(); + ssd1306_setpos(0,7); + ssd1306_send_data_start(); + for (byte i =0; i<128; i++){ + ssd1306_send_byte(B00000000); + } + ssd1306_send_data_stop(); + + // draw ball + ssd1306_setpos(ballx,bally/8); + uint8_t temp = B00000001; + ssd1306_send_data_start(); + temp = temp << bally%8+1; + ssd1306_send_byte(temp); + ssd1306_send_data_stop(); + + drawPlatform(); + interrupts(); + // + + } +} +void resetGame(){ + ssd1306_char_f6x8(16, 4, "B R E A K O U T"); + ssd1306_char_f6x8(20, 6, "webboggles.com"); + beep(200,600); beep(300,200); beep(400,300); + delay(2000); + for (byte i =0; i<16;i++){ // reset blocks + row1[i]=1; row2[i]=1; row3[i]=1; + } + platformWidth = 16; + ballx = 64; + bally = 50; + hdir = -1; + vdir = -1; + score = 0; + player = random(0,128-platformWidth); + ballx = player+platformWidth/2; +} + +void collision(){ // the collsision check is actually done befor this is called, this code works out where the ball will bounce + if ((bally+vdir)%8==7&&(ballx+hdir)%8==7){ // bottom right corner + if (vdir==1){hdir=1;}else if(vdir==-1&&hdir==1){vdir=1;}else {hdir=1;vdir=1;} + }else if ((bally+vdir)%8==7&&(ballx+hdir)%8==0){ // bottom left corner + if (vdir==1){hdir=-1;}else if(vdir==-1&&hdir==-1){vdir=1;}else {hdir=-1;vdir=1;} + }else if ((bally+vdir)%8==0&&(ballx+hdir)%8==0){ // top left corner + if (vdir==-1){hdir=-1;}else if(vdir==1&&hdir==-1){vdir=-1;}else {hdir=-1;vdir=-1;} + }else if ((bally+vdir)%8==0&&(ballx+hdir)%8==7){ // top right corner + if (vdir==-1){hdir=1;}else if(vdir==1&&hdir==1){vdir=-1;}else {hdir=1;vdir=-1;} + }else if ((bally+vdir)%8==7){ // bottom side + vdir = 1; + }else if ((bally+vdir)%8==0){ // top side + vdir = -1; + }else if ((ballx+hdir)%8==7){ // right side + hdir = 1; + }else if ((ballx+hdir)%8==0){ // left side + hdir = -1; + }else { + hdir = hdir*-1; vdir = vdir*-1; + } + + beep(30,300); + +} +void drawPlatform(){ + noInterrupts(); + ssd1306_setpos(player,7); + ssd1306_send_data_start(); + for (byte pw = 1; pw >4)|0x10); // |0x10 + ssd1306_send_byte((x&0x0f)|0x01); // |0x01 + + ssd1306_xfer_stop(); +} + +void ssd1306_fillscreen(uint8_t fill_Data){ + uint8_t m,n; + for(m=0;m<8;m++) + { + ssd1306_send_command(0xb0+m); //page0-page1 + ssd1306_send_command(0x00); //low column start address + ssd1306_send_command(0x10); //high column start address + ssd1306_send_data_start(); + for(n=0;n<128;n++) { ssd1306_send_byte(fill_Data); } ssd1306_send_data_stop(); } } void ssd1306_char_f6x8(uint8_t x, uint8_t y, const char ch[]){ uint8_t c,i,j=0; while(ch[j] != '\0') { c = ch[j] - 32; if(x>126) + { + x=0; + y++; + } + ssd1306_setpos(x,y); + ssd1306_send_data_start(); + for(i=0;i<6;i++) + { + ssd1306_send_byte(pgm_read_byte(&ssd1306xled_font6x8[c*6+i])); + } + ssd1306_send_data_stop(); + x += 6; + j++; + } +} + +// Routines to set and clear bits (used in the sleep code) +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +void system_sleep() { + ssd1306_fillscreen(0x00); + ssd1306_send_command(0xAE); + cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF + set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here + sleep_enable(); + sleep_mode(); // System actually sleeps here + sleep_disable(); // System continues execution here when watchdog timed out + sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON + ssd1306_send_command(0xAF); +} \ No newline at end of file diff --git a/platformio/examples/breakout/src/game.rob b/platformio/examples/breakout/src/game.rob new file mode 100644 index 0000000..caeb387 --- /dev/null +++ b/platformio/examples/breakout/src/game.rob @@ -0,0 +1,241 @@ +/* + * Robcmp examples: Breakout game on a SSD1306 display + */ + +use math.random16; +use graphic.canvas8; +use math.abs; +use intfs.mcu; +use intfs.display; + + +type game { + + // Bar related vars + bar_middle = 0u; + bar_width = 30u; + bar_next_move = 0; + + // Ball related vars + ball_dir_x = 1; + ball_dir_y = 1; + ball_pos_x = 0u; + ball_pos_y = 0u; + + // Game status + paused = false; + gameover = false; + level = 0; + rem_blocks = 0u; + + // Blocks const and vars + start_y = 0u; + const bottom_margin = 4; + + /* The size and position of game elements + blocks = 129/(width+1) + use block width = 5, 21 blocks */ + const block_size = 4; + const block_sizesp = 4+1; + const right_margin = 25 * block_sizesp - 1; + blocks = {{true:25}:5}; + + void move_bar(canvas8 canvas) { + if bar_next_move == 0 { + return; + } + pixels = bar_next_move; + bar_next_move = 0; + + left_limit = bar_width/2 - 1; + right_limit = right_margin - bar_width/2; + + if bar_middle + pixels < left_limit { + pixels = left_limit - bar_middle + 1; + } else if bar_middle + pixels > right_limit { + pixels = right_limit - bar_middle; + } + + if pixels == 0 { + return; + } + + move = abs8(pixels); + bar_middle += pixels; + start = bar_middle - bar_width/2; + end = start + bar_width - 1; + set = pixels > 0; + if pixels < 0 { + canvas.fill_rect(start, bottom_margin-4, start+move-1, bottom_margin-2, true); + canvas.fill_rect(end+1, bottom_margin-4, end+move, bottom_margin-2, false); + } else { + canvas.fill_rect(start-move, bottom_margin-4, start-1, bottom_margin-2, false); + canvas.fill_rect(end-move+1, bottom_margin-4, end, bottom_margin-2, true); + } + + if paused { + // when paused, set ball direction according + // to the first movement + if pixels > 0 { + ball_dir_x = 1; + } else { + ball_dir_x = -1; + } + } + } + + void update_block(canvas8 canvas, uint8 row, uint8 col) { + c = col * (block_size+1); + r = start_y + row * (block_size+1); + status = blocks[row][col]; + canvas.fill_rect(c, r, c+block_size-1, r+block_size-1, status); + } + + void draw_blocks(canvas8 canvas, display oled, mcu mmcu) { + // update blocks according to the level + if level > 1 { + i = 0u; + while i < level*10 { + arow = random16() % blocks.rows; + acol = random16() % blocks.cols; + blocks[arow][acol] = true; + i++; + } + } + + // draw blocks + row = 0u; + while row < blocks.rows { + col = 0u; + while col < blocks.cols { + if level > 1 { + v = !blocks[row][col]; + blocks[row][col] = v; + } + update_block(canvas, row, col); + if blocks[row][col] { + rem_blocks++; + } + col++; + } + row++; + mmcu.wait_ms(100); // animation effect + oled.update_frame(); + } + oled.update_frame(); + } + + void init_level(canvas8 canvas, display oled, mcu mmcu) { + start_y = canvas.height() - blocks.rows * block_sizesp; + + draw_blocks(canvas, oled, mmcu); + + // hide current bar + start = bar_middle - bar_width/2; + canvas.fill_rect(start, bottom_margin-4, start + bar_width-1, bottom_margin-2, false); + bar_width = 30 - level; + if bar_width < 10 { + bar_width = 10; + } + // draw new bar + bar_middle = uint8(right_margin/2); + start = bar_middle - bar_width/2; + canvas.fill_rect(start, bottom_margin-4, start + bar_width-1, bottom_margin-2, true); + + // set ball initial pos + ball_dir_x = 1; + ball_dir_y = 1; + ball_pos_x = bar_middle; + ball_pos_y = bottom_margin; + canvas.fill_rect(ball_pos_x - 1, ball_pos_y - 1, ball_pos_x, ball_pos_y, true); + } + + void move_ball(canvas8 canvas) { + canvas.fill_rect(ball_pos_x - 1, ball_pos_y - 1, ball_pos_x, ball_pos_y, false); + + // ball_pos_{x,y} represents the top right pixel of the ball + + if ball_pos_y >= start_y - 1 { + ball_edge_x = ball_pos_x; + if ball_dir_x == -1 { + ball_edge_x--; + } + bcol = ball_edge_x / block_sizesp; + + brow = (ball_pos_y + 1 - start_y) / block_sizesp; + if ball_dir_y == -1 { + brow = (ball_pos_y - start_y) / block_sizesp; + } + + if (brow < blocks.rows and + bcol < blocks.cols and + blocks[brow][bcol]) { + + blocks[brow][bcol] = false; + rem_blocks--; + update_block(canvas, brow, bcol); + + hit_y = (ball_pos_y + 1 - start_y) % block_sizesp == 0; + hit_x = ball_pos_x % block_sizesp == 0; + + if hit_y { + ball_dir_y *= -1; + } else if hit_x { + ball_dir_x *= -1; + } + } + } + + if (ball_dir_x == -1 and ball_pos_x - 1 == 0) or // hit left margin + (ball_dir_x == 1 and ball_pos_x + 1 == right_margin) { // hit right margin + ball_dir_x *= -1; + } + + if ball_dir_y == 1 and ball_pos_y == canvas.height() - 1 { + // hit top + ball_dir_y *= -1; + + } else if ball_dir_y == -1 and ball_pos_y - 1 == bottom_margin { + // hit bottom + ball_dir_y *= -1; + mwidth = bar_width/2; + if ball_pos_x < bar_middle - mwidth or + ball_pos_x > bar_middle + mwidth { + //gameover = true; + } + } + + ball_pos_x += ball_dir_x; + ball_pos_y += ball_dir_y; + + if rem_blocks > 0 { + canvas.fill_rect(ball_pos_x - 1, ball_pos_y - 1, ball_pos_x, ball_pos_y, true); + } + } + + void check_level_done(canvas8 canvas, display oled, mcu mmcu) { + if rem_blocks == 0 { + //set_level_debug(); + level = (level+1) % 30; + init_level(canvas, oled, mmcu); + //paused = true; + } + } + + key_press implements interrupt_i8 { + void handler(uint8 key) { + if gameover { + gameover = false; + level = 0; + } else { + if key == 'C' {// right + bar_next_move += 10; + } else if key == 'D' { + bar_next_move -= 10; + } + } + paused = false; + } + } + +} diff --git a/platformio/examples/breakout/src/main.rob b/platformio/examples/breakout/src/main.rob new file mode 100644 index 0000000..bf966c0 --- /dev/null +++ b/platformio/examples/breakout/src/main.rob @@ -0,0 +1,68 @@ +/* + * Robcmp examples: Breakout game on a SSD1306 display + */ + +use intfs.ports; +use intfs.mcu; +use intfs.display; +use intfs.databus; + +use graphic.canvas8; +use game; + +type globals { + mmcu = mcu(); + oled = display(); + dbus_display = databus(); + dbus_uart = databus(); +} + +void setup_hardware(globals gg) { + // dbus_serial setup + dbus_uart = gg.dbus_uart; + dbus_uart.setup(115200); + dbus_uart.enable(); + dbus_uart.write_array("Robcmp Breakout Game for SSD1306 肖\n"); + dbus_uart.write_array("Use left/right arrows to move and space to pause.\n"); + + // dbus_display setup + dbus_display = gg.dbus_display; + dbus_display.setup(0); + dbus_display.enable(); + + // init display + oled = gg.oled; + oled.set_address(0x78); + oled.init_display(); + //oled.clear(); + + // enable interruptions + mmcu = gg.mmcu; + mmcu.set_interruptions(true); +} + +int8 main() { + gg = globals(); + setup_hardware(gg); + + dbus_uart = gg.dbus_uart; + mmcu = gg.mmcu; + oled = gg.oled; + + gm = game(); + k = gm.key_press; + dbus_uart.async_read_to(k); + canvas = canvas8(); + + loop { + gm.move_bar(canvas); + + if !gm.paused and !gm.gameover { + mmcu.wait_ms(20); + gm.move_ball(canvas); + } + + gm.check_level_done(canvas, oled, mmcu); + oled.update_frame(); + } +} diff --git a/platformio/examples/old/avr328p-blink/platformio.ini b/platformio/examples/old/avr328p-blink/platformio.ini index b75fd8c..e306673 100644 --- a/platformio/examples/old/avr328p-blink/platformio.ini +++ b/platformio/examples/old/avr328p-blink/platformio.ini @@ -1,7 +1,7 @@ [env] platform = robcmp -board = avr328p +board = atmega328p upload_protocol = serial [env:release] diff --git a/platformio/examples/old/avr328p-ssd1306/genll.sh b/platformio/examples/old/avr328p-ssd1306/genll.sh deleted file mode 100755 index c217ae9..0000000 --- a/platformio/examples/old/avr328p-ssd1306/genll.sh +++ /dev/null @@ -1,11 +0,0 @@ -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ /Users/thborges/.platformio/packages/toolchain-robcmp/lib/avr328p.rob > lls/avr328p.rob.ll -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/main.rob > lls/main.rob.ll -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/avr/avr5mcu.rob > lls/avr5mcu.rob.ll -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/avr/avr5regs.rob > lls/avr5regs.rob.ll -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/display/ssd1306.rob > lls/ssd1306.rob.ll -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/buffer8.rob > lls/buffer8.rob.ll -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/canvas8.rob > lls/canvas8.rob.ll -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/databus.rob > lls/databus.rob.ll -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/display.rob > lls/display.rob.ll -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/mcu.rob > lls/mcu.rob.ll -./robcmp -a avr328p -O0 -I /Users/thborges/projects/robcmp/platformio/examples/avr328p-ssd1306/src/ src/lib/ports.rob > lls/ports.rob.ll diff --git a/platformio/examples/old/avr328p-ssd1306/platformio.ini b/platformio/examples/old/avr328p-ssd1306/platformio.ini index 9b03d1f..2d81cd4 100644 --- a/platformio/examples/old/avr328p-ssd1306/platformio.ini +++ b/platformio/examples/old/avr328p-ssd1306/platformio.ini @@ -1,29 +1,29 @@ -[avr328p] +[atmega328p] platform = robcmp -board = avr328p +board = atmega328p upload_protocol = serial -[env:avr328p_release_spi] -extends = avr328p +[env:atmega328p_release_spi] +extends = atmega328p build_type = release debug_tool = robcmp-ssd1306 board_hardware_spec = specs/avr-spi.spec -[env:avr328p_release_i2c] -extends = avr328p +[env:atmega328p_release_i2c] +extends = atmega328p build_type = release debug_tool = robcmp-led board_hardware_spec = specs/avr-i2c.spec -[env:avr328p_debug_spi] -extends = avr328p +[env:atmega328p_debug_spi] +extends = atmega328p build_type = debug debug_tool = robcmp-ssd1306 board_hardware_spec = specs/avr-spi.spec -[env:avr328p_debug_i2c] -extends = avr328p +[env:atmega328p_debug_i2c] +extends = atmega328p build_type = debug debug_tool = robcmp-led board_hardware_spec = specs/avr-i2c.spec diff --git a/platformio/examples/ssd1306/platformio.ini b/platformio/examples/ssd1306/platformio.ini index a72c72a..79e06f0 100644 --- a/platformio/examples/ssd1306/platformio.ini +++ b/platformio/examples/ssd1306/platformio.ini @@ -1,7 +1,7 @@ [avr] platform = robcmp -board = avr328p +board = atmega328p upload_protocol = serial board_hardware_spec = specs/avr.spec @@ -12,7 +12,7 @@ build_type = release [env:avr-debug] extends = avr build_type = debug -debug_tool = robcmp-led +debug_tool = robcmp-ssd1306 diff --git a/platformio/examples/ssd1306/specs/avr.spec b/platformio/examples/ssd1306/specs/avr.spec index 0f00502..c7a9c79 100644 --- a/platformio/examples/ssd1306/specs/avr.spec +++ b/platformio/examples/ssd1306/specs/avr.spec @@ -1,4 +1,23 @@ - +/* + * Injections for a SSD1306 I2C display + * and an atmega328p mcu + */ + use arch.avr.avr5mcu; use display.ssd1306; -use graphics.canvas; +use graphic.canvas8; + +bind avr5mcu to globals.mmcu singleton; +bind avr5mcu to ssd1306.mmcu singleton; +bind avr5mcu.b5 to globals.led singleton; + +// SPI display +bind avr5mcu.b0 to ssd1306.reset singleton; +bind avr5mcu.b1 to ssd1306.datacmd singleton; +bind avr5mcu.b2 to ssd1306.select singleton; +bind avr5mcu.spi to globals.dbus singleton; +bind avr5mcu.spi to ssd1306.dbus singleton; + +bind ssd1306 to globals.oled singleton; +bind ssd1306.framebuffer to canvas8.buffer singleton; + \ No newline at end of file diff --git a/platformio/install b/platformio/install index b513448..6162cd1 100755 --- a/platformio/install +++ b/platformio/install @@ -8,5 +8,5 @@ cp -r platform/* ~/.platformio/platforms/robcmp cp -r toolchain-robcmp ~/.platformio/packages/ code --install-extension vscode-syntax/robcmpsyntax-0.0.1.vsix echo "Open the examples folder and try to build and upload!" -echo " code examples/avr328p-blink" +echo " code examples/atmega328p-blink" echo " code examples/stm32f1" diff --git a/platformio/platform/boards/avr328p.json b/platformio/platform/boards/atmega328p.json similarity index 100% rename from platformio/platform/boards/avr328p.json rename to platformio/platform/boards/atmega328p.json diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index cde47b4..0fa0440 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -40,30 +40,28 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 hardware_spec = None pass -#ldflags = ["-nostdlib", "-entry=main", "-L", stdlib_folder, "-Bstatic"] ldflags = ["-nostdlib", "-L", stdlib_folder, "-Bstatic"] +ldflags.append("--gc-sections") +ldflags.append("--lto=thin") + if mcu.startswith("stm32f1"): ldflags.append("-Tstm32f1.ld") auxsources += Glob(join(stdlib_folder, "stm32f1.rob")) elif mcu == "atmega328p": - ldflags.append("-Tavr328p.ld") + ldflags.append("-Tatmega328p.ld") ldflags.append(join(stdlib_folder, "avr5.o")) - auxsources += Glob(join(stdlib_folder, "avr328p.rob")) + auxsources += Glob(join(stdlib_folder, "atmega328p.rob")) else: sys.stderr.write("The requested mcu is not supported.\n") env.Exit(1) -ldflags.append("--gc-sections") -ldflags.append("--lto=thin") - -build_type = env.subst("$BUILD_TYPE") +build_type = env.GetProjectOption("build_type") robcmp_args = ["robcmp", "-a", board, "-o", "$TARGET"] if build_type == "debug": robcmp_args.append("-g") - robcmp_args.append("-O0") + robcmp_args.append("-O1") elif build_type == "release": - #robcmp_args.append("-g") robcmp_args.append("-Oz") hardware_spec_args = [] @@ -74,8 +72,7 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 robcmp_args.append(stdlib_folder) robcmp_args.append("$SOURCE") -if board.startswith("avr"): - print("Will use avr-gdb from robcmp") +if board.startswith("atmega") or board.startswith("attiny"): avr_gdb = join(platform.get_package_dir("toolchain-robcmp"), "bin", "avr-gdb") env.Replace( GDB=avr_gdb @@ -88,8 +85,7 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 suffix=".bin" ), Linker=Builder( - action = ' '.join(["ld.lld", "$SOURCES", ' '.join(ldflags), "-o", "$TARGET"]), - #action = ' '.join(["avr-ld", "$SOURCES", ' '.join(ldflags), "-o", "$TARGET"]), + action = ' '.join(["ld.lld", ' '.join(ldflags), "$SOURCES", "-o", "$TARGET"]), suffix=".elf" ), Rob=Builder( @@ -171,7 +167,7 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 upload_actions.append(env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")) upload = None -if mcu.startswith("stm32f1"): +if mcu.startswith("stm32"): upload = env.Alias(["upload"], target_elf, upload_actions) else: upload = env.Alias(["upload"], target_bin, upload_actions) diff --git a/platformio/platform/platform.py b/platformio/platform/platform.py index 08d3b5e..67789d7 100644 --- a/platformio/platform/platform.py +++ b/platformio/platform/platform.py @@ -13,12 +13,12 @@ def configure_default_packages(self, variables, targets): required_tool = None if upload_protocol == "serial": - if board == "avr328p": + if board.startswith("atmega") or board.startswith("attiny"): required_tool = "tool-avrdude" - elif board.startswith("stm32f1"): + elif board.startswith("stm32"): required_tool = "tool-stm32duino" elif upload_protocol == "stlink": - if board.startswith("stm32f1"): + if board.startswith("stm32"): required_tool = "tool-openocd" if required_tool: diff --git a/test/avr328p/Makefile b/test/atmega328p/Makefile similarity index 53% rename from test/avr328p/Makefile rename to test/atmega328p/Makefile index 6c5bb5d..f171d3d 100644 --- a/test/avr328p/Makefile +++ b/test/atmega328p/Makefile @@ -1,7 +1,7 @@ ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) -ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/avr328p.o +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/atmega328p.o ROBCMP=../../build/robcmp INCLUDES=-I ../../lib @@ -11,31 +11,31 @@ ifndef OPT OPT=-Oz endif -LD_FLAGS=-nostdlib -entry=main -L../../lib -Tavr328p.ld ../../lib/avr5.o +LD_FLAGS=-nostdlib -entry=main -L../../lib -Tatmega328p.ld ../../lib/avr5.o LD_FLAGS+=-Bstatic LD_FLAGS+=--gc-sections LD_FLAGS+=--lto=thin DEPENDS=${ROBCMP} Makefile -LINK_DEPENDS=out/avr328p.o +LINK_DEPENDS=out/atmega328p.o all: out test out: mkdir -p out -out/avr328p.o : ../../lib/avr328p.rob ${DEPENDS} - ${ROBCMP} -a avr328p ${OPT} -o $@ $< +out/atmega328p.o : ../../lib/atmega328p.rob ${DEPENDS} + ${ROBCMP} -a atmega328p ${OPT} -o $@ $< -out/avr328p.ll : ../../lib/avr328p.rob ${DEPENDS} - ${ROBCMP} -a avr328p ${OPT} $< > $@ +out/atmega328p.ll : ../../lib/atmega328p.rob ${DEPENDS} + ${ROBCMP} -a atmega328p ${OPT} $< > $@ .SECONDARY: -out/%.o : %.rob out/avr328p.o ${DEPENDS} - ${ROBCMP} -bdep -a avr328p ${OPT} ${INCLUDES} -o $@ $< +out/%.o : %.rob out/atmega328p.o ${DEPENDS} + ${ROBCMP} -bdep -a atmega328p ${OPT} ${INCLUDES} -o $@ $< out/%.ll : %.rob ${DEPENDS} - ${ROBCMP} -bdep -a avr328p ${OPT} ${INCLUDES} $< > $@ + ${ROBCMP} -bdep -a atmega328p ${OPT} ${INCLUDES} $< > $@ %.tt : %.rob ${DEPENDS} @-./runtest.sh $< $(patsubst %.rob,out/%,$<) diff --git a/test/avr328p/bitstruct-field-i5.rob b/test/atmega328p/bitstruct-field-i5.rob similarity index 100% rename from test/avr328p/bitstruct-field-i5.rob rename to test/atmega328p/bitstruct-field-i5.rob diff --git a/test/avr328p/bsscheck.rob b/test/atmega328p/bsscheck.rob similarity index 100% rename from test/avr328p/bsscheck.rob rename to test/atmega328p/bsscheck.rob diff --git a/test/avr328p/bssinjcheck.rob b/test/atmega328p/bssinjcheck.rob similarity index 100% rename from test/avr328p/bssinjcheck.rob rename to test/atmega328p/bssinjcheck.rob diff --git a/test/avr328p/datacheck.rob b/test/atmega328p/datacheck.rob similarity index 100% rename from test/avr328p/datacheck.rob rename to test/atmega328p/datacheck.rob diff --git a/test/avr328p/globaldata.rob b/test/atmega328p/globaldata.rob similarity index 100% rename from test/avr328p/globaldata.rob rename to test/atmega328p/globaldata.rob diff --git a/test/avr328p/globals.rob b/test/atmega328p/globals.rob similarity index 100% rename from test/avr328p/globals.rob rename to test/atmega328p/globals.rob diff --git a/test/avr328p/itoa.rob b/test/atmega328p/itoa.rob similarity index 100% rename from test/avr328p/itoa.rob rename to test/atmega328p/itoa.rob diff --git a/test/avr328p/memcpycheck.rob b/test/atmega328p/memcpycheck.rob similarity index 100% rename from test/avr328p/memcpycheck.rob rename to test/atmega328p/memcpycheck.rob diff --git a/test/avr328p/robcmp-simavr-debug b/test/atmega328p/robcmp-simavr-debug similarity index 100% rename from test/avr328p/robcmp-simavr-debug rename to test/atmega328p/robcmp-simavr-debug diff --git a/test/avr328p/runtest.sh b/test/atmega328p/runtest.sh similarity index 100% rename from test/avr328p/runtest.sh rename to test/atmega328p/runtest.sh diff --git a/test/avr328p/runtrace.sh b/test/atmega328p/runtrace.sh similarity index 100% rename from test/avr328p/runtrace.sh rename to test/atmega328p/runtrace.sh diff --git a/test/avr328p/uart.rob b/test/atmega328p/uart.rob similarity index 100% rename from test/avr328p/uart.rob rename to test/atmega328p/uart.rob diff --git a/test/avr328p/uartdata.rob b/test/atmega328p/uartdata.rob similarity index 100% rename from test/avr328p/uartdata.rob rename to test/atmega328p/uartdata.rob diff --git a/test/avr328p/run_avr b/test/avr328p/run_avr deleted file mode 120000 index 1dc1d13..0000000 --- a/test/avr328p/run_avr +++ /dev/null @@ -1 +0,0 @@ -../../platformio/toolchain-robcmp/bin/run_avr \ No newline at end of file diff --git a/test/debug/platformio.ini b/test/debug/platformio.ini index ced8e26..8c41415 100644 --- a/test/debug/platformio.ini +++ b/test/debug/platformio.ini @@ -1,7 +1,7 @@ [env] platform = robcmp -board = avr328p +board = atmega328p upload_protocol = serial [env:release] diff --git a/test/general/bsscheck.rob b/test/general/bsscheck.rob index 845fac6..3fe20d6 120000 --- a/test/general/bsscheck.rob +++ b/test/general/bsscheck.rob @@ -1 +1 @@ -../avr328p/bsscheck.rob \ No newline at end of file +../atmega328p/bsscheck.rob \ No newline at end of file diff --git a/test/general/bssinjcheck.rob b/test/general/bssinjcheck.rob index 924abb9..18ae991 120000 --- a/test/general/bssinjcheck.rob +++ b/test/general/bssinjcheck.rob @@ -1 +1 @@ -../avr328p/bssinjcheck.rob \ No newline at end of file +../atmega328p/bssinjcheck.rob \ No newline at end of file diff --git a/test/general/global-pointer.rob b/test/general/global-pointer.rob new file mode 100644 index 0000000..0cf364f --- /dev/null +++ b/test/general/global-pointer.rob @@ -0,0 +1,56 @@ + +/* + * Test case for global pointers to interfaces + */ + +use intfs.interrupt; + +myint = interrupt_i8(); + +// myint defaults to void_interrupt_i8 +bind void_interrupt_i8 to myint singleton; + +value = 0xff; + +void call_handler() { + myint.handler(0); +} + +type custom_handler implements interrupt_i8 { + void handler(uint8 byte) { + value = byte; + } +} + +void set_interface(interrupt_i8 i) { + a = i; + myint = a; +} + +int8 main() { + ch = custom_handler(); + vo = void_interrupt_i8(); + + // direct set + a = ch; + myint = a; + call_handler(); + if value != 0 { + return 1; + } + + // direct set is working, restore + // defaults before the next test + value = 0xff; + myint = vo; + + // set through function call + set_interface(ch); + call_handler(); + if value != 0 { + return 2; + } + + return value; +} + diff --git a/test/general/memcpycheck.rob b/test/general/memcpycheck.rob index bd74754..4d0b1d5 120000 --- a/test/general/memcpycheck.rob +++ b/test/general/memcpycheck.rob @@ -1 +1 @@ -../avr328p/memcpycheck.rob \ No newline at end of file +../atmega328p/memcpycheck.rob \ No newline at end of file diff --git a/test/general/phior.rob b/test/general/phior.rob new file mode 100644 index 0000000..a903cd6 --- /dev/null +++ b/test/general/phior.rob @@ -0,0 +1,22 @@ + +void func(bool x) { +} + +int8 main() { + a = true; + b = false; + c = true; + d = a or b and c; + e = a and b or c; + + func(e and d and e); + + while a and b and c; + + if (a and b and c) { + return 1; + } + + return 0; +} + From b55cb6a0615a4b470e9e45f214a7abe992fa85ff Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 5 Sep 2024 10:47:58 -0300 Subject: [PATCH 084/117] Missing changes on string constants and avr328p to atmega328p renaming. --- CMakeLists.txt | 3 ++- lib/Makefile | 3 ++- lib/atmega328p.rob | 37 ++++++++++++++++++++++++++++++++++--- lib/avr5.S | 4 ++-- lib/convert/itoa.rob | 10 ++++------ lib/math/abs.rob | 12 ++++++++++++ rob.vim | 1 + src/BackLLVM.cpp | 8 +++++++- src/BackLLVM.h | 17 ++++++++++++++++- src/StringConst.cpp | 17 +++++++++++++++-- src/StringConst.h | 1 + 11 files changed, 96 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e72bfe3..8f97c7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,9 @@ cmake_minimum_required(VERSION 3.20.0) cmake_policy(SET CMP0054 NEW) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE) set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -fno-exceptions") -set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -flto -fno-exceptions") +set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -fno-exceptions") add_compile_definitions() project(robcmp) diff --git a/lib/Makefile b/lib/Makefile index 3ace01d..a2a586d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -5,7 +5,8 @@ all: ${GEN} avr5.o: avr5.S @#here we are interested in the fastest possible code, intead of size - avr-gcc -mmcu=avr5 -O3 -c $< + @#avr-gcc -mmcu=avr5 -O3 -c $< + clang --target=avr -mmcu=avr5 -O3 -c $< clean: rm -f ${GEN} diff --git a/lib/atmega328p.rob b/lib/atmega328p.rob index 46ac806..eb3cc60 100644 --- a/lib/atmega328p.rob +++ b/lib/atmega328p.rob @@ -47,8 +47,39 @@ asm " ret"; } -void irq_usart_rx() naked, weak, section __irqs { } -void irq_usart_tx() naked, weak, section __irqs { } +/* Weak definitions for supported interruptions + */ + void irq_usart_rx() naked, weak, section __irqs { } + void irq_usart_tx() naked, weak, section __irqs { } + +/* Timer0 is used to provide milliseconds time readings + */ + const fcpu = 16E6; + const cycles_per_us = fcpu / 1E6; + const usec_per_ovf = (64 * 256) / cycles_per_us; + const millis_per_ovf = usec_per_ovf / 1000; + const millis_frac_per_ovf = uint16(usec_per_ovf % 1000); + timer0_millis = uint32(0); + timer0_fract = uint16(0); + + void irq_timer0_ovf() signal, weak, section __irqs { + timer0_millis += millis_per_ovf; + timer0_fract += millis_frac_per_ovf; + if (timer0_fract > 1000) { + timer0_fract -= 1000; + timer0_millis += 1; + } + } + + register int8 SREG at 0x5f; + + uint32 millis() { + sreg_bkp = SREG; + asm "cli"; + result = timer0_millis; + SREG = sreg_bkp; + return result; + } void __default_irq() naked, section __irqs { asm "jmp __default_irq"; @@ -73,7 +104,7 @@ void __vectors() naked, section __isr { asm "jmp __default_irq"; // Timer1 Overflow asm "jmp __default_irq"; // Timer0 Compare A asm "jmp __default_irq"; // Timer0 Compare B - asm "jmp __default_irq"; // Timer0 Overflow + asm "jmp irq_timer0_ovf"; // Timer0 Overflow asm "jmp __default_irq"; // SPI Transfer Complete asm "jmp irq_usart_rx"; // USART, RX Complete asm "jmp __default_irq"; // USART, UDR Empty diff --git a/lib/avr5.S b/lib/avr5.S index b456ae0..2e1e9d5 100644 --- a/lib/avr5.S +++ b/lib/avr5.S @@ -23,14 +23,14 @@ .macro DEFUN name .global \name -.func \name +#.func \name \name: .endm .macro ENDF name .size \name, .-\name -.endfunc +#.endfunc .endm .macro mov_l r_dest, r_src diff --git a/lib/convert/itoa.rob b/lib/convert/itoa.rob index a72824f..6ea4a9a 100644 --- a/lib/convert/itoa.rob +++ b/lib/convert/itoa.rob @@ -3,7 +3,9 @@ * Apache License v2.0. */ -const itoa_chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; +use math.abs; + +const itoa_chars = "0123456789abcdef"; void itoa(int16 value, int8 base, char[] result) { if base < 2 or base > 16 { @@ -12,9 +14,7 @@ void itoa(int16 value, int8 base, char[] result) { } negative = value < 0; - //abs without branch - mask = value >> 15; - value = (value ^ mask) - mask; + value = abs16(value); i = 0; if value == 0 { @@ -25,8 +25,6 @@ void itoa(int16 value, int8 base, char[] result) { temp = value; value /= base; result[i] = itoa_chars[temp - value * base]; - //result[i] = itoa_chars[value % base]; - //value /= base; i++; } if negative { diff --git a/lib/math/abs.rob b/lib/math/abs.rob index 63f4cdc..e27066f 100644 --- a/lib/math/abs.rob +++ b/lib/math/abs.rob @@ -16,3 +16,15 @@ int16 abs16(int16 value) inline { value = (value ^ mask) - mask; return value; } + +int32 abs32(int32 value) inline { + mask = value >> 31; + value = (value ^ mask) - mask; + return value; +} + +int64 abs64(int64 value) inline { + mask = value >> 63; + value = (value ^ mask) - mask; + return value; +} diff --git a/rob.vim b/rob.vim index 9b7dcd2..ca62365 100644 --- a/rob.vim +++ b/rob.vim @@ -8,6 +8,7 @@ if exists("b:current_syntax") endif syn keyword keywords while loop if else delay print return register at volatile const asm type interface implements use copy bind to singleton transient +syn keyword keywords naked weak section inline noinline syn keyword typeKeywords void char int8 int16 int32 int64 uint8 uint16 uint32 uint64 long float double bool enum syn keyword operatorKeywords and or quando esta servo syn keyword booleanKeyword true false diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index ec3ce7e..7201457 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -51,8 +51,14 @@ extern char *build_outputfilename; TargetInfo supportedTargets[__last_target] = { {rb_native, "", "", "", "", tint64}, // default target - {rb_avr, "avr328p", "avr", "atmega328p", "+avr5", tint16}, + + {rb_avr, "attiny13a", "avr", "attiny13a", "+avr25", tint16}, + {rb_avr, "attiny85", "avr", "attiny85", "+avr25", tint16}, + {rb_avr, "atmega328p", "avr", "atmega328p", "+avr5", tint16}, + {rb_avr, "atmega32u4", "avr", "atmega32u4", "+avr5", tint16}, + {rb_arm, "stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, + {rb_xtensa, "esp32", "xtensa", "", "", tint32}, }; diff --git a/src/BackLLVM.h b/src/BackLLVM.h index 3b3724a..f487106 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -20,7 +20,22 @@ typedef struct { extern unsigned int codeAddrSpace; extern unsigned int dataAddrSpace; -enum SupportedTargets {st_native, st_avr328p, st_stm32f1, st_esp32, __last_target}; +enum SupportedTargets { + st_native, + + // avr + st_attiny13a, + st_attiny85, + st_atmega328p, + st_atmega32u4, + + // stm32 + st_stm32f1, + + // awaiting backend goes mainstream + st_esp32, + __last_target}; + extern enum SupportedTargets currentTargetId; extern TargetInfo supportedTargets[__last_target]; diff --git a/src/StringConst.cpp b/src/StringConst.cpp index fa06ba4..579a4b5 100644 --- a/src/StringConst.cpp +++ b/src/StringConst.cpp @@ -10,6 +10,19 @@ StringConst::StringConst(const string& name, const string& str, location_t loc) } Value* StringConst::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - Builder->SetInsertPoint(block); - return Builder->CreateGlobalStringPtr(str, name); + Builder->SetInsertPoint(allocblock); + + if (value) + return value; + + Constant *constant = ConstantDataArray::getString(global_context, str, false); + auto *gv = new GlobalVariable( + *mainmodule, constant->getType(), true, GlobalValue::PrivateLinkage, + constant, name); + gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); + gv->setAlignment(Align(1)); + Constant *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); + Constant *indices[] = {zero, zero}; + value = ConstantExpr::getInBoundsGetElementPtr(gv->getValueType(), gv, indices); + return value; } diff --git a/src/StringConst.h b/src/StringConst.h index 3fc4ae9..794544b 100644 --- a/src/StringConst.h +++ b/src/StringConst.h @@ -7,6 +7,7 @@ class StringConst: public Array { protected: string str; + Value *value = NULL; public: StringConst(const string& name, const string& str, location_t loc); From dab973c3c6a2ee61e2aea3534c154d199212affb Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 25 Sep 2024 14:08:08 -0300 Subject: [PATCH 085/117] Allow building and debugging in vscode for native platform. --- platformio/platform/boards/native.json | 16 ++++++++++ platformio/platform/builder/main.py | 28 ++++++++++++++---- platformio/platform/platform.py | 41 +++++++++++++++----------- src/BackLLVM.cpp | 2 +- test/debug/platformio.ini | 5 ++++ 5 files changed, 68 insertions(+), 24 deletions(-) create mode 100644 platformio/platform/boards/native.json diff --git a/platformio/platform/boards/native.json b/platformio/platform/boards/native.json new file mode 100644 index 0000000..61a593a --- /dev/null +++ b/platformio/platform/boards/native.json @@ -0,0 +1,16 @@ +{ + "build": { + "mcu": "native" + }, + "debug": { + "target_mcu": "native", + "tools": {} + }, + "name": "Native", + "url": "", + "vendor": "native", + "upload": { + "protocol": "none" + } + } + \ No newline at end of file diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 0fa0440..0f6150b 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -40,9 +40,14 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 hardware_spec = None pass -ldflags = ["-nostdlib", "-L", stdlib_folder, "-Bstatic"] -ldflags.append("--gc-sections") -ldflags.append("--lto=thin") +if mcu == "native": + ldflags = [] +else: + ldflags = ["-L", stdlib_folder] + ldflags.append("-nostdlib") + ldflags.append("-Bstatic") + ldflags.append("--gc-sections") + ldflags.append("--lto=thin") if mcu.startswith("stm32f1"): ldflags.append("-Tstm32f1.ld") @@ -51,6 +56,8 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 ldflags.append("-Tatmega328p.ld") ldflags.append(join(stdlib_folder, "avr5.o")) auxsources += Glob(join(stdlib_folder, "atmega328p.rob")) +elif mcu == "native": + pass else: sys.stderr.write("The requested mcu is not supported.\n") env.Exit(1) @@ -60,7 +67,7 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 if build_type == "debug": robcmp_args.append("-g") - robcmp_args.append("-O1") + robcmp_args.append("-O0") elif build_type == "release": robcmp_args.append("-Oz") @@ -77,6 +84,15 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 env.Replace( GDB=avr_gdb ) +else: + env.Replace( + GDB="gdb" + ) + + +linker = "ld.lld" +if mcu == "native": + linker = "clang -g -O0" # using clang to link on native platform env.Append( BUILDERS=dict( @@ -85,7 +101,7 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 suffix=".bin" ), Linker=Builder( - action = ' '.join(["ld.lld", ' '.join(ldflags), "$SOURCES", "-o", "$TARGET"]), + action = ' '.join([linker, ' '.join(ldflags), "$SOURCES", "-o", "$TARGET"]), suffix=".elf" ), Rob=Builder( @@ -160,6 +176,8 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 sys.stderr.write("Upload protocol %s doesn't support mcu %s\n" % (upload_protocol, mcu)) env.Exit(1) +elif upload_protocol == "none": + pass else: sys.stderr.write("Unknown upload protocol %s\n" % upload_protocol) env.Exit(1) diff --git a/platformio/platform/platform.py b/platformio/platform/platform.py index 67789d7..997a8a3 100644 --- a/platformio/platform/platform.py +++ b/platformio/platform/platform.py @@ -43,24 +43,29 @@ def _add_default_debug_tools(self, board): debug["tools"] = {} if debug.get("target_mcu", ""): - debug["tools"]["robcmp-led"]["server"]["arguments"] = [ - "-f", "$PROG_PATH", - "-m", debug["target_mcu"], - "-hw", "led", - "-g" - ] - debug["tools"]["robcmp-ssd1306"]["server"]["arguments"] = [ - "-f", "$PROG_PATH", - "-m", debug["target_mcu"], - "-hw", "ssd1306", - "-g" - ] - debug["tools"]["robcmp-hd44780"]["server"]["arguments"] = [ - "-f", "$PROG_PATH", - "-m", debug["target_mcu"], - "-hw", "hd44780", - "-g" - ] + if "robcmp-led" in debug["tools"]: + debug["tools"]["robcmp-led"]["server"]["arguments"] = [ + "-f", "$PROG_PATH", + "-m", debug["target_mcu"], + "-hw", "led", + "-g" + ] + + if "robcmp-ssd1306" in debug["tools"]: + debug["tools"]["robcmp-ssd1306"]["server"]["arguments"] = [ + "-f", "$PROG_PATH", + "-m", debug["target_mcu"], + "-hw", "ssd1306", + "-g" + ] + + if "robcmp-hd44780" in debug["tools"]: + debug["tools"]["robcmp-hd44780"]["server"]["arguments"] = [ + "-f", "$PROG_PATH", + "-m", debug["target_mcu"], + "-hw", "hd44780", + "-g" + ] # J-Link, ST-Link upload_protocols = board.manifest.get("upload", {}).get("protocols", []) diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 7201457..a324152 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -50,7 +50,7 @@ enum SupportedTargets currentTargetId; extern char *build_outputfilename; TargetInfo supportedTargets[__last_target] = { - {rb_native, "", "", "", "", tint64}, // default target + {rb_native, "native", "", "", "", tint64}, // default target {rb_avr, "attiny13a", "avr", "attiny13a", "+avr25", tint16}, {rb_avr, "attiny85", "avr", "attiny85", "+avr25", tint16}, diff --git a/test/debug/platformio.ini b/test/debug/platformio.ini index 8c41415..26e80a0 100644 --- a/test/debug/platformio.ini +++ b/test/debug/platformio.ini @@ -10,3 +10,8 @@ build_type = release [env:debug] build_type = debug debug_tool = robcmp-ssd1306 + +[env:native] +board = native +build_type = debug +upload_protocol = none \ No newline at end of file From a220bbb292718d1a06d5db47c0fd341d0fa89fde Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Mon, 30 Sep 2024 12:14:14 -0300 Subject: [PATCH 086/117] Add basic float support to atmega and implements a bitcast operator --- lib/avr5.S | 839 ++++++++++++++++++++++++++++++++++++++ lib/math/float.rob | 17 + src/BitCast.cpp | 9 + src/BitCast.h | 29 ++ src/FunctionAttributes.h | 1 + src/FunctionDecl.cpp | 4 + src/Header.h | 1 + src/Language.l | 1 + src/Language.y | 12 +- src/LanguageHeader.y | 2 +- src/LanguageUse.y | 1 + src/PropagateTypes.cpp | 16 + src/PropagateTypes.h | 7 +- src/Visitor.h | 2 + test/atmega328p/float.rob | 69 ++++ test/general/float.rob | 1 + 16 files changed, 1007 insertions(+), 4 deletions(-) create mode 100644 lib/math/float.rob create mode 100644 src/BitCast.cpp create mode 100644 src/BitCast.h create mode 100644 test/atmega328p/float.rob create mode 120000 test/general/float.rob diff --git a/lib/avr5.S b/lib/avr5.S index 2e1e9d5..52a11e2 100644 --- a/lib/avr5.S +++ b/lib/avr5.S @@ -349,3 +349,842 @@ DEFUN memset ret ENDF memset +/* + * The assembly code below implements float32 functions and was slight + * adapted from avrlibc/libm (https://github.com/avrdudes/avr-libc) + * by thborges, 29-Sep-2024. + */ + +/* Copyright (c) 2002 Michael Stumpf + Copyright (c) 2006 Dmitry Xmelkov + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + 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 OWNER 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. */ + +#define rB0 r18 +#define rB1 r19 +#define rB2 r20 +#define rB3 r21 +#define rA0 r22 +#define rA1 r23 +#define rA2 r24 +#define rA3 r25 +#define rBE r26 +#define rAE r27 + + +DEFUN __subsf3 + subi rB3, 0x80 ; complement sign bit of B +DEFUN __addsf3 + clr rAE + clr rBE + rcall __addsf3x + rjmp __fp_round +ENDF __subsf3 + + + + +DEFUN __fp_pscA + clr r0 + dec r0 + cp r1, rA0 + cpc r1, rA1 + cpc r1, rA2 + cpc r0, rA3 + ret +ENDF __fp_pscA + + +DEFUN __fp_pscB + clr r0 + dec r0 + cp r1, rB0 + cpc r1, rB1 + cpc r1, rB2 + cpc r0, rB3 + ret +ENDF __fp_pscB + + +DEFUN __fp_nan + ldi rA3, 0xFF + ldi rA2, 0xC0 + ret +ENDF __fp_nan + + +DEFUN __fp_inf + bld rA3, 7 ; sign + ori rA3, 0x7f + ldi rA2, 0x80 + ldi rA1, 0 + ldi rA0, 0 + ret +ENDF __fp_inf + + +__addsf3xexit: + rcall __fp_pscA + brcs .L_nan + rcall __fp_pscB + brcs .L_nan + brne .L_inf ; B is finite --> return A + cpi rA3, 255 + brne .L_infB ; A is finite --> return B + brtc .L_inf ; Inf + Inf with the same sign +.L_nan: + rjmp __fp_nan +.L_infB: + brtc .L_inf + com ZL +.L_inf: + bst ZL, 7 + rjmp __fp_inf + +DEFUN __addsf3x + mov ZL, rA3 ; save sign of A + rcall __fp_split3 + brcs __addsf3xexit + ; compare A and B + cp rAE, rBE + cpc rA0, rB0 + cpc rA1, rB1 + cpc rA2, rB2 + cpc rA3, rB3 + brlo 2f ; fabs(A) < fabs(B) + brne 4f ; fabs(A) > fabs(B) + brtc .L_add + rjmp __fp_zero ; A + (-A) = +0.0 + ; swap A and B +2: brtc 3f + com ZL ; update sign +3: mov r0, rAE + mov rAE, rBE + mov rBE, r0 + movw r0, rA0 + movw rA0, rB0 + movw rB0, r0 + movw r0, rA2 + movw rA2, rB2 + movw rB2, r0 + clr r1 +4: clr ZH + sub rB3, rA3 +5: breq 7f ; shift is not needed + cpi rB3, -7 + brsh 6f + cpi rB3, -32 + brlo .L_ret + cp r1, rBE + sbci ZH, 0 + mov rBE, rB0 + mov rB0, rB1 + mov rB1, rB2 + clr rB2 + subi rB3, -8 + rjmp 5b + +6: lsr rB2 + ror rB1 + ror rB0 + ror rBE + sbci ZH, 0 + inc rB3 + brne 6b + +7: + ; direction ? + brtc .L_add + ; A -= B + cp r1, ZH + sbc rAE, rBE + sbc rA0, rB0 + sbc rA1, rB1 + sbc rA2, rB2 + brmi .L_ret +8: subi rA3, 1 + breq 9f + lsl ZH + rol rAE + rol rA0 + rol rA1 + rol rA2 + brpl 8b + rjmp .L_ret + +.L_add: + add rAE, rBE + adc rA0, rB0 + adc rA1, rB1 + adc rA2, rB2 + brcc .L_ret + ror rA2 + ror rA1 + ror rA0 + ror rAE + ror ZH + cpi rA3, 254 + brlo 9f + rjmp .L_inf +9: inc rA3 +.L_ret: + lsl rA2 + brcs 1f + clr rA3 +1: lsl ZL ; sign + ror rA3 + ror rA2 + ret +ENDF __addsf3x + + +DEFUN __fp_zero + clt +DEFUN __fp_szero + clr rAE + clr rA0 + clr rA1 + wmov rA2, rA0 + bld rA3, 7 + ret +ENDF __fp_szero + + +DEFUN __fp_split3 + ; rA3[7] := sign(A) ^ sign(B) + sbrc rB3, 7 + subi rA3, 0x80 + ; split B + lsl rB2 + rol rB3 ; exponent + breq 4f + cpi rB3, 0xff ; C = 1, if rB3 != 0xff + breq 5f +1: ror rB2 ; restore rB2 and (possible) hidden bit +; __fp_splitA (float A); +DEFUN __fp_splitA + lsl rA2 +2: bst rA3, 7 + rol rA3 + breq 6f + cpi rA3, 0xff + breq 7f +3: ror rA2 + ret + + ; B is zero or subnormal +4: cp r1, rB0 + cpc r1, rB1 + cpc r1, rB2 ; C = 1, if B is not a zero + rol rB3 ; C = 0 + rjmp 1b + ; B is not a finite +5: lsr rB2 + rcall __fp_splitA + rjmp 8f + + ; A is zero or subnormal +6: cp r1, rA0 + cpc r1, rA1 + cpc r1, rA2 + rol rA3 + rjmp 3b + ; A is not a finite +7: lsr rA2 ; C = 0 + cpc rA1, r1 + cpc rA0, r1 +8: sec + ret +ENDF __fp_split3 + + +DEFUN __fixsfsi + rcall __fixunssfsi + set + cpse rAE, r1 ; error flag + rjmp __fp_szero ; return 0x80000000 + ret +ENDF __fixsfsi + + +DEFUN __fixunssfsi + rcall __fp_splitA + brcs .L_err + ; A is finite + subi rA3, 127 ; exponent field of 1.0 + brlo .L_zr + ; fabs(A) >= 1.0 + mov rAE, rA3 + clr rA3 + subi rAE, 23 + brlo 4f ; shift to right + breq .L_sign ; no shift + ; fabs(A) >= 0x0.800000p+25 To reduce code size we will not check + ; number of shifts. Instead we will check a MSB of result. +1: lsl rA0 + rol rA1 + rol rA2 + rol rA3 + brmi 2f ; next shift is impossible: data lost + dec rAE + brne 1b + rjmp .L_sign + +2: cpi rAE, 1 + breq .L_sign ; rAE: overflow for 'signed long' usage + +.L_err: rcall __fp_zero + ldi rAE, 1 ; error flag + ret + +.L_zr: rjmp __fp_zero ; return 0x00000000, clear rAE + + ; fabs(A) <= 0x0.ffffffp+23 + ; Shift A to right by 1 (rA3==-1) .. 23 (rA3==-23) positions. + +3: mov rA0, rA1 + mov rA1, rA2 + clr rA2 + subi rAE, -8 + breq .L_sign + +4: cpi rAE, -7 + brlt 3b ; quick shift is possible + +5: lsr rA2 + ror rA1 + ror rA0 + inc rAE + brne 5b + + ; restore the sign and return +.L_sign: + brtc 6f + com rA3 + com rA2 + com rA1 + neg rA0 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 +6: ret + +ENDF __fixunssfsi + + +DEFUN __fp_round + ; is A finite ? + mov r0, rA3 + inc r0 + lsl r0 + brne 1f + tst rA2 + brmi 3f ; no, A is not a finite number + ; rounding +1: lsl rAE + brcc 3f + or rAE, ZH + brne 2f + sbrs rA0, 0 ; round to even + rjmp 3f +2: subi rA0, -1 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 + +3: ret +ENDF __fp_round + +#define ret_lo r24 +DEFUN __cmpsf2 +DEFUN __eqsf2 +DEFUN __nesf2 +DEFUN __ltsf2 +DEFUN __lesf2 + rcall __fp_cmp + brcc 1f + ldi ret_lo, 1 +1: ret +ENDF __cmpsf2 + +DEFUN __fp_cmp + lsl rA3 + sbc r0, r0 ; r0 = (A < 0) ? -1 : 0 + lsl rB3 + sbc rBE, rBE ; rBE = (B < 0) ? -1 : 0 + ; isnan(A) ? + ldi ZL, 0x80 ; NaN: 0x{f/7}f800001..0x{f/7}fffffff + ldi ZH, 0xfe + cp r1, rA0 + cpc r1, rA1 + cpc ZL, rA2 + cpc ZH, rA3 + brlo 9f ; branch, if C == 1 + ; isnan(B) ? + cp r1, rB0 + cpc r1, rB1 + cpc ZL, rB2 + cpc ZH, rB3 + brlo 9f ; branch, if C == 1 + ; compare + sub rA0, rB0 + sbc rA1, rB1 + sbc rA2, rB2 + sbc rA3, rB3 ; C is set, if A < B + brne 1f + ; absolute values are equal, check signs + eor r0, rBE + breq 9f ; if branch, rA2 = 0, C = 0 + ; force -0.0 == +0.0 + or rB0, rB1 + or rB0, rB2 + or rB0, rB3 + brne 2f ; evaluate sign(B) + ret + ; view argument signes +1: eor r0, rBE ; C is not changed + brne 2f ; signs are different + sbci rBE, 1 ; rBE[0] = (A < B && A > 0) ? 0 : 1 +2: lsr rBE ; C = above result OR sign(B) + ; build return value, C is set, if A > B + ldi rA2, -1 + adc rA2, r1 + adc rA2, r1 ; C = 0 at any case +9: ret +ENDF __fp_cmp + + +DEFUN __unordsf2 + rcall __fp_cmp ; return C=1, if any of args is NaN + sbc r24, r24 + sbc r25, r25 + ret +ENDF __unordsf2 + + +DEFUN __mulsf3 + rcall __mulsf3x + rjmp __fp_round +ENDF __mulsf3 + + +__mulsf3x_exit: +0: rcall __fp_pscA + brcs 1f + rcall __fp_pscB + brcs 1f + and rA3, rB3 ; one of args is 0xff + breq 1f + rjmp __fp_inf ; nonzero * Inf --> Inf +1: rjmp __fp_nan ; 0 * Inf --> NaN +2: clr r1 ; after 'mul rA3,rB3' + rjmp __fp_szero + +DEFUN __mulsf3x + rcall __fp_split3 + brcs 0b + +DEFUN __mulsf3_pse ; post split entry + ; check zero + mul rA3, rB3 ; r1 would be clean + breq 2b + ; rB3.rA3 := rA3 + rB3 + add rA3, rB3 + ldi rB3, 0 + adc rB3, rB3 + + ; multiplication: rA2.rA1.rA0 * rB2.rB1.rB0 --> rA2.rA1.rA0.rAE.ZH.ZL + + ; ZH.ZL = rA0 * rB0 + mul rA0, rB0 + movw ZL, r0 + ; rAE.ZH += rA1 * rB0 + mul rA1, rB0 + clr rAE + add ZH, r0 + adc rAE, r1 + ; rBE.rAE.ZH = rAE.ZH + rA0 * rB1 + mul rA0, rB1 + clr rBE + add ZH, r0 + adc rAE, r1 + adc rBE, rBE + ; rA0.rBE.rAE = rBE.rAE + rA0 * rB2 + mul rA0, rB2 + clr rA0 + add rAE, r0 + adc rBE, r1 + adc rA0, rA0 + ; rA0.rBE.rAE += rA2 * rB0 + mul rA2, rB0 + clr rB0 + add rAE, r0 + adc rBE, r1 + adc rA0, rB0 + ; rA0.rBE.rAE += rA1 * rB1 + mul rA1, rB1 + add rAE, r0 + adc rBE, r1 + adc rA0, rB0 ; rB0 == 0 + ; rB0.rA0.rBE = rA0.rBE + rA2 * rB1 + mul rA2, rB1 + add rBE, r0 + adc rA0, r1 + adc rB0, rB0 ; rB0 was 0 + ; rB0.rA0.rBE += rA1 * rB2 + mul rA1, rB2 + clr rB1 + add rBE, r0 + adc rA0, r1 + adc rB0, rB1 + ; rB0.rA0 += rA2 * rB2 + mul rA2, rB2 + add rA0, r0 + adc rB0, r1 + ; move result: rA2.rA1.rA0.rAE.ZH.ZL = rB0.rA0.rBE.rAE.ZH.ZL + mov rA2, rB0 + mov rA1, rA0 + mov rA0, rBE + ; __zero_reg__ + clr r1 + + ; exponent -= 127 (Why not 126? For compare convenience.) + subi rA3, 0x7F ;lo8(127) + sbci rB3, 0x00 ;hi8(127) + brmi 13f ; denormalization is needed + breq 15f ; normalization is impossible + ; result exponent > min ==> normalization is possible +10: tst rA2 + brmi 11f ; mantissa is normal + ; mantissa <<= 1 + lsl ZL + rol ZH + rol rAE + rol rA0 + rol rA1 + rol rA2 + ; exponent -= 1 + subi rA3, 0x01 ;lo8(1) + sbci rB3, 0x00 ;hi8(1) + brne 10b + ; check to overflow +11: cpi rA3, 254 + cpc rB3, r1 + brlo 15f + rjmp __fp_inf + ; check lowest value of exponent to avoid long operation +12: rjmp __fp_szero +13: cpi rB3, 0xFF ;hi8(-24) ; here rB3 < 0 + brlt 12b + cpi rA3, 0XE8 ;lo8(-24) + brlt 12b + ; mantissa >>= -rA3 +14: lsr rA2 + ror rA1 + ror rA0 + ror rAE + ror ZH + ror ZL + subi rA3, -1 + brne 14b + ; for rounding +15: or ZH, ZL + ; pack + lsl rA2 + adc rA3, r1 ; restore exponent for normal values + lsr rA3 + ror rA2 + bld rA3, 7 ; sign + ret +ENDF __mulsf3x + + +DEFUN __gesf2 +DEFUN __gtsf2 + rcall __fp_cmp + brcc 1f + ldi ret_lo, -1 +1: ret +ENDF __gesf2 + + +DEFUN __divsf3 + rcall __divsf3x + rjmp __fp_round +ENDF __divsf3 + + +__divsf3x_exit: +0: rcall __fp_pscB + brcs .L_nan_div + rcall __fp_pscA + brcs .L_nan_div + brne .L_zr_div ; finite / Inf --> 0 +.L_infA: + cpi rB3, 255 + breq .L_nan_div ; Inf / Inf --> NaN +.L_inf_div: + rjmp __fp_inf +1: + cpse rB3, r1 ; 0/finite --> 0, 0/0 --> NaN +.L_zr_div: rjmp __fp_szero +.L_nan_div: rjmp __fp_nan + +DEFUN __divsf3x + rcall __fp_split3 + brcs 0b + +DEFUN __divsf3_pse ; post split entry + tst rA3 + breq 1b + tst rB3 + breq .L_inf_div ; finite / 0.0 --> Inf + + sub rA3, rB3 + sbc rB3, rB3 + +/* Prepare to division: + A: rAE.rA2.rA1.rA0 0x00000001..0x00FFFFFF + B: rBE.rB2.rB1.rB0 0x00000002..0x01FFFFFE + A < B + */ + clr rAE + clr rBE +2: cp rA0, rB0 + cpc rA1, rB1 + cpc rA2, rB2 + brlo 3f + subi rA3, 0xFF ;lo8(-1) + sbci rB3, 0xFF ;hi8(-1) + lsl rB0 + rol rB1 + rol rB2 + rol rBE + breq 2b +3: + rcall .L_div + mov r0, ZL + brmi 5f ; N is result of 'com ZL' from .L_div + +4: ldi ZL, 0x80 + rcall .L_div1 + subi rA3, 0x01 ;lo8(1) + sbci rB3, 0x00 ;hi8(1) + lsr ZL + rol r0 + brpl 4b + +5: rcall .L_div + mov ZH, ZL + rcall .L_div + + lsl rA0 + rol rA1 + rol rA2 + rol rAE + cp rB0, rA0 + cpc rB1, rA1 + cpc rB2, rA2 + cpc rBE, rAE + ldi rAE, 0x80 + breq 4f + sbc rAE, rAE + +4: mov rA2, r0 + wmov rA0, ZL + clr ZH + + ; exponent += 125 + subi rA3, 0x83 ;lo8(-125) + sbci rB3, 0xFF ;hi8(-125) + brmi 13f ; denormalization is needed + ; check to overflow +11: cpi rA3, 254 + cpc rB3, r1 + brlo 15f + rjmp __fp_inf + ; check lowest value of exponent to avoid long operation +12: rjmp __fp_szero +13: cpi rB3, 0xFF ;hi8(-24) ; here rB3 < 0 + brlt 12b + cpi rA3, 0xE8 ;lo8(-24) + brlt 12b + ; mantissa >>= -rA3 +14: lsr rA2 + ror rA1 + ror rA0 + ror rAE + ror ZH + subi rA3, -1 + brne 14b + ; pack +15: lsl rA2 + adc rA3, r1 ; restore exponent for normal values + lsr rA3 + ror rA2 + bld rA3, 7 + ret + +.L_div: + ldi ZL, 1 +.L_div1: + lsl rA0 + rol rA1 + rol rA2 + rol rAE + cp rA0, rB0 + cpc rA1, rB1 + cpc rA2, rB2 + cpc rAE, rBE + brcs 2f + sub rA0, rB0 + sbc rA1, rB1 + sbc rA2, rB2 + sbc rAE, rBE +2: rol ZL + brcc .L_div1 + com ZL + ret +ENDF __divsf3x + + +DEFUN __floatdisf + bst rA3, 7 ; sign + brtc 1f + rcall __fp_negdi +1: rjmp __fp_di2sf +ENDF __floatdisf + + +DEFUN __fp_negdi + com rA3 + com rA2 + com rA1 + com rA0 + com rB3 + com rB2 + com rB1 + neg rB0 + sbci rB1, -1 + sbci rB2, -1 + sbci rB3, -1 + sbci rA0, -1 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 + ret +ENDF __fp_negdi + + +DEFUN __floatundisf + clt ; result sign + +DEFUN __fp_di2sf + mov ZH, rA3 + ldi rA3, 127 + 55 ; exponent for 00.80.00.00.00.00.00.00 + tst ZH + breq .L_tstA2 + +/* Shift to right is needed by 1..8 positions. + Optimization: accumulate an info about tail into rB2. */ + cp r1, rB0 + cpc r1, rB1 + cpc r1, rB2 + sbc rB2, rB2 + ; shift to right +1: inc rA3 ; exponent += 1 + lsr ZH + ror rA2 + ror rA1 + ror rA0 + ror rB3 + sbci rB2, 0 ; set rB2[7] if C was 1 + tst ZH + brne 1b + rjmp .L_round + + ; x == 0 +2: clr rA3 + ret + ; check: is fast shift possible? +.L_tstA2: + tst rA2 + brne 4f + ; fast shift to left +3: subi rA3, 8 + brpl 2b ; 127+55 - 7*8 --> 126 + or rA2, rA1 ; obtain Z flag + mov rA1, rA0 + mov rA0, rB3 + mov rB3, rB2 + mov rB2, rB1 + mov rB1, rB0 + ldi rB0, 0 + breq 3b ; Z is result of 'or rA2,rA1' + +/* rA2 is not 0. It is needed shift to left by 0..7 positions. + Optimization: rB2..rB0 are not shifted. Instead, save an info + about tail in rB2. */ +4: cp r1, rB0 + cpc r1, rB1 + cpc r1, rB2 + sbc rB2, rB2 + tst rA2 + brmi .L_round +5: dec rA3 ; exponent -= 1 + lsl rB2 + rol rB3 + rol rA0 + rol rA1 + rol rA2 + brpl 5b + +/* Round and pack. Now we have: + rA3 - mantissa + rA2.rA1.rA0.rB3 - fraction + rB2 - is negative if tail is not equal 0 */ +.L_round: + tst rB3 + brpl 7f + lsl rB2 + rol rB3 + brne 6f + sbrs rA0, 0 ; round to even + rjmp 7f +6: subi rA0, -1 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 + ; pack +7: lsl rA2 + lsr rA3 + ror rA2 + bld rA3, 7 ; sign + ret +ENDF __floatundisf + + diff --git a/lib/math/float.rob b/lib/math/float.rob new file mode 100644 index 0000000..41eec4d --- /dev/null +++ b/lib/math/float.rob @@ -0,0 +1,17 @@ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + */ + +const NAN = 0.0 / 0.0; +const INFINITY = 1.0 / 0.0; + +bool isnan(float x) { + u = bitcast(x, uint32); + return (u & 0x7fffffff) > 0x7f800000; +} + +bool isinf(float x) { + u = bitcast(x, uint32); + return (u & 0x7fffffff) == 0x7f800000; +} diff --git a/src/BitCast.cpp b/src/BitCast.cpp new file mode 100644 index 0000000..7813488 --- /dev/null +++ b/src/BitCast.cpp @@ -0,0 +1,9 @@ + +#include "BitCast.h" + +Value *BitCast::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) +{ + Value *v = value->generate(func, block, allocblock); + Type *dTy = buildTypes->llvmType(destTy); + return Builder->CreateBitCast(v, dTy); +} diff --git a/src/BitCast.h b/src/BitCast.h new file mode 100644 index 0000000..bd79566 --- /dev/null +++ b/src/BitCast.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Node.h" +#include "Visitor.h" + +class BitCast: public Node { +private: + Node *value; + DataType destTy; + +public: + BitCast(Node *v, DataType dTy): Node(v->getLoc()), value(v), destTy(dTy) { + addChild(v); + } + + virtual DataType getDataType() override { + return destTy; + } + + virtual DataType getSourceType() { + return value->getDataType(); + } + + virtual Node* accept(Visitor& v) override { + return v.visit(*this); + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; +}; diff --git a/src/FunctionAttributes.h b/src/FunctionAttributes.h index 8a203f8..ea7ad80 100644 --- a/src/FunctionAttributes.h +++ b/src/FunctionAttributes.h @@ -9,6 +9,7 @@ enum FunctionAttributeType { fa_naked, fa_signal, fa_debugonly, + fa_noopt, }; typedef pair FunctionAttribute; diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 9dec694..0f55dbb 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -110,6 +110,10 @@ void FunctionBase::addFunctionAttributes(Function *func) { func->addFnAttr(Attribute::Naked); func->addFnAttr(Attribute::NoInline); break; + case fa_noopt: + func->addFnAttr(Attribute::OptimizeNone); + func->addFnAttr(Attribute::NoInline); + break; default: break; } diff --git a/src/Header.h b/src/Header.h index 07221a5..751916a 100644 --- a/src/Header.h +++ b/src/Header.h @@ -53,3 +53,4 @@ #include "MemCopy.h" #include "BackLLVM.h" #include "NamedConst.h" +#include "BitCast.h" diff --git a/src/Language.l b/src/Language.l index 195cf7e..259437e 100644 --- a/src/Language.l +++ b/src/Language.l @@ -51,6 +51,7 @@ EXP ([Ee][-+]?[0-9]+)? "naked" { return TOK_NAKED; } "signal" { return TOK_SIGNAL; } "debugonly" { return TOK_DEBUGONLY; } +"noopt" { return TOK_NOOPT; } "bind" { return TOK_BIND; } "to" { return TOK_TO; } diff --git a/src/Language.y b/src/Language.y index e342049..f6d1ee7 100644 --- a/src/Language.y +++ b/src/Language.y @@ -151,6 +151,7 @@ function_attribute | TOK_NAKED { $$ = new FunctionAttribute(fa_naked, ""); } | TOK_SIGNAL { $$ = new FunctionAttribute(fa_signal, ""); } | TOK_DEBUGONLY { $$ = new FunctionAttribute(fa_debugonly, ""); } + | TOK_NOOPT { $$ = new FunctionAttribute(fa_noopt, ""); } | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } event : TOK_QUANDO TOK_INTEGER TOK_ESTA TOK_INTEGER '{' stmts '}'[ef] { @@ -464,7 +465,16 @@ unary : '-' factor { $$ = new BinaryOp($factor, '*', getNodeForIntConst(-1, @fac call_or_cast : ident_or_xident[id] '(' paramscall ')' { if (strncmp("copy", $id, 4) == 0 && $paramscall->getNumParams() == 1) $$ = new MemCopy($paramscall->getParamElement(0)); - else { + else if (strncmp("bitcast", $id, 7) == 0 && $paramscall->getNumParams() == 2) { + Node *nodeTy = $paramscall->getParamElement(1); + Load *load = dynamic_cast(nodeTy); + if (load && buildTypes->getType(load->getName()) != BuildTypes::undefinedType) { + DataType dt = buildTypes->getType(load->getName()); + $$ = new BitCast($paramscall->getParamElement(0), dt); + } else { + $$ = new FunctionCall($id, $paramscall, @id); + } + } else { $$ = new FunctionCall($id, $paramscall, @id); } $$->setLocation(@id); diff --git a/src/LanguageHeader.y b/src/LanguageHeader.y index 5156e8d..77b54be 100644 --- a/src/LanguageHeader.y +++ b/src/LanguageHeader.y @@ -35,7 +35,7 @@ %token TOK_QUANDO TOK_ESTA %token EQ_OP NE_OP GE_OP LE_OP GT_OP LT_OP TOK_LSHIFT TOK_RSHIFT -%token TOK_INLINE TOK_NOINLINE TOK_WEAK TOK_SECTION TOK_NAKED TOK_SIGNAL TOK_DEBUGONLY +%token TOK_INLINE TOK_NOINLINE TOK_WEAK TOK_SECTION TOK_NAKED TOK_SIGNAL TOK_DEBUGONLY TOK_NOOPT %union { char *ident; diff --git a/src/LanguageUse.y b/src/LanguageUse.y index 42aeed3..e56932a 100644 --- a/src/LanguageUse.y +++ b/src/LanguageUse.y @@ -159,6 +159,7 @@ function_attribute | TOK_NAKED { $$ = new FunctionAttribute(fa_naked, ""); } | TOK_SIGNAL { $$ = new FunctionAttribute(fa_signal, ""); } | TOK_DEBUGONLY { $$ = new FunctionAttribute(fa_debugonly, ""); } + | TOK_NOOPT { $$ = new FunctionAttribute(fa_noopt, ""); } | TOK_SECTION TOK_IDENTIFIER[id] { $$ = new FunctionAttribute(fa_section, $id); } qualifier : TOK_CONST { $$ = qconst; } diff --git a/src/PropagateTypes.cpp b/src/PropagateTypes.cpp index d456a75..e72de0c 100644 --- a/src/PropagateTypes.cpp +++ b/src/PropagateTypes.cpp @@ -536,3 +536,19 @@ Node* PropagateTypes::visit(MemCopy& n) { n.symbols = n.children()[0]->getSymbols(); return NULL; } + +Node* PropagateTypes::visit(BitCast& n) { + propagateChildren(n); + DataType dt = n.getDataType(); + int returnBitwidth = buildTypes->bitWidth(dt); + DataType st = n.getSourceType(); + int sourceBitwidth = buildTypes->bitWidth(st); + + if (returnBitwidth != sourceBitwidth) { + yyerrorcpp(string_format("Can not bitcast from '%s' to '%s'.", + buildTypes->name(st), + buildTypes->name(dt)), &n); + } + + return NULL; +} diff --git a/src/PropagateTypes.h b/src/PropagateTypes.h index 146b93d..0063f78 100644 --- a/src/PropagateTypes.h +++ b/src/PropagateTypes.h @@ -15,6 +15,7 @@ #include "Enum.h" #include "Load.h" #include "MemCopy.h" +#include "BitCast.h" class CoercionBase: public Node { protected: @@ -121,9 +122,9 @@ class FloatToInt: public CoercionBase { RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); if (buildTypes->isUnsignedDataType(dt)) - return Builder->CreateFPToUI(v, buildTypes->llvmType(dt), "trunc"); + return Builder->CreateFPToUI(v, buildTypes->llvmType(dt), "fptoui"); else - return Builder->CreateFPToSI(v, buildTypes->llvmType(dt), "trunc"); + return Builder->CreateFPToSI(v, buildTypes->llvmType(dt), "fptosi"); } }; @@ -216,4 +217,6 @@ class PropagateTypes: public Visitor { virtual Node* visit(Return& n) override; virtual Node* visit(FunctionImpl& n) override; virtual Node* visit(FunctionCall& n) override; + + virtual Node* visit(BitCast& n) override; }; diff --git a/src/Visitor.h b/src/Visitor.h index 2dc7476..f27ed6c 100644 --- a/src/Visitor.h +++ b/src/Visitor.h @@ -36,6 +36,7 @@ class Variable; class NamedConst; class MemCopy; class Enum; +class BitCast; #define VISITOR_DECLAREP(T, P) \ virtual Node *visit(T& n) { return visit((P&)n); } \ @@ -87,6 +88,7 @@ class Visitor { VISITOR_DECLARE(MemCopy) VISITOR_DECLARE(Enum) VISITOR_DECLARE(UpdateArray) + VISITOR_DECLARE(BitCast) }; diff --git a/test/atmega328p/float.rob b/test/atmega328p/float.rob new file mode 100644 index 0000000..41e2189 --- /dev/null +++ b/test/atmega328p/float.rob @@ -0,0 +1,69 @@ + +/* Test case to check float support on atmega328p */ + +use math.float; + +a = 1.2; +b = 1.1; + +float sum() { + c = a + b; + return c; +} + +float sub() { + c = a - b; + return c; +} + +float mult() { + c = a * b; + return c; +} + +float div() { + c = a / b; + return c; +} + +const epsilon = 0.000001; + +int8 main() { + r = sum(); + if r - 2.3 >= epsilon { + return 1; + } + + r = sub(); + if r - 0.1 >= epsilon { + return 2; + } + + r = mult(); + if r - 1.32 >= epsilon { + return 3; + } + + r = div(); + if r - 1.090909 >= epsilon { + return 4; + } + + r = NAN; + if !isnan(r) { + return 5; + } + + r = INFINITY; + if !isinf(r) { + return 6; + } + + r = -INFINITY; + if !isinf(r) { + return 7; + } + + return 0; +} + diff --git a/test/general/float.rob b/test/general/float.rob new file mode 120000 index 0000000..ba4a261 --- /dev/null +++ b/test/general/float.rob @@ -0,0 +1 @@ +../atmega328p/float.rob \ No newline at end of file From 6024488f0f8ed202e7261ff5f5cdca7e479c9dc7 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Mon, 30 Sep 2024 12:15:09 -0300 Subject: [PATCH 087/117] Fixes to build with LLVM19 --- src/BackLLVM.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index a324152..a3884e4 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -92,12 +93,18 @@ void setup_target_machine(char opt_level) { std::string defaultt = sys::getDefaultTargetTriple(); supportedTargets[0].triple = defaultt.c_str(); SubtargetFeatures Features; + + #if LLVM_VERSION_MAJOR < 19 StringMap HostFeatures; if (sys::getHostCPUFeatures(HostFeatures)) { + #else + auto HostFeatures = sys::getHostCPUFeatures(); { + #endif for (auto &F : HostFeatures) { Features.AddFeature(F.first(), F.second); } } + static string nativeFeatures = Features.getString(); supportedTargets[0].features = nativeFeatures.c_str(); From b13a816ef952466e7bec61d70e78241f5d151be9 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 3 Oct 2024 11:41:02 -0300 Subject: [PATCH 088/117] Added float_to_int32 and float_to_64 assembly support on atmega328p. --- lib/avr5.S | 163 ++++++++++++++++++++++++++++++++++++++ test/atmega328p/float.rob | 21 ++++- 2 files changed, 183 insertions(+), 1 deletion(-) diff --git a/lib/avr5.S b/lib/avr5.S index 52a11e2..34c4cd6 100644 --- a/lib/avr5.S +++ b/lib/avr5.S @@ -1188,3 +1188,166 @@ DEFUN __fp_di2sf ENDF __floatundisf +DEFUN __fixsfdi + ldi rAE, 62 + rcall .L_sf2di + brcc 1f + ldi rA3, 0x80 +1: ret + +DEFUN __fixunssfdi + ldi rAE, 63 + +.L_sf2di: + ; clear LSBytes + clr rB0 + clr rB1 + movw rB2, rB0 + ; split + rcall __fp_splitA + brcs .L_ovfl ; is not finite + + subi rA3, 127 ; 1.0 exponent field + brlo .L_zero ; too small + + cp rAE, rA3 + brlo .L_ovfl ; fabs(A) >= 2**64 (or 2**63) + ldi rAE, 63 + sub rAE, rA3 + /* Now rAE is, for example: + 63 - exponent was 127+0, shift >>55 is needed, + 0 - exponent was 127+63, shift <<8 is needed. */ + clr rA3 + subi rAE, 8 ; rAE= -8..+55 + brpl 3f + ; fabs(A) >= 1.0 * 2**56 Shift to left is needed. + /* Shift to 8 is not optimized specially as an exotic. */ +2: lsl rA0 + rol rA1 + rol rA2 + rol rA3 + inc rAE + brmi 2b + rjmp .L_sign2 + ; Shift to right is needed +3: /* Now rAE: + 55 - exponent was 127+0, shift >>55 is needed, + 1 - exponent was 127+54, shift >>1 is needed, + 0 - exponent was 127+55, no shift is needed. */ + subi rAE, 8 + brmi 5f + ; quick shift by 8 +4: mov rB0, rB1 + mov rB1, rB2 + mov rB2, rB3 + mov rB3, rA0 + mov rA0, rA1 + mov rA1, rA2 + clr rA2 + subi rAE, 8 + brpl 4b + +5: subi rAE, -8 ; rAE = 0..7 + breq .L_sign2 + ; shift to 1..7 positions +6: lsr rA2 + ror rA1 + ror rA0 + ror rB3 + ror rB2 + ror rB1 + ror rB0 + dec rAE + brne 6b +.L_sign2: + brtc 7f + rcall __fp_negdi +7: clc + ret + +.L_zero: + clc +.L_ovfl: ; overflow, C is set already + ldi rA0, 0 + ldi rA1, 0 + movw rA2, rA0 + ret +ENDF __fixsfdi + + +DEFUN __floatunsisf + clt + rjmp 1f + +DEFUN __floatsisf + bst rA3, 7 ; sign + brtc 1f + ; negate A + com rA3 + com rA2 + com rA1 + neg rA0 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 +1: + tst rA3 + breq 4f + ; shift to right + mov ZH, rA3 + ldi rA3, 127 + 23 ; exponent + clr rAE +2: inc rA3 + lsr ZH + ror rA2 + ror rA1 + ror rA0 + ror rAE + cpse ZH, r1 + rjmp 2b + ; rounding + brpl .L_pack ; flags from 'ror rAE' + lsl rAE + brne 3f + sbrs rA0, 0 ; round to even + rjmp .L_pack +3: subi rA0, -1 + sbci rA1, -1 + sbci rA2, -1 + sbci rA3, -1 + rjmp .L_pack + +4: tst rA2 + breq 5f + ldi rA3, 127 + 23 + rjmp 8f + +5: tst rA1 + breq 6f + ldi rA3, 127 + 15 + mov rA2, rA1 + mov rA1, rA0 + rjmp 7f + +6: tst rA0 + breq 9f ; 0.0 + ldi rA3, 127 + 7 + mov rA2, rA0 + ldi rA1, 0 +7: + ldi rA0, 0 + brmi .L_pack ; flag from 'tst rA*' + ; shift to left by 1..7 positions +10: dec rA3 + lsl rA0 + rol rA1 + rol rA2 +8: brpl 10b + +.L_pack: + lsl rA2 + lsr rA3 + ror rA2 + bld rA3, 7 ; sign +9: ret +ENDF __floatunsisf diff --git a/test/atmega328p/float.rob b/test/atmega328p/float.rob index 41e2189..9516bd2 100644 --- a/test/atmega328p/float.rob +++ b/test/atmega328p/float.rob @@ -26,6 +26,14 @@ float div() { return c; } +int64 floattoi64(float x) { + return int64(x); +} + +int32 floattoi32(float x) { + return int32(x); +} + const epsilon = 0.000001; int8 main() { @@ -64,6 +72,17 @@ int8 main() { return 7; } - return 0; + r = div(); + s = floattoi64(r); + if s != 1 { + return 8; + } + + t = floattoi32(r); + if t != 1 { + return 9; + } + + return 0; } From b387d086b36565797ab0fce60c23c9ccb397e49f Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 19 Oct 2024 18:28:28 -0300 Subject: [PATCH 089/117] Fix declaration of string variable initialized by string constant and minor tweaks. --- .gitignore | 2 ++ src/FunctionDecl.cpp | 2 +- src/LoadArray.cpp | 1 + src/Scalar.cpp | 11 +++++++---- src/StringConst.cpp | 31 ++++++++++++++++++++++++++++--- src/StringConst.h | 5 +++++ test/general/byref-simple.rob | 24 ++++++++++++++++++++++++ test/general/strcpy.rob | 21 +++++++++++++++++++++ test/general/strlen.rob | 16 ++++++++++++++++ 9 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 test/general/byref-simple.rob create mode 100644 test/general/strcpy.rob create mode 100644 test/general/strlen.rob diff --git a/.gitignore b/.gitignore index 2ed40ef..268d16a 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,5 @@ test/atmega328p/out platformio/toolchain-robcmp/bin platformio/toolchain-robcmp/lib platformio/avr-gdb-build +Documentation +hack diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 0f55dbb..7feaa43 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -92,7 +92,7 @@ void FunctionBase::addFunctionAttributes(Function *func) { for(auto &[attr, value] : attributes->getAttributes()) { switch (attr) { case fa_weak: - func->setLinkage(GlobalValue::ExternalWeakLinkage); + func->setLinkage(GlobalValue::WeakAnyLinkage); break; case fa_inline: func->addFnAttr(Attribute::AlwaysInline); diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index b450d79..05738d1 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -73,6 +73,7 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al alloc = Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); } + Builder->SetInsertPoint(block); Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); Value *indexList[2] = {zero, indice}; Value *ptr = Builder->CreateGEP(symbol->getLLVMType(), alloc, ArrayRef(indexList), "gep"); diff --git a/src/Scalar.cpp b/src/Scalar.cpp index f42d3ac..9c4e1a3 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -178,10 +178,13 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc nvalue = exprv; } - RobDbgInfo.emitLocation(this); - const DataLayout &DL = mainmodule->getDataLayout(); - Align align = DL.getABITypeAlign(nvalue->getType()); - return Builder->CreateAlignedStore(nvalue, alloc, align, symbol->hasQualifier(qvolatile)); + if (nvalue != alloc) { + RobDbgInfo.emitLocation(this); + const DataLayout &DL = mainmodule->getDataLayout(); + Align align = DL.getABITypeAlign(nvalue->getType()); + return Builder->CreateAlignedStore(nvalue, alloc, align, symbol->hasQualifier(qvolatile)); + } else + return nvalue; } } diff --git a/src/StringConst.cpp b/src/StringConst.cpp index 579a4b5..d037a51 100644 --- a/src/StringConst.cpp +++ b/src/StringConst.cpp @@ -1,5 +1,6 @@ #include "StringConst.h" +#include "BackLLVM.h" #include "NamedConst.h" StringConst::StringConst(const string& name, const string& str, location_t loc) : @@ -21,8 +22,32 @@ Value* StringConst::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * constant, name); gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); gv->setAlignment(Align(1)); - Constant *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); - Constant *indices[] = {zero, zero}; - value = ConstantExpr::getInBoundsGetElementPtr(gv->getValueType(), gv, indices); + + // const a = "abcdef" + if (leftValue->hasQualifier(qconst)) { + Constant *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); + Constant *indices[] = {zero, zero}; + value = ConstantExpr::getInBoundsGetElementPtr(gv->getValueType(), gv, indices); + } else { + // a = "abcdef", alloc array and copy string const to it + Type* I = buildTypes->llvmType(tchar); + auto arrayType = ArrayType::get(I, str.size()); + + // alloc array + Builder->SetInsertPoint(allocblock); + auto alloc = Builder->CreateAlloca(arrayType, dataAddrSpace, 0, leftValue->getName()); + if (debug_info) { + RobDbgInfo.emitLocation(this); + RobDbgInfo.declareVar(leftValue, alloc, allocblock); + } + leftValue->setAlloca(alloc); + + // copy string to the new array + Builder->SetInsertPoint(block); + Builder->CreateMemCpy(alloc, Align(1), gv, Align(1), str.size()); + value = alloc; + + } + return value; } diff --git a/src/StringConst.h b/src/StringConst.h index 794544b..c8e97f5 100644 --- a/src/StringConst.h +++ b/src/StringConst.h @@ -8,6 +8,7 @@ class StringConst: public Array { protected: string str; Value *value = NULL; + Variable *leftValue = NULL; public: StringConst(const string& name, const string& str, location_t loc); @@ -34,4 +35,8 @@ class StringConst: public Array { virtual bool isConstExpr() override { return true; } + + void setLeftValue(Variable *symbol) override { + leftValue = symbol; + } }; diff --git a/test/general/byref-simple.rob b/test/general/byref-simple.rob new file mode 100644 index 0000000..708c169 --- /dev/null +++ b/test/general/byref-simple.rob @@ -0,0 +1,24 @@ + +mapping = { + 0x00E1, 0x00C1, + 0x00E9, 0x00C9 +}; + +type Integer { + codepoint = int32(0); +} + +void utf8_decode(Integer i) { + i.codepoint = 10; +} + +int8 main() { + cp = Integer(); + utf8_decode(cp); + if cp.codepoint != 10 { + return 1; + } + + return 0; +} + diff --git a/test/general/strcpy.rob b/test/general/strcpy.rob new file mode 100644 index 0000000..dfabb9c --- /dev/null +++ b/test/general/strcpy.rob @@ -0,0 +1,21 @@ +void strcpy(char[] src, int16 spos, char[] dst, int16 dpos, int16 len) { + i = 0; + while (i < len) { + dst[dpos + i] = src[spos + i]; + i++; + } +} + +int16 main(){ + a = "a noifas SDOINDAda"; + b = "B akjsad ADJNDAODA"; + strcpy(a, 0, b, 0, a.size); + i = 0; + while i < a.size { + if b[i] != a[i] { + return i; + } + i++; + } + return 0; +} diff --git a/test/general/strlen.rob b/test/general/strlen.rob new file mode 100644 index 0000000..d0917c4 --- /dev/null +++ b/test/general/strlen.rob @@ -0,0 +1,16 @@ + +const str = "abcd"; + +int8 strlen(char[] s) { + return s.size; +} + +int8 main() { + r = strlen(str); + if r == 4 { + return 0; + } else { + return 1; + } +} + From 6a16d8c32c74664c104cfe993719c940d19ad43d Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 30 Oct 2024 09:30:19 -0300 Subject: [PATCH 090/117] Fix build of function calls with string constants. --- src/StringConst.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/StringConst.cpp b/src/StringConst.cpp index d037a51..a340711 100644 --- a/src/StringConst.cpp +++ b/src/StringConst.cpp @@ -23,8 +23,8 @@ Value* StringConst::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); gv->setAlignment(Align(1)); - // const a = "abcdef" - if (leftValue->hasQualifier(qconst)) { + // const a = "abcdef" or a call to func("abc") + if (!leftValue || leftValue->hasQualifier(qconst)) { Constant *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); Constant *indices[] = {zero, zero}; value = ConstantExpr::getInBoundsGetElementPtr(gv->getValueType(), gv, indices); From d6c3db4995c531da5816fcb9a978a3c1fdd1756d Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 9 Nov 2024 15:46:59 -0300 Subject: [PATCH 091/117] Initial support to avr1284p; add test folder to stm32f1. --- lib/Makefile | 7 +- lib/atmega1284p.ld | 17 +++ lib/atmega1284p.rob | 147 ++++++++++++++++++++++++ src/BackLLVM.cpp | 1 + src/BackLLVM.h | 1 + test/atmega1284p/Makefile | 52 +++++++++ test/atmega1284p/bitstruct-field-i5.rob | 1 + test/atmega1284p/bsscheck.rob | 1 + test/atmega1284p/bssinjcheck.rob | 1 + test/atmega1284p/datacheck.rob | 1 + test/atmega1284p/float.rob | 1 + test/atmega1284p/globaldata.rob | 1 + test/atmega1284p/globals.rob | 1 + test/atmega1284p/itoa.rob | 1 + test/atmega1284p/memcpycheck.rob | 1 + test/atmega1284p/robcmp-simavr-debug | 1 + test/atmega1284p/run_avr | 1 + test/atmega1284p/runtest.sh | 1 + test/atmega1284p/runtrace.sh | 1 + test/atmega1284p/uart.rob | 1 + test/atmega1284p/uartdata.rob | 1 + test/stm32f1/Makefile | 54 +++++++++ test/stm32f1/blink.rob | 20 ++++ test/stm32f1/example.rob | 41 +++++++ test/stm32f1/runtest.sh | 27 +++++ test/stm32f1/uart.rob | 41 +++++++ 26 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 lib/atmega1284p.ld create mode 100644 lib/atmega1284p.rob create mode 100644 test/atmega1284p/Makefile create mode 120000 test/atmega1284p/bitstruct-field-i5.rob create mode 120000 test/atmega1284p/bsscheck.rob create mode 120000 test/atmega1284p/bssinjcheck.rob create mode 120000 test/atmega1284p/datacheck.rob create mode 120000 test/atmega1284p/float.rob create mode 120000 test/atmega1284p/globaldata.rob create mode 120000 test/atmega1284p/globals.rob create mode 120000 test/atmega1284p/itoa.rob create mode 120000 test/atmega1284p/memcpycheck.rob create mode 120000 test/atmega1284p/robcmp-simavr-debug create mode 120000 test/atmega1284p/run_avr create mode 120000 test/atmega1284p/runtest.sh create mode 120000 test/atmega1284p/runtrace.sh create mode 120000 test/atmega1284p/uart.rob create mode 120000 test/atmega1284p/uartdata.rob create mode 100644 test/stm32f1/Makefile create mode 100644 test/stm32f1/blink.rob create mode 100644 test/stm32f1/example.rob create mode 100755 test/stm32f1/runtest.sh create mode 100644 test/stm32f1/uart.rob diff --git a/lib/Makefile b/lib/Makefile index a2a586d..6d2ff32 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,5 +1,5 @@ -GEN=avr5.o +GEN=avr5.o avr51.o all: ${GEN} @@ -8,5 +8,10 @@ avr5.o: avr5.S @#avr-gcc -mmcu=avr5 -O3 -c $< clang --target=avr -mmcu=avr5 -O3 -c $< +avr51.o: avr51.S + @#here we are interested in the fastest possible code, intead of size + @#avr-gcc -mmcu=avr5 -O3 -c $< + clang --target=avr -mmcu=avr51 -O3 -c $< + clean: rm -f ${GEN} diff --git a/lib/atmega1284p.ld b/lib/atmega1284p.ld new file mode 100644 index 0000000..1c114b9 --- /dev/null +++ b/lib/atmega1284p.ld @@ -0,0 +1,17 @@ +/* + * RobCmp linker script for atmega1284p + */ + +MEMORY +{ + text (rx) : ORIGIN = 0, LENGTH = 128K + data (rw!x) : ORIGIN = 0x800100, LENGTH = 16K + eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 4K + fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K + lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K + signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K + user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = 1K +} + +INCLUDE avr5.ld + diff --git a/lib/atmega1284p.rob b/lib/atmega1284p.rob new file mode 100644 index 0000000..7bab194 --- /dev/null +++ b/lib/atmega1284p.rob @@ -0,0 +1,147 @@ +/* + * Robcmp interruptions vector for atmega1284p + */ + +int8 main(); + +void __do_copy_data() naked { +asm " + ldi r17, hi8(__data_end) + ldi r26, lo8(__data_start) + ldi r27, hi8(__data_start) + ldi r30, lo8(__data_load_start) + ldi r31, hi8(__data_load_start) + rjmp __do_copy_data_start + __do_copy_data_loop: + lpm r0, Z+ + st X+, r0 + __do_copy_data_start: + cpi r26, lo8(__data_end) + cpc r27, r17 + brne __do_copy_data_loop + ret"; +} + +void __do_clear_bss() naked { +asm " + ldi r17, hi8(__bss_end) + ldi r26, lo8(__bss_start) + ldi r27, hi8(__bss_start) + rjmp __do_clear_bss_start + __do_clear_bss_loop: + st X+, r1 + __do_clear_bss_start: + cpi r26, lo8(__bss_end) + cpc r27, r17 + brne __do_clear_bss_loop + ret"; +} + +void __delay_us() naked { +asm " + ldi r18, 5 + __delay_ms_loop: + dec r18 + brne __delay_ms_loop + nop + ret"; +} + +/* Weak definitions for supported interruptions + */ + void irq_usart_rx() naked, weak, section __irqs { } + void irq_usart_tx() naked, weak, section __irqs { } + +/* Timer0 is used to provide milliseconds time readings + */ + const fcpu = 16E6; + const cycles_per_us = fcpu / 1E6; + const usec_per_ovf = (64 * 256) / cycles_per_us; + const millis_per_ovf = usec_per_ovf / 1000; + const millis_frac_per_ovf = uint16(usec_per_ovf % 1000); + timer0_millis = uint32(0); + timer0_fract = uint16(0); + + void irq_timer0_ovf() signal, weak, section __irqs { + timer0_millis += millis_per_ovf; + timer0_fract += millis_frac_per_ovf; + if (timer0_fract > 1000) { + timer0_fract -= 1000; + timer0_millis += 1; + } + } + + register int8 SREG at 0x5f; + + uint32 millis() { + sreg_bkp = SREG; + asm "cli"; + result = timer0_millis; + SREG = sreg_bkp; + return result; + } + +void __default_irq() naked, section __irqs { + asm "jmp __default_irq"; +} + +void __vectors() naked, section __isr { + + /* atmega1284p has 31 interruptions */ + asm "jmp __init"; + asm "jmp __default_irq"; // IRQ0 + asm "jmp __default_irq"; // IRQ1 + asm "jmp __default_irq"; // IRQ2 + asm "jmp __default_irq"; // PCINT0 + asm "jmp __default_irq"; // PCINT1 + asm "jmp __default_irq"; // PCINT2 + asm "jmp __default_irq"; // PCINT3 + asm "jmp __default_irq"; // Watchdog Timer + asm "jmp __default_irq"; // Timer2 Compare A + asm "jmp __default_irq"; // Timer2 Compare B + asm "jmp __default_irq"; // Timer2 Overflow + asm "jmp __default_irq"; // Timer1 Capture + asm "jmp __default_irq"; // Timer1 Compare A + asm "jmp __default_irq"; // Timer1 Compare B + asm "jmp __default_irq"; // Timer1 Overflow + asm "jmp __default_irq"; // Timer0 Compare A + asm "jmp __default_irq"; // Timer0 Compare B + asm "jmp irq_timer0_ovf"; // Timer0 Overflow + asm "jmp __default_irq"; // SPI Transfer Complete + asm "jmp irq_usart_rx"; // USART, RX Complete + asm "jmp __default_irq"; // USART, UDR Empty + asm "jmp irq_usart_tx"; // USART, TX Complete + asm "jmp __default_irq"; // Analog Comparator + asm "jmp __default_irq"; // ADC Conversion + asm "jmp __default_irq"; // EEPROM Ready + asm "jmp __default_irq"; // 2-wire Serial Interface (TWI) + asm "jmp __default_irq"; // Store Program Memory Ready + asm "jmp __default_irq"; // USART1 Rx Complete + asm "jmp __default_irq"; // USART1 Data Register Empty + asm "jmp __default_irq"; // USART1 Tx Complete + + asm "__init:"; + // clear r1 (zero reg) + asm "clr r1"; + // clear sreg + asm "out 0x3f, r1"; + // set stack at 0x40FF (0x100+16K-1) + asm "ldi r28, 0xFF"; + asm "ldi r29, 0x40"; + asm "out 0x3e, r29"; + asm "out 0x3d, r28"; + + // copy global vars init data + __do_copy_data(); + + // clear zeroed global vars + __do_clear_bss(); + + main(); + + // if main returns, disable interruptions and sleep. + // this is used to quit simavr in our tests + asm "cli"; + asm "sleep"; + } + diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index a3884e4..7f4007b 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -57,6 +57,7 @@ TargetInfo supportedTargets[__last_target] = { {rb_avr, "attiny85", "avr", "attiny85", "+avr25", tint16}, {rb_avr, "atmega328p", "avr", "atmega328p", "+avr5", tint16}, {rb_avr, "atmega32u4", "avr", "atmega32u4", "+avr5", tint16}, + {rb_avr, "atmega1284p", "avr", "atmega1284p", "+avr51", tint16}, {rb_arm, "stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, diff --git a/src/BackLLVM.h b/src/BackLLVM.h index f487106..610b1a3 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -28,6 +28,7 @@ enum SupportedTargets { st_attiny85, st_atmega328p, st_atmega32u4, + st_atmega1284p, // stm32 st_stm32f1, diff --git a/test/atmega1284p/Makefile b/test/atmega1284p/Makefile new file mode 100644 index 0000000..787aa4b --- /dev/null +++ b/test/atmega1284p/Makefile @@ -0,0 +1,52 @@ +ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) +ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/atmega1284p.o + +ROBCMP=../../build/robcmp +INCLUDES=-I ../../lib + +ifndef OPT +#OPT=-g -O0 +OPT=-Oz +endif + +LD_FLAGS=-nostdlib -entry=main -L../../lib -Tatmega1284p.ld ../../lib/avr51.o +LD_FLAGS+=-Bstatic +LD_FLAGS+=--gc-sections +LD_FLAGS+=--lto=thin + +DEPENDS=${ROBCMP} Makefile +LINK_DEPENDS=out/atmega1284p.o + +all: out test + +out: + mkdir -p out + +out/atmega1284p.o : ../../lib/atmega1284p.rob ${DEPENDS} + ${ROBCMP} -a atmega1284p ${OPT} -o $@ $< + +out/atmega1284p.ll : ../../lib/atmega1284p.rob ${DEPENDS} + ${ROBCMP} -a atmega1284p ${OPT} $< > $@ + +.SECONDARY: +out/%.o : %.rob out/atmega1284p.o ${DEPENDS} + ${ROBCMP} -bdep -a atmega1284p ${OPT} ${INCLUDES} -o $@ $< + +out/%.ll : %.rob ${DEPENDS} + ${ROBCMP} -bdep -a atmega1284p ${OPT} ${INCLUDES} $< > $@ + +%.tt : %.rob ${DEPENDS} + @-./runtest.sh $< $(patsubst %.rob,out/%,$<) + +out/% : out/%.o ${LINK_DEPENDS} + # exchange here if ld.lld show relocation errors + ld.lld ${LD_FLAGS} $^ -o $@ + #avr-ld ${LD_FLAGS} $^ -o $@ + +test: ${ALL_TT} + +clean: + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} + diff --git a/test/atmega1284p/bitstruct-field-i5.rob b/test/atmega1284p/bitstruct-field-i5.rob new file mode 120000 index 0000000..8246bd7 --- /dev/null +++ b/test/atmega1284p/bitstruct-field-i5.rob @@ -0,0 +1 @@ +../atmega328p/bitstruct-field-i5.rob \ No newline at end of file diff --git a/test/atmega1284p/bsscheck.rob b/test/atmega1284p/bsscheck.rob new file mode 120000 index 0000000..3fe20d6 --- /dev/null +++ b/test/atmega1284p/bsscheck.rob @@ -0,0 +1 @@ +../atmega328p/bsscheck.rob \ No newline at end of file diff --git a/test/atmega1284p/bssinjcheck.rob b/test/atmega1284p/bssinjcheck.rob new file mode 120000 index 0000000..18ae991 --- /dev/null +++ b/test/atmega1284p/bssinjcheck.rob @@ -0,0 +1 @@ +../atmega328p/bssinjcheck.rob \ No newline at end of file diff --git a/test/atmega1284p/datacheck.rob b/test/atmega1284p/datacheck.rob new file mode 120000 index 0000000..016886b --- /dev/null +++ b/test/atmega1284p/datacheck.rob @@ -0,0 +1 @@ +../atmega328p/datacheck.rob \ No newline at end of file diff --git a/test/atmega1284p/float.rob b/test/atmega1284p/float.rob new file mode 120000 index 0000000..ba4a261 --- /dev/null +++ b/test/atmega1284p/float.rob @@ -0,0 +1 @@ +../atmega328p/float.rob \ No newline at end of file diff --git a/test/atmega1284p/globaldata.rob b/test/atmega1284p/globaldata.rob new file mode 120000 index 0000000..58624a6 --- /dev/null +++ b/test/atmega1284p/globaldata.rob @@ -0,0 +1 @@ +../atmega328p/globaldata.rob \ No newline at end of file diff --git a/test/atmega1284p/globals.rob b/test/atmega1284p/globals.rob new file mode 120000 index 0000000..fc74855 --- /dev/null +++ b/test/atmega1284p/globals.rob @@ -0,0 +1 @@ +../atmega328p/globals.rob \ No newline at end of file diff --git a/test/atmega1284p/itoa.rob b/test/atmega1284p/itoa.rob new file mode 120000 index 0000000..89cdfe3 --- /dev/null +++ b/test/atmega1284p/itoa.rob @@ -0,0 +1 @@ +../atmega328p/itoa.rob \ No newline at end of file diff --git a/test/atmega1284p/memcpycheck.rob b/test/atmega1284p/memcpycheck.rob new file mode 120000 index 0000000..4d0b1d5 --- /dev/null +++ b/test/atmega1284p/memcpycheck.rob @@ -0,0 +1 @@ +../atmega328p/memcpycheck.rob \ No newline at end of file diff --git a/test/atmega1284p/robcmp-simavr-debug b/test/atmega1284p/robcmp-simavr-debug new file mode 120000 index 0000000..c9994e3 --- /dev/null +++ b/test/atmega1284p/robcmp-simavr-debug @@ -0,0 +1 @@ +../../build/robcmp-simavr-debug \ No newline at end of file diff --git a/test/atmega1284p/run_avr b/test/atmega1284p/run_avr new file mode 120000 index 0000000..1dc1d13 --- /dev/null +++ b/test/atmega1284p/run_avr @@ -0,0 +1 @@ +../../platformio/toolchain-robcmp/bin/run_avr \ No newline at end of file diff --git a/test/atmega1284p/runtest.sh b/test/atmega1284p/runtest.sh new file mode 120000 index 0000000..d72879e --- /dev/null +++ b/test/atmega1284p/runtest.sh @@ -0,0 +1 @@ +../atmega328p/runtest.sh \ No newline at end of file diff --git a/test/atmega1284p/runtrace.sh b/test/atmega1284p/runtrace.sh new file mode 120000 index 0000000..fc1aeb1 --- /dev/null +++ b/test/atmega1284p/runtrace.sh @@ -0,0 +1 @@ +../atmega328p/runtrace.sh \ No newline at end of file diff --git a/test/atmega1284p/uart.rob b/test/atmega1284p/uart.rob new file mode 120000 index 0000000..a97d855 --- /dev/null +++ b/test/atmega1284p/uart.rob @@ -0,0 +1 @@ +../atmega328p/uart.rob \ No newline at end of file diff --git a/test/atmega1284p/uartdata.rob b/test/atmega1284p/uartdata.rob new file mode 120000 index 0000000..60d70e6 --- /dev/null +++ b/test/atmega1284p/uartdata.rob @@ -0,0 +1 @@ +../atmega328p/uartdata.rob \ No newline at end of file diff --git a/test/stm32f1/Makefile b/test/stm32f1/Makefile new file mode 100644 index 0000000..6045c5b --- /dev/null +++ b/test/stm32f1/Makefile @@ -0,0 +1,54 @@ +ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) +ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/stm32f1.o + +TOOL_OPEN_OCD_FOLDER=~/.platformio/packages/tool-openocd +ROBCMP=../../build/robcmp +INCLUDES=-I ../../lib + +ifndef OPT +#OPT=-g -O0 +OPT=-Oz +endif + +LD_FLAGS=-nostdlib -entry=main -L../../lib -Tstm32f1.ld +LD_FLAGS+=-Bstatic +LD_FLAGS+=--gc-sections +LD_FLAGS+=--lto=thin + +DEPENDS=${ROBCMP} Makefile +LINK_DEPENDS=out/stm32f1.o + +all: out test + +out: + mkdir -p out + +out/stm32f1.o : ../../lib/stm32f1.rob ${DEPENDS} + ${ROBCMP} -a stm32f1 ${OPT} -o $@ $< + +out/stm32f1.ll : ../../lib/stm32f1.rob ${DEPENDS} + ${ROBCMP} -a stm32f1 ${OPT} $< > $@ + +.SECONDARY: +out/%.o : %.rob out/stm32f1.o ${DEPENDS} + ${ROBCMP} -bdep -a stm32f1 ${OPT} ${INCLUDES} -o $@ $< + +out/%.ll : %.rob ${DEPENDS} + ${ROBCMP} -bdep -a stm32f1 ${OPT} ${INCLUDES} $< > $@ + +%.tt : %.rob ${DEPENDS} + @-./runtest.sh $< $(patsubst %.rob,out/%,$<) + +%.up : %.tt ${DEPENDS} + ${TOOL_OPEN_OCD_FOLDER}/bin/openocd -f ${TOOL_OPEN_OCD_FOLDER}/scripts/interface/stlink.cfg -f ${TOOL_OPEN_OCD_FOLDER}/scripts/target/stm32f1x.cfg -c "program $(patsubst %.tt,out/%,$<) reset exit" + +out/% : out/%.o ${LINK_DEPENDS} + ld.lld ${LD_FLAGS} $^ -o $@ + +test: ${ALL_TT} + +clean: + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} + diff --git a/test/stm32f1/blink.rob b/test/stm32f1/blink.rob new file mode 100644 index 0000000..06ff3b1 --- /dev/null +++ b/test/stm32f1/blink.rob @@ -0,0 +1,20 @@ +/* + * Blinks the board default led + */ + +use intfs.ports; +use arch.stm32.stm32f1; + +int16 main() { + mmcu = stm32f1(); + led = mmcu.c13; + + led.mode(port_mode.output); + + loop { + led.set(true); + mmcu.wait_ms(500); + led.set(false); + mmcu.wait_ms(500); + } +} diff --git a/test/stm32f1/example.rob b/test/stm32f1/example.rob new file mode 100644 index 0000000..e02e4d2 --- /dev/null +++ b/test/stm32f1/example.rob @@ -0,0 +1,41 @@ + +use intfs.ports; +use arch.stm32.stm32f1; +use convert.itoa; + +void run_test(stm32f1 mmcu) { + mmcu.wait_ms(500); +} + +int16 main() { + mmcu = stm32f1(); + serial = mmcu.uart2; + serial.setup(9600); + serial.enable(); + + //led = mmcu.c13; + //led.mode(port_mode.output); + + loop { + start = mmcu.millis(); + + run_test(mmcu); + + time = mmcu.millis() - start; + + timestr = {'0': 10}; + itoa(time, 10, timestr); + + serial.write_array(timestr); + serial.write('\r'); + serial.write('\n'); + + /*led.set(true); + mmcu.wait_ms(500); + led.set(false); + mmcu.wait_ms(500);*/ + + } + return 0; +} + diff --git a/test/stm32f1/runtest.sh b/test/stm32f1/runtest.sh new file mode 100755 index 0000000..5676a41 --- /dev/null +++ b/test/stm32f1/runtest.sh @@ -0,0 +1,27 @@ +#!/bin/bash +#CMD="./robcmp-simavr-debug -c 16000000 -m atmega328p -f $2" +CMD="echo \"no simulator for stm32f1 yet.\"" + +GREEN="\033[0;32m" +RED="\033[0;31m" +NC="\033[0m" + +echo -n " $1 " +make -s $2 +if [ "$?" -eq 0 ]; then + if [ "$V" = "1" ]; then + ${CMD} + else + timeout 10s ${CMD} &> /dev/null + fi + STATUS=$? + #if [ "${STATUS}" -eq 0 ]; then + # echo -e \\r${GREEN}[PASS]\\t\\t${NC} + #else + # echo -e \\r${RED}[FAILED] ${STATUS}\\t${NC} + #fi + ${CMD} +else + echo -e \\r${RED}[BUILD FAILED]\\t${NC} +fi + diff --git a/test/stm32f1/uart.rob b/test/stm32f1/uart.rob new file mode 100644 index 0000000..1863f45 --- /dev/null +++ b/test/stm32f1/uart.rob @@ -0,0 +1,41 @@ + +use intfs.ports; +use arch.stm32.stm32f1; +use convert.itoa; + +void run_test() { + +} + +int16 main() { + mmcu = stm32f1(); + serial = mmcu.uart2; + serial.setup(9600); + serial.enable(); + + //led = mmcu.c13; + //led.mode(port_mode.output); + + loop { + start = mmcu.time(); + + run_test(); + + time = mmcu.time() - start; + + timestr = {'0': 10}; + itoa(time, 10, timestr); + + serial.write(timestr); + serial.write('\r'); + serial.write('\n'); + + /*led.set(true); + mmcu.wait_ms(500); + led.set(false); + mmcu.wait_ms(500);*/ + + } + return 0; +} + From 376267606542ac798137abdf6472f2aa9b630359 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 9 Nov 2024 15:49:46 -0300 Subject: [PATCH 092/117] Small fix when passing array as argument to function. When the array is not const. --- src/FunctionCall.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 5e766fa..a7fa4f6 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -132,8 +132,8 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock for(const string& p: params) { Node *coerced; Value *value; - if (param->isConstExpr()) { - Node *size = param->findMember("size"); + Node *size = param->findMember("size"); + if (size) { coerced = PropagateTypes::coerceTo(size, tint32u); value = coerced->generate(func, block, allocblock); } else { From fdcd29ee6db9356017ff4628153d46ac8ddc118a Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Tue, 19 Nov 2024 17:02:20 -0300 Subject: [PATCH 093/117] Missing stm32 functions. --- lib/arch/stm32/stm32f1.rob | 115 ++++++++++++++++++++++++++++++--- lib/arch/stm32/stm32f1regs.rob | 63 ++++++++++++++++++ 2 files changed, 170 insertions(+), 8 deletions(-) diff --git a/lib/arch/stm32/stm32f1.rob b/lib/arch/stm32/stm32f1.rob index fd86b1c..0e3dfe2 100644 --- a/lib/arch/stm32/stm32f1.rob +++ b/lib/arch/stm32/stm32f1.rob @@ -16,6 +16,48 @@ type stm32f1 implements mcu { return; } + a2 implements digitalport { + void mode_input(PIN_MODE mode, INPUT_MODE cnf) inline { + GPIOA_CRL.mode2 = mode; + GPIOA_CRL.cnf2 = cnf; + } + void mode_output(PIN_MODE mode, OUTPUT_MODE cnf) inline { + GPIOA_CRL.mode2 = mode; + GPIOA_CRL.cnf2 = cnf; + } + void mode(port_mode m) { + APB2EN.iopa = true; + if (m == port_mode.input) { + mode_input(PIN_MODE.INPUT, INPUT_MODE.PULLUPDOWN); + } else { + mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.PUSHPULL); + } + } + void set(bool v) inline { GPIOA_ODR.odr2 = v; } + bool get() inline { return GPIOA_IDR.idr2; } + } + + a3 implements digitalport { + void mode_input(PIN_MODE mode, INPUT_MODE cnf) inline { + GPIOA_CRL.mode3 = mode; + GPIOA_CRL.cnf3 = cnf; + } + void mode_output(PIN_MODE mode, OUTPUT_MODE cnf) inline { + GPIOA_CRL.mode3 = mode; + GPIOA_CRL.cnf3 = cnf; + } + void mode(port_mode m) { + APB2EN.iopa = true; + if (m == port_mode.input) { + mode_input(PIN_MODE.INPUT, INPUT_MODE.PULLUPDOWN); + } else { + mode_output(PIN_MODE.OUTPUT50MHz, OUTPUT_MODE.PUSHPULL); + } + } + void set(bool v) inline { GPIOA_ODR.odr3 = v; } + bool get() inline { return GPIOA_IDR.idr3; } + } + c13 implements digitalport { void mode(port_mode m) { APB2EN.iopc = true; @@ -86,6 +128,14 @@ type stm32f1 implements mcu { } } + uint32 micros() { + return SYSTICK_VAL / (clock()/1E6); + } + + uint32 millis() { + return micros() / 1000; + } + spi implements databus { /* setup hardware SPI at: xx = MOSI @@ -100,20 +150,67 @@ type stm32f1 implements mcu { bool has_data() { return false; } bool start_transaction(uint16 address) { return true; } void end_transaction() { } + void async_read_to(interrupt_i8 i) {} databus_protocol get_protocol() { return databus_protocol.SPI; } } - uart0 implements databus { - void setup(uint32 baud) {} - void enable() {} - void disable() {} - void write(uint8 b) {} - void write_array(int8[] data) {} - uint8 read() { return 0; } - bool has_data() { return false; } + uart2 implements databus { + void setup(uint32 baud) { + APB1EN.usart2 = true; // enable usart2 clock + //AHBENR.sdio = true; // enable SDIO clock + APB2EN.afio = true; //? enable alternate function I/O clock + APB2EN.iopa = true; // port A clock + + // set ports a2 (output TX) and a3 (input RX) + a2.mode_output(PIN_MODE.OUTPUT2MHz, OUTPUT_MODE.APUSH_PULL); + a3.mode_input(PIN_MODE.INPUT, INPUT_MODE.FLOATING); + + // assuming reset configuration, that is 8 bits per byte, + // no parity checks, and 1 “stop bit”. + + // set baudrate + uartdiv = clock() / baud; + USART2_BRR.DIV_Fraction = uint4(uartdiv % 16); + USART2_BRR.DIV_Mantissa = uint12(uartdiv / 16); + } + + void async_read_to(interrupt_i8 i) {} + + void enable() { + USART2_CR1.RE = true; // receptor + USART2_CR1.TE = true; // transmiter + USART2_CR1.UE = true; // usart enable + } + + void disable() { + USART2_CR1.UE = false; + } + + void write(uint8 b) inline { + while !USART2_SR.TXE; + USART2_DR.DR = b; + } + + void write_array(int8[] data) { + i = 0u; + while i < data.size { + write(uint8(data[i])); + i++; + } + } + + uint8 read() { + while !USART2_SR.RXNE; + return uint8(USART2_DR.DR); + } + + bool has_data() { + return USART2_SR.RXNE; + } + bool start_transaction(uint16 address) { return true; } void end_transaction() {} @@ -158,6 +255,8 @@ type stm32f1 implements mcu { I2C1_CCR.ccr = uint12(((1.0/400000)/2) / (3.0/clock())); I2C1_TRISE = uint16(clock()/1E6*0.3+1); } + + void async_read_to(interrupt_i8 i) {} void enable() { I2C1_CR1.pe = true; diff --git a/lib/arch/stm32/stm32f1regs.rob b/lib/arch/stm32/stm32f1regs.rob index 8d9928b..261b2e6 100644 --- a/lib/arch/stm32/stm32f1regs.rob +++ b/lib/arch/stm32/stm32f1regs.rob @@ -438,3 +438,66 @@ register I2C_SR2_t I2C2_SR2 at 0x40005818; register I2C_CCR_t I2C2_CCR at 0x4000581C; // I2C 2 T RISE register register uint16 I2C2_TRISE at 0x40005820; + +/* + * USART types + */ + + type SR_t { + PE = false; // Parity error + FE = false; // Framing error + NE = false; // Noise error flag + ORE = false; // Overrun error + IDLE = false; // IDLE line detected + RXNE = false; // Read data register not empty + TC = false; // Transmission complete + TXE = false; // Transmit data register empty + LBD = false; // LIN break detection flag + CTS = false; // CTS flag + _res1 = uint16(0); // Reserved, 22 bits + _res2 = uint6(0); // + } + + type CR1_t { + SBK = false; // Send break + RWU = false; // Receiver wakeup + RE = false; // Receiver enable + TE = false; // Transmitter enable + IDLEIE = false; // IDLE interrupt enable + RXNEIE = false; // RXNE interrupt enable + TCIE = false; // Transmission complete interrupt enable + TXEIE = false; // TXE interrupt enable + PEIE = false; // PE interrupt enable + PS = false; // Parity selection + PCE = false; // Parity control enable + WAKE = false; // Wakeup method + M = false; // Word length + UE = false; // USART enable + _res1 = uint16(0); // Reserved, 18 bits + _res2 = uint2(0); // + } + + type DR_t { + DR = uint9(0); // Data value + _res1 = uint16(0); // Reserved, 23 bits + _res2 = uint7(0); // + } + + type BRR_t { + DIV_Fraction = uint4(0); // fraction of USARTDIV + DIV_Mantissa = uint12(0); // mantissa of USARTDIV + _res1 = uint16(0); // Reserved, 16 bits + } + + // Status register + register SR_t USART2_SR at 0x40004400; + + // Data register + register DR_t USART2_DR at 0x40004404; + + // Baud rate register + register BRR_t USART2_BRR at 0x40004408; + + // Control register 1 + register CR1_t USART2_CR1 at 0x4000440C; + From 61d854bfcde27ceb16fa9bf059ae614395878b17 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Thu, 28 Nov 2024 14:11:36 -0300 Subject: [PATCH 094/117] Fix function call passing array size. --- src/FunctionCall.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index a7fa4f6..e4c7870 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -131,18 +131,20 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock for(const string& p: params) { Node *coerced; - Value *value; + Value *value = NULL; Node *size = param->findMember("size"); if (size) { coerced = PropagateTypes::coerceTo(size, tint32u); value = coerced->generate(func, block, allocblock); - } else { + } + if (!value) { string pname = param->getName() + p; Load ld(Identifier(pname, param->getLoc())); ld.setScope(func); coerced = PropagateTypes::coerceTo(&ld, tint32u); value = coerced->generate(func, block, allocblock); } + assert(value != NULL && "must pass the array size."); args.push_back(value); dataTypes.push_back(coerced->getDataType()); } From cb4b22db111daea8c52a239c6f5c6474d5f3af3d Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 4 Dec 2024 11:11:20 -0300 Subject: [PATCH 095/117] Basic float support to stm32f1, using pre-built libgcc. --- hack/avr/Makefile | 13 ++++++++----- hack/stm32/Makefile | 22 ++++++++++++---------- lib/Makefile | 5 ++++- lib/arm-eabi-libgcc.a | Bin 0 -> 1514234 bytes lib/arm-missing.c | 16 ++++++++++++++++ lib/avr51.S | 1 + lib/convert/itoa.rob | 7 +++++-- lib/stm32f1.rob | 2 +- platformio/platform/builder/main.py | 2 ++ test/atmega1284p/run_avr | 1 - test/debug/platformio.ini | 15 ++++++++++++++- test/stm32f1/Makefile | 2 +- 12 files changed, 64 insertions(+), 22 deletions(-) create mode 100644 lib/arm-eabi-libgcc.a create mode 100644 lib/arm-missing.c create mode 120000 lib/avr51.S delete mode 120000 test/atmega1284p/run_avr diff --git a/hack/avr/Makefile b/hack/avr/Makefile index 67b6c56..195b50a 100644 --- a/hack/avr/Makefile +++ b/hack/avr/Makefile @@ -1,9 +1,9 @@ INCLUDES=-I/Users/thborges/.platformio/packages/toolchain-atmelavr/avr/include #AVRLIB=-L~/.platformio/packages/toolchain-atmelavr/lib/gcc/avr/7.3.0/avr5 -lgcc -CC=/usr/local/robllvm/bin/clang -LLC=/usr/local/robllvm/bin/llc +CC=clang +LLC=llc CCPLAT=-target avr -mmcu=atmega328p -DF_CPU=16000000 -ROBCMP=../../robcmp +ROBCMP=../../build/robcmp AVRDUDECFG=-C /Users/thborges/.platformio/packages/tool-avrdude/avrdude.conf AVRDUDEPORT=`ls /dev/cu.usb*` @@ -36,10 +36,13 @@ all: ${ROBCMP} ${ALL} %.elf : %.o @#${CC} -v ${CCPLAT} ${AVRLIB} $< -o $@ @#avr-gcc -v -mmcu=atmega328p $< -o $@ - avr-ld -o $@ -Tdata=0x800100 $< + #avr-ld -o $@ -Tdata=0x800100 $< + ld.lld -o $@ -Tdata=0x800100 $< + %.hex : %.elf - avr-objcopy -Oihex $< $@ + #avr-objcopy -Oihex $< $@ + llvm-objcopy -Oihex $< $@ %.up: %.hex avrdude ${AVRDUDECFG} -v -V -c arduino -p m328p -U flash:w:$<:i -P ${AVRDUDEPORT} diff --git a/hack/stm32/Makefile b/hack/stm32/Makefile index 5e5e397..d37acf4 100644 --- a/hack/stm32/Makefile +++ b/hack/stm32/Makefile @@ -1,10 +1,11 @@ -#GCC=~/.platformio/packages/toolchain-gccarmnoneeabi/bin/arm-none-eabi-gcc -CC=/usr/local/robllvm/bin/clang -LLC=/usr/local/robllvm/bin/llc -OBJCOPY=/usr/local/robllvm/bin/llvm-objcopy +CC=~/.platformio/packages/toolchain-gccarmnoneeabi/bin/arm-none-eabi-gcc +#CC=/usr/local/opt/llvm/bin/clang +LLC=/usr/local/opt/llvm/bin/llc +OBJCOPY=/usr/local/opt/llvm/bin/llvm-objcopy INCLUDES= -CCPLAT=-target arm-none-eabi -mcpu=cortex-m3 -mthumb -ROBCMP=../../robcmp +#CCPLAT=-target arm-none-eabi -mcpu=cortex-m3 -mthumb +CCPLAT=-mcpu=cortex-m3 -mthumb +ROBCMP=../../build/robcmp USBPORT=`ls /dev/cu.usb*` @@ -15,10 +16,11 @@ ALL=${ALL_C} ${ALL_ROB} all: ${ROBCMP} ${ALL} %.c.ll: %.c - ${CC} ${CCPLAT} -Oz -S -emit-llvm ${INCLUDES} $< -o $@ + #${CC} ${CCPLAT} -Oz -S -emit-llvm ${INCLUDES} $< -o $@ + ${CC} ${CCPLAT} -Os -S -emit-llvm ${INCLUDES} $< -o $@ %.c.o: %.c - ${CC} ${CCPLAT} -Oz -c ${INCLUDES} $< -o $@ + ${CC} -v ${CCPLAT} -Os -c ${INCLUDES} $< -o $@ @@ -34,8 +36,8 @@ all: ${ROBCMP} ${ALL} ${LLC} $< -o $@ -filetype=asm %.elf : %.o - ${CC} -v ${CCPLAT} -nostdlib -Wl,-entry=main -Wl,-Tmemory.lld.ld $< -o $@ - @#${GCC} -mthumb -mcpu=cortex-m3 -nostdlib -Wl,-Tmemory.gcc.ld $< -o $@ + #${CC} ${CCPLAT} -nostdlib -Wl,-entry=main -Wl,-Tmemory.lld.ld $< -o $@ + ${CC} -mthumb -mcpu=cortex-m3 -nostdlib -Wl,-Tmemory.gcc.ld $< -o $@ %.bin : %.elf diff --git a/lib/Makefile b/lib/Makefile index 6d2ff32..47bf19a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,5 +1,5 @@ -GEN=avr5.o avr51.o +GEN=avr5.o avr51.o cortex-m3-arm-missing.o all: ${GEN} @@ -13,5 +13,8 @@ avr51.o: avr51.S @#avr-gcc -mmcu=avr5 -O3 -c $< clang --target=avr -mmcu=avr51 -O3 -c $< +cortex-m3-arm-missing.o: arm-missing.c + clang --target=arm-none-eabi -mcpu=cortex-m3 -mthumb -O3 -c $< -o $@ + clean: rm -f ${GEN} diff --git a/lib/arm-eabi-libgcc.a b/lib/arm-eabi-libgcc.a new file mode 100644 index 0000000000000000000000000000000000000000..bed37c8400203af4303a6d31626e22dd1090a529 GIT binary patch literal 1514234 zcmeFa3w%|@wLiYjGbbk}CvS=rF+qw*5tD#`7Bw#pV3F{MTx+c%A><@#Z7UHU z^>r=M)}LBSskOG(TD4TY)t?eCwbpXI7VvQ`QmfR9deV9mMQg$0|GW0yv-j+o9db~w z!vDwQv$OYFvu4ejHEYe9J$v>(B{Lhk8e7kZo?PrsWv7&tmrkEvI=!s8xYWp!{}&gR zPcNHVZs3A!&hZoA#qqNpME8RJm*wX1t16-o zd-VB<`1toN=JEJdM11@1^34P7f``dhcLVv(y^wt8pGCf<<>YI8i+pXT zk#A*~e4Qx6NAf}PT{MP#m)uIeOF_RDc~|+#cg;FcioyvgMM%6jrIeV6<#De|wFPyUsg$e#r5MN#r!(n0=j z>>&T;Pmuqc6Ul$=4dh>k^55P={{M3p`ER|4{2Om4{~clS|6~REe|`b^@7qHD`^S_2 z->xP9qnDEZvEAfpj50SW}(qCmzy6v$dZft>LaD7uOQ$5c^ZH1dwWfC49sp}@qKC@^^g z1y1o(V8#{-%v?)>sy!4)JWqkMHdA0e$}c&M0_TmTzy|H{E_eN0Qz%mN@$5Jq~ zn}V^)6wDn%!NMp7N8&u@O$v_PNx|_rpR}2RW%p3g^P)=%8TDc@&(3^0kvG zxadv_E3Kp;Hm=@OkPOA3sV&Q`dbw2T|vRiU!veOdnouX zEfidb{9B%&;P)?};GN?s_^&AcbI9-j>U(G`1%C(n=lm4>GxFX9&E88X_+A*p;SCi0 zAfG~^77D?aLa{CiWETk^;Qb?TuY&^o<*TG;CVU9 zd~-5|{$)LdZk$h{?}FxL)cpgLyL~r>?%Y73yAM$4zReW6|56J5>I@2PM)@r${{(2C zT0)`UBkvi|KM(va@O*g$h5mdAh2Gdep}&rz5c(;!7xL_zNTGk+Nnu|;g)>g0aP%$; z$45~(?zAp>Gh_$Rkh_-8E?{snLkTteZ8&Y*A~>f8dlCoZ7y?@-_G-=y#} zODO#O!xY|ydS3?5KjZohltEj=18XV#?yVHw7pCw(x+sHoQbzcB%7|7`M)p0FQLvRV zK64gjjKX;g&f_kij0uYGJeoS89(lzjGscbyU(DEP2l~&gOu?QXdZ!_TOOv2C%_Z2Fym>^ zZ@-W-{%Zwg?0lLsUINXlpnnbZ^ygE?o0n3?UgZDnCCb>Jpos50iUi-HNaR|I#Nrgm zpGJ`p<0-;694H^Cm_9j{4uLVhLp)gS_J&rp)8VQ|9>flsV~I$}Am2nNv1V=JeAj^Yj+VtOVWK6_k19 z^OSi_6=hz34`r^ui!yH-L7BI#rOY2(LYcSkq0BqyQ|8@gQRclUi*YaWA=LK>^7~Sh z`RhfL`8(wO=NXi_9p`5sq|6r}(~CDy<}24y=Bw{g=IhHS^Ud=pbMOhud}lIc?w?4R z2X3OM?*K(J_E9uz8Aan;DVkqS(UB7=I(iI6i*Y_4G$;5eI&lR>OF=W`X^KvtM$ywj zSFwSjHBpM56{hIfT@+oglcGzIe;)F`g1iRcTfl$Cn-uMMm!e%L--Gp=4@@L&HtMQ`3p(c6&!1C;;qO%(kp^6qY-=)EZSz!MaG=s}9^dx@e4&Y~>e zgOn8-Ls?m)C@X#yW#zp^S)WN!)@K({)|kzdHFi8@O&CjApTB{!%8)-5`7q`eH>nkfLYv~TkY60DfX_U2c17)oaQ`SYuM=Z|j zZK15ok^jxpDC^qWDQg|de&<@sx_LcieGlb-fbzFLPgy@rQP$l{DC=I-@xa5B^$_HF z1T=m7DC;-xQr7R5QP%IzqpTgse|{om{Q-G@0w0Wnv2nLkY(kh~7|&uD&tg-bpcuxp z7{;?$<((9pl~1ubms0GDdnmT>C5oMspxC+hQ0#)cD7FlF%@|gt$&zeH$O@mn5`whze?mUV;wS{6kHdE|*Pn5l>I}L{qY%;{jUki zz85@yxtp^84fSqDU0X&`_HQ;(_EV7I_o(L?od2+ovj4b(vR?-6t7lPmYCdKEbu(oT zg4f@cQ1-s(Df>VN#Y1t5M=qgw)^3XDUrX_#0~9|7_|Y#>d@OL|mr(q~Cn$dMn-rh2 zg5uNmQ2cb{SEMLjvxwqnB`ALOgA`vlp5k>kQT#j{7}Men7gBurT8jU3KE*q3r+7DL zE(Yz_o~HO^J1KtUe2QPah2qzrM)CFF^W7&XehaR*-bL}JCsTa;R*FB@Lh)VT^`{LK z--EJmfab3_51`z;kZ&J&{9`la1olu)MhE3Y-=duO4U|)K8s&`KLOI8+pd7RzXZ$kC zIq@aRDIH5WQ#Me}^f=|5KAv(aKvRRf*(f*vLdsb*f^yD1gL1ySm2&D)w$V>HZ4)V{ z9dIY$A3jYvKL+og-bp!k=Tpum@Oj`8%J~)Q-wgg+=2OmZ9;TfC!0~(V-*FS=yntgD z`24AZa(3^eoY$YHoWE32&i~v)Iq!ha-%;oLYbn={BlH&KW?n$KIXLpSQtpUplzYqu z%02ET%01psx#L$*?xYsVJ^6Xcosyv3Q*q3Eka8==Qf^`t<<7l|a_51^g7YYM$s)@A z(q_v2%6Q6cM1IS9%3T2-tM*ZD5_~QMkDrdA+@IY*x%WmXcN5C~3cMZxE#iFcZva0D z+NZiG_xCBveSQSx{sFi@t)<-EsAEqH<-YL};UCmc`M~zKbG>owVCq1eIDiA3O?UQnT@+C?+(;=7mlBAp}b#| zQ{KPfcz6fpZSJ7FEm6vQay{ieHIedu51F0^?hkKK-XE7y-piobg9Cn%2fxUB8^_-k zQQp23J{B^DgBd+d}!r;~1Z!{E0Z1;+T2~<gg%DE}#(w*miOFH!!k3n>4U5tRRWobvy&f$|4Wqx^SJ?)`mK z;Jb+m!sS$uy@U$#c2mKKOQ-3TMCQjQ{l*msc_6DDjYk8 z3O{!h6;61Q3Sm2i<;XkbK`J~I_%H6D!rIfQaMA5lxFkx2=ZC4VzJm&vJx_(LZ&6|U z1ys0dD-|Zosqm{4sqpLTsc_9cD!lStD!gVH6<+@|6|S2`g*PGpmJL++eU!ib02SW3 zf(ri?Jbr!#75)&QQ?2(Q{f-uRQU2GRQPAe z_}Y9b#F$k$a1Ryk9YKZrkpGWMsfbck6kJ3_(fL%A{V)~fjisW`;23oS6&<^eib|GI z(Fx~K(ZnrOGbjMRE*wQgUj_Y|%~W)GITc-XCly@_+`2JT z^zECd=>J5i==;;CXyb!abO+8q*+fM@-$6ycK)v^)%)<{;(dN^r=-=<5qTitI{}@k2 zPv1&KJHk}-0*)8gQqiCMRJ8k2Dtdhb75xQ#{|EW+;J~<5^!`mWf}%7c9H$YPH_(V| zKaD8BF=9Q97*$0hj(v+pj6>cDn`y-7J7`21XigbJBW65JBW41wx{yXB#?y$o&(nx+ zyhI}|+u=Tb`!0?656}&DJa-q3_%O%YXV8fMjbncojqo@=6B$LHDO|)yef{!|p8D?A zo|VhW>Khx9&GpIEZKPv+Jh91EPg+lGl1Y1-+Ad7CO~F+|bHlQ>`kpo*+|bHZO+YAg zE;0s8svew7cJ_tImq|)(zU?N|*wEfye_>lgeHXGEpiBnJWdL$IWK(6}6d9N%1Jh+- zh76o40m*g=Xz7%IHW^6DKzkP&)ShhZYLXP#-kxN1gNkktXtdo?H>go@eMj^1rWUl+ z>Vzi14$zhCSq2FIn_8TbO(wRXsmX-}4BD3VRSn%e9mzI~(Sm7DTe+R($}sWG7k4*z zG$mVPIa-_&JsnLhX6;UvE5pRE>}hvN1sHOm(_L7=z%K7Lt6bh}p4%U+*zZuh+`2Iq*rPs)AYBKN(LWA=Sx z`z6UXwjx|KnHSv_#%y9ccq7{cdR!0>qUNY8a%}|rpFGN#eZZrPSqEIoxaa|Q3)SA- z(1pRZvDL8lWl2N@!@6;0Qox2pq`;NQ9@b{z_{zkgE(^z3CJr@Q{P@b`S5sHJsD9qu z#dY=dXkfJqYH3ND)#F0QcS(JB1CN7^-Ik_0S9Lb7>gnjV@B%ao3dk(o+0fP2{Z%W+ zxVG@CE`nuqJ3Db@`ZJ_XHu5-&ized&YBe#qFfq%L7d3R6?2JnxV^?ySiEV7hrHRFW zfKioWt=Ua2<(QmV=RBtdc+Kk7Y^JPv0If2Rlz}E0Xl;b~hPtG|yzVnwU%mB+VmB(mX>h?vmyWN*5Pb1(N1L+1lLR z+1$07XB4b{8`G*`k{YH-!?ZT2e3BZbNyDI(YB4lbL+Jvb(HfO50{Tv)vW36^ps2vc z*do{%TLK$n3t(gH`fZF|y^YapcT`{#IVx~ax&V#}94cJ|M+FX*Ed*xsk_|KD7%@YR zoiXH?u|a9unL+7-982ar$&?MyU58}MMy|USc@$(;jy;>iu4%-e8TpWd_K8uEAs2J>sGR3wkN%YNToqt=5_w77=5;l6H<#JtgN?EK(#F^- zv@y1_Y>eG&Hpb~82c`2yTdWa8q7s9OgVNZS+r}h_%I%)9F-}KID4TiGH7`jr=y;9+ zI__zJj^~)fwr`lkZqRYjWD-HyiDU*SSA<--B7ky50G)_tlyzLx0Og8Y@jjV!MSKHv zEXM#H(=mx1`{1&U@tDL?E`pidB93i#3{EBi$}IvYw}^=)T`{p6lv{*BRj!D~Sg9g_ zazy~;ikMj9%*1ZcsR(&aHC)cFgiFbQQvs9N{FqDz9M&)njFS#`6Lu;vVW$ogcB--H zZRQre0z37gHcUF~sWTv_F3xjmV#uk7A*VeCrCo!cI*V zy~58?pG7a_!wFpVF)Y`|uv{O*a(xE9!cVTxpqKJt{L%p2!_FWL!6xjuk_kJ$WYOF1 zV$mzGGZ^=%b5`TkU zfu;I5+c8PLgOqDC3fl&2+`8JCR2d9fS1X!pU9D)Yb+x+@DB;o^3MjCmxz^P%by<}_xHSiaTXS4Q zWvbSSshpdsTXPUwJkJpgRbaQ~&@5vSNN5(#a=}Seb4k?*ld9%G;Sw>aXbuIGd_{9f zRdYbNH3x)Sb6iAa>ed_=Q7GJ+gV-)jL2LzfYYzE}rrest%9lM^H@c!p)m)QmgrIPV z2m%FmH=${@qB$VkHV1@Tb3nK?$3>J%5QSwE<01;etvQJ8(iFs2V7KOw@6ue8Vsotx z?lGvf!QH6V26vlU8{ADoz8!H*Cund&u7yw(*V>>c4hXdpMR8ojr4}xtBHW5Y!(56% z!xY%9I5bSncPS3}E;y+uE~zLE@ysL^<;?OXcA|R*&yA_9qsrfF&A>Rd~QEp!a!fg*gxSIupyIEYs)e0`6 zBHYaa1lfAqDysJ0|^yfLS(lt)tL=9%B@RvZUadbU8=JiP$;@Y5qD#F!sF@> z6j2e-r9uK#su-mgF{9C{h9Z@L0Yn-~QKdT3L7Nm+s#6`NP&KEhQl0HUGNnc8dTr8@KBM!Ibd5~~QsDna2^CDh_JW~O-eJHlxAYjo~v2d zzp23P8bR-p0Q3s1G_y%DP}8bR-p z0Q3s1G&9+v_$Cl)l}ago7vQ&G!qE7 zVu4VrRGP^}luDE#2o!d;c&2OI^T`Y14$helIyh&#?cnSR9hBWr2jx+z(_DwlX|aT} z8!h2%lag>Ak~poG=rmd6b!|b%_lP3!IXGPb(w(A1rYS(WTXd*&1@Nt)Fe-^oQvm2R z1<1FNa#>*y5>8WqygV)F_)bq%0N>l`I8E=;4W7fzqf%V~#$BEjA)TU**-JQ00bEvX zEO1(1$oGGOpS;TK;B*Dx&O}pywA}0z)oPXQ%N#0Q0miMFq5$LGOvh;okZ;(eIy^+t z#{lVuN)(lDsT`DUip~U9qOxb?4$hg9J2<`lyd11~fHZfN%4+SGmy#tqt^IsIrWuN} zbSa8T_dyOyYrk|azQrl4w_m<@k?6GcgHCI|aRa0Jjz|B)675-yr~^377J<`L z0GuWZmsNGlWj%13ErJe8P_@NaeehwdJ|-I+JgU+ML!-P#DJ`Me%8*u3C7iAdggVuM z(HdPD(u%6YPge%wnzMc-QFM!yydon+@=yks*OVcxf!fte%b*fYR|W@6#rhz( zt_+We2|6!Xyp&-?O|97+=X5J#T8}1rD8nmGf}`#x(mJNC3=WiP!w~{KaJn=ot4Zh) zJ|T;jGK>hSDZ_}NURbZ{J(Pj+dT)3HO(<6%Go-ahTS3xtq=eI@krpK-IxktE3{~S^ z(G(KGv^*&F&S6Sz)aLSfECZoly+;HEonE;|3v|5ArUZF)&mq%QzzcS&TI6LuxvZ*ad9hET z(`1pB`~;b_>gS*|L8P@mhe}fjRt#0iq(wldpl%fMQlLcVA%|`e@|vJrRu=`ftXQqI zI4Fur>w^wT6GU1ibf`3iNNa@-m4^_zLgYn5r>JfrpwnDLUOkk{>W$YGA}u3|qS8vD zgVGctttUEEnnI*iMTbgL2-XF)@myYBbc*T<0iC80d7V)%t15)csyJ!EQ52Qd937OV z5NYMnq0$s0tv@She}fjRuXj!k(Ml-qPjwO6;d5&<+V$>tf~-s1=HNJ(!n!y_Y)^ZDNm&sr978n zl=5V%BdKkyV3fv7+g!m^8ZYoy<63(8iOE`OQmvA0}peuBK9-=r=M(~qnst!t%M14ffLy7WS(?DrrNHbN3 zy`~V%EH#D5GgYUk6J;cvrVx3iD$!{Q0i7m`G*cBtrJ1UO(t1XksXA1eLZq3hL**fa zt`K>q>J-%#BF|JMIuA+UaEjG%SrsSER0TU}rs|+Hg-A11he{JenyETe9zy5}k!Pw- zQC%VOOjV-ukVIFA*G$zI4QzWAvls(wJB|x$YsQ7Ot=5ILrE+2Ij&fmbExE9cqTFb2 z*&KDbslBCh#u+!Yw|tH*Nz~GSRC{G%jc;&X=svIOQVwu>t%J)80Dh%l1&<^T(n+RhjGKpA><*;#lur| z^1$V$_7=}mb@B)%F_8u_7uL(_q#ZmiTCaY^NGQfj7p+&XN;`X8w4SPy2RAphSHH?b zoSWKPJWtihW1aQ&t9tV@5{MGkN3gn@8=Cn0MizJxKK#@y!JLhc0J^dnZtiGU*4|v- zd~tJQPdC1~*xk_h&p`7#hppu;_4v9{b5}Ki*d>pS^li9&uEUFMC(Qs_A*+3e=->O`d_vxQsK z(3WhTb#Y^JXLs8w{(c>|$I45r>S}CmG68qaqUL1JO3^UE$-vdG>Z)JV+}+x>>LR<| z>Q(#^wrViZ`CSm3T@al?hp^%_dU6pcdx3S!d)dPT2xkF zGX#NP@=s@_Sl+z2 zv$?UYrLD21p&R3=Q;gw7&FxkAQmc%v!}m08wDDCod_yX^3PT7!L|1Qo3blD`1Yrb!G{g-1ppa?&*Wi- zgEc>sAs2H#jA@rMIpIr^Hpb*6V@yu`xka1E_>3i@TZ@WGDj4%Kr*1072|D8&xmM^g zsm!nDx={A#l+IbW&?Is&b2Q9i4O63G>NL!pN|p0s4O63G>P(CXzzY`&2_=jrp@gv{ zlrWZr62_8H!dMbY7)wG4V@W7s6ba{O5(1-02#g{jFp7l0C=xOsw>FrMhEXJBK5m-D znuNe85(1-02#g{jFp7lCN2^Pbkojmdii9j3Oa0iiFI^T|4v9Fp7lC z$4yhGNeGN0Aux)Bz$g*|qe#enw7L`tnU6-JNI0ib^%P(f34u{01V)h%7)3(n;Gx z=4v#})o7XnAEkQm(J-or;G@xKn&YUhsENb6j#4$p1$FkiRGQ}W83F8BwYfS?b9I{L z>NL&OX_^BcMM&_`FskOjN2Ad+$FmJZO+cxdkihPNgc< zoJv)wIhCqRb1K#T1s_ER;Gc9)< zs$v17NCk`{6flZRz$hXyAGbuzN5d$ZV?J)0IhusPC=vprNC=D~Aux)B%txzBk&yXl zG>U|aH3@-HBm_p05Ew;5U=#_NkGpo}qhS;YnU9;MMw1X2MM7W{34u{01V)jN`Dk@1 z5;7l+Mv<^ilMon1LSPgLfl(v`Mv;*DxNB!V8b*Dx85)I0K__21elwjKUf7J%uwc3TI#x&cG;~fl)YP)}(Oed6Zil zz$l!7Q8)vmaK?N=;S7wz85o5#FbZd26wZjc3TKYPZkd5mI0K__21enGu|{RhD1|qp z6y}UlxHC#+ulox|3XQ$)F-)bh2TEnHI}L^%jlJ$ROr^31N@Wj=SM-iCOk)p}svMwH z_CTrZVfHF}pj6!hrLqS~We=3f9=5Nt2TElRl*%3`l|4`@dpLl~9w?PPP%3+%RQ5or z?BN9}d!SVIK&kA3QrQEgvWF|E?156*1EsPDN@Wj}%6{Qo>qbEYAk=1sNC{(wNC{(w zNC{(wNC{(wNC{(wNC{(wNC~5aNXP?!b;U?V=`xBqF0m4UTt?|)icl_7>4J*shD@c3 zI!9CH98H;X=Bmn^GgnpSoVlu$;NzY-zyeem!AGOfCDfG3vwlUtKO__C?GQmd?5_~j_s!Z_FXf$Q=ZJ(khzVFjf zsxtY`Pp8u5)GQMPbxDOX#iJ-}&cSf5ELNFFOI$alC9oT5iR?yNLc5Wc*lwhyVK>qe z-Ho*L>_!SzD_BqQg~AnD&jtv!E3}?X5Xx6*JsaWG1$N|;8Q8(gjr8aOJA}C@J-WaS zWNu22F0jLyo6@5T5Ij5#2w0CU;BaJGvzx6LLlmrM3&cpG(0aB(xPU_I(F!}>$)tA3 zb0a;PU=ksfAb$4WP)M+@wT>8A9M-;SGZN)I2lqo1qYm!-RnKY=GB5 z#C*LJ=+y>%r=^zZ^Z)Ve7>EC@Vx>Ft>7F7DL@PUKZ+ zJ>~c60w)A396Y)Jw4QD7>H_9#G_8j>5HIg&ZaS$2KN_FpyDjt0g_EpJ&Lwk<)zc7mre)%l+rR}mKzjhrKQuRPAx8;R*rv0S{hw5YhJ?V^N~nCnm`Uj zRB8gDsRqFWickjm?_Zsm8<|U)OXkuIHU39BXH#G0Xb>2$Fpw`Fm!at=olW6r#@U(v zV`P4!9{C(_)kqW|znl$NrEqf$P!NA)aN)Z1{m36D-X`d7?OD034BM5Hc-sSSXw&56 zS6A{cj89H>cbVr_an+5@+%&m~cYaS^hHcuDD;J$TxuLtet8E!x7D>9KIymrIOP;Vr z#`-Iiim<$#N^o#%0t_I{F;Dh?(b5xuiQpKHZjwpUDHt%nV+DY-;KyfK%dLR95X;L4 z%a@BI6Nji1m-GUTQG8(~!7mT6O!pSxnSuysL3grgil+JD|0iav=O1adip}~*ZPl=# zPt8`Rx(C+(ZCec(<7x$AWW9i`HGq-za2Z#5>^jJ}imxCX9aq^{KQ&vO_Nm$Gc}JG5 z;^n5Jw)*Lgt1}MOR%clAh2iI`Q_YEnYre|ks=w@-NH1MOk#j3XUX=(u^0&m{GiM!f z@UiuiGFS4NvyL<@#r!waoOPZ=!pLLunzPpPPaG%P_*F#14u_iuoNB$1SzJ84y#~!mxNWal6eT**zwN&Lg9DwjBfqE} z_@MNIza8kK6W`nBPcWAD=aqEMjzQKBkbLC(dOVg*42#6E`s1B9$TNGM=LhXRHtQ4` zHK727?E4236EaWM{{ZeGGjPqN#Jqz0LU7@E#&Lj)aPU0{!=*Tj#5lgc8`p&QXsy1% zmGuIB8#>Dktz5-~W;W+CFXk~O%dFoI@z~D&e1mn6yTh*L_Q~2EA|socm-Q^?pE$;g z#vlHc(P%U4K)z=j2UsNGf9$83I4Z1+n^A~G=Yz{L9bbRWf<^D03s_D<-=7DP>4&46 z3K~&{`7pm?zOa&zkM%3dw-JR{-&_Y2iL(onIH3K zShN9`bS~;WgDAzvvF zvhUvk2Hao6`F<~G(((O`pnD9*aK673^?m_#B8hgWzJEV5Jbk|hhI0rpe}+A$9p3kU zWeTIj{2<5tw|x8aNsjvmi}P&9M~a`btnA0Ef00~%Z0XzOyD%o6AB;g~^Z9U&)7(Ch zgfFPRIuHGxj<3!WjI6V;UDa2IqEmg9>53(uLO#`3>rhcTzS<66>G)eYPDLo<7@j;mW3Zd=|;NsUGg0dRlq< zKFhKp**?q9EDxt=lsxqxi&)6dDp^zko6jue`&4n)%3mEq&mZL8RJ$+zkWVhz{#hpZ z9#q&K(DppE#G(`TTQfLQN@f=jscS$((M>{G`CgFe(y`ZbLD!3e<>iBAWq)A%6|&*d zcy3wD7giGTsrLFF@;%ppmMz1#0o%Ik`EfjKb~t-IWor8N`l>0D%U(a;7-8OQinjCf zbUE>Q&L?7AsKv{^WLboys(tbJC@0Z>s(lSbr`i|OrDI=ppj&{0ZA+|Oc-hw-$QLr< z(!N&h>&M9Rw6Dg7_V)S<+ZyV-_;YH*&SA<*#bU$o_ZzR8N_E*6&3-Hq!I6t&B#vSn z6L6H`n1Q1L#~d6BaGZ-{DUMbgojCrtZBy2xqe<2(`?RyygRNHFQ;5D{nBx-rzsTnp zoGrmTws60Q{8_l>wMGFi!ZoiK3%DNFY%2n8$2HrhfWM0C&q?rAxIR&Wzm02NzYz2r zaa|_CKgabc68tc(PnBRJE;#mquYx)NJ}~J3_yVW{Op$@9GH{9vOp}4>GJvn8I^0f` zfF!<-YUi}zbDTENCId+sXz%)DMi{U0MfNxD15Vt3Y-eI5>|~^rgbk|W%TRRc_`-DQ zj4$gzw*Zw57r$Nx&2K&AQ^%K|z}MyWiguiQ>Z#Tf4j8 zT}|mfBQrK48m2gW{HigH*cHFFRb-9cUU6HZ__Sv#MpiGXYD|0^=fh{e%t+{oV^JJu z7GJ>T9N$uwedpZXp8OQYN0v>bp~lB~g1|b9aYY>;hoV!*N2W_>d~63@FOK2H$G?Dv z$9|E7eCqg^fecUkZ8%i>O@Dqr#}r1h-@MA=(*n=lmMEwkS>2deRApN5;j=G+_j$@T zEMV(C)l`^c!wsLN4UZNbkMmGAyg;JiOJO6b4G%@9+A!0lW5b=G>%}pg4G(}O9UIO% zhz(<foiPS~yW$vQ41NaZBV`PR!?Us+`)$X(_LEp*@ti{(9fOJL z`CH%}&C8ow%8gaQ;pV8*Pc^@Mp3Xj->yh3Dr~Y#SLk zn1&CQ_jDZc+T~Kf>BNOz(5=J4JOoeXudZF@qTY1gxtIyMvr%3op_h~K8v*jo-*A3a zUM?0dho76zV8NxecHvk4m#Oda0je&2pf*(*tW8yizLN^&MEcgH{5i+<)ukwQPRbu! zlWIDDO{)2P8ra=io2sjOw*Q=Se$}_KD)z@oHN7dn|FTpdur@_>dCKP#@U)Yz?kjyX zZ-8oRQ@*m=y}hI7rSi)B+bXIW`YU|}20k!lUaDYYEDps%<(mln`xE-+4ftc6_t?mV z{eNEV8=zSk&tX?ieAghwF6}4k==b@4@lNk?pMB;R@6d6vXXZxgQ>9d!ni&hCzS>mH zqWpJyb9x7E?R{jBY9oF1sRgkGgLn$qA6!_O3i(POtxwI1Ra91jPu||%<5AS_^#k!VeoNqEZ!F! zK$*8IQUNO27kqnGDgdb-ABQr>)pz>* z*SJ4N_HmD%xXtPB&^GSxVBax`T$H;p704OWMk6eR8Hut#AsalXyH4( z!I^!&cY5v+T>(tV$Nnc+~ajyf28_?Ig!jMshsmXLCFb zUxGF=%&|&_CjjP{d!d!j>$x(_`wp)}9_y9M&r{$p0sb-a$6EQ#3cMQd?~q?*<*!lT z>i}n4I%fX2DDa(tk464@ICK6c1-9cWq-oJw$TJQrDaiwn*~ z;yg|#;Nba$$R3KW6f~j?E{W;x<_jx{dM5#v=Rh}O!pXW7^A)D!`qVklxyVRo4sEbA$aEETAc&EfWF-fyhuWJb$#b`$mcx=nmXlB=0IikX5QiFKqGk)uFQctG2VX= zo45Dn_R*=lx?}rBrwY#bPAZo3T^uy<(tDF?Ft-Vpq~VgHesi!C3KlqQ>)qRh=^YW@OFKiZbk+_(P zbUun&5(&(-DpG!ebiVuh&kt_td$vCos!RnJc0S6oL4vq%CcXW$-on9YIWP55F``{% zCuR#2ES`A^<`th6^NJ8*)@05tLT@ooP*#`HQH!KM*LutPJ_5|7}}!DjevX&HWfde~#?q z-i&Qqkg5!G?^TDlZ)d%6-Ov+tKFT@azTCty3C=wRbD~&|e>-}6TETWM8`_R}%e2u3 zMbs`^Db0DHbpyKC*ZJtdZR#iQ-O(QkqW(C~g?MgE16N~K9hg!((0k6TR6#*?D!&mk znX$7{c}25Qxy`jH8Xt$O-^V=WrmC93e*}ZDBL9vrM`}~${s%`j_Xk4eb?x5X+}gb~ z>A`+~yr(}9AKUlfsGdYcDn=Hqf?UyEVTkk=jL`C1*!Hd-0a zy&`yJ;3}T6o#@LF`JA^61E8Gmf9>#HqhNV?4#M*z9=8R|_q69&ZQ=am71*4k@bA9K z^AEt73t&T(3kz6V*HGsKhf|Cn$AQyI;<5xV>qo?Hj-hhmJWgtiABs+m@l40DTO`3= zjqyK4tSttSh{sIl72|)3jC5lBlc2lL;vsnE0#;-E#i*BM7D=>Mjqy){&MU?n>xYdi zJJVf1ESo;vT0k5=#?L^VNcJ-veoqe(er6c!9JK?!nBO{|{a)}tvEqT1jrQ}g>VZ2r zzWVGo-+l1^Sd61YjPFzZ#!3hkch1foq#VYa+jk4b;dND$`d;|Vs??u5D+YYnwJ3NQ zQDbJtcIL?(pXae=<}=&A@?J2D*D$ZZz4fxh^%!>=69id&58$n#4`{-iKIZRx^z8Q{ ze`QRp&sR*vUwJRGpZWxDst4{nY2xIv2OH0>h4P~F;=!{pXwjFm7R9O3zK^^fdBvPR zHy-K5ST`H@ro2YU>24f+FBYweM{e-X&Jy^?hQL2N1pf6Q@b4@5kN3V*crq$MO6R>v zlhXXp?@6-nu^+Jhc#LEn%P{MM{b;R~&oM%V#{p*lxx~spNr8Fak(|%-_%|P2%!q^W1L1 z?G|i0Il=%wkYwCVHm^3%=H}VPrY=yl<9AxE+swu$z|H()=z_qVuVgdW&fgC*sSVI! z#^7=V>_!u41CA(cm&dv&6!y4ve!)8bh0oT806ufy$?Nb_EqJJV*j6jQozF0WUJJg$ zf^W9q+bo#nVE*@8@WJBWr}1tpuWO4Gv@XOtON9m3Afpu59DkUc>G=9{7A!o>+9Lw2 znFQ<417!N)=veon40B+9kMo6!VA&_WM7BUbiwtm?wz4nJ)h?wP=hDdpDf z^YF3qKC^LltmJ0`?l=~;N{nBhiQp7wS#m75F%i8BY8~$5k zLKZ&DYlkcwkC8bzvkC-kj%h;Ku3@Ez$4_+}IGCSm`~3fxpT}_SbAE-&=q}xxfiO5x#diaI)|90#3*GHiB*)4)$fi zllgOpf#y`g@I@HHA@q&!7JeYv@Hh;2jo64P;gs(=0zxODvUNzkpc zcnF@%U-eJ^?gP&wL=x>){qqWBc=_kaWz)(IWvzI|A$;%UNmCe?f1X8oJJ>(-c4XWB z8GlyxPxejWf9#hWFFz<1m>3!=$4l0UNENtz85XW<&_Bh~0675xe@?vCo`=tGW1;aImo3EaFO8WCvo^vC)d=m3j|E9s0 ztH<^I@*NtzYw*DN*?+*g{=C}MWBz%m1)ZDl{G_7)a>BC*(9X9aRv)l`0c@ciy!qK(fdJVziK(U9~9kbtS`X??KBft>G;)= zyC2m3GT?Brv}}5r6-*DdOY!1lN#H;CUt!K z3Ox7CU$&#apz+`Pc8sj7m{U=SFQ0w6>X^@8jh%DYl~-G_m#BDPO$Fbd^1Ui{+xbcc z)>Mw{n_I=4&fIqUpwC~4opHJSG5R%j$zgZgAmQ%T|J>ZFrTrCj-#e63@XURKy=%hH zRN(n`na__B2PQ7u@e3o8Z&_eQa^3^kIeRWu^kdB2OF7Kff?pQPs%mNBXuI@13p3u7S%SRk*Jgviiz>UwGg(%pn5YMt%l#e0#|@mNdAH zDI_xT)Hg;5+-#_8vs0je-_)4P%cY zGz)#1I}+t8NZ*eJdl&!c9SS_M@A|hQr~RmZ%i`P@v1|1G#u~zZ z%y9g?zZEl_x2pU7_PodsJX3N0g48_Tttj$SyE^r?K8{l&@wY>w{s*%Jj$!u8=%Oqm zo-y4z;I3z!KXKU3cUW$o?}$BxO%^QHx&=G|?a0Ql)XFbY;4=WPL>}va`OQ;c-c#6v ze0~PR`OONv8t{$CXMJ)08U<$j50U?ME1&NHWZ0aana@O8oIQg{>FIony=TycRrU-f zo!xxcGsu9koiN!ZWk`7587SpoXP{lgmBIKz$SgloVVyEOiO*;okL?UsSn%Pr);d~R ziVi|PP9-=XwmmmoAklC>=W$Z!kVDaxf>xB_a!ki|B$B9?^~Lva6;{SZWN=w=kH>U8 zXFVMU=B=GL8R<6g^P2ND!P)#LWLM{q+aQqF9P;Gy zvgyVRqxEmtSZ9B@W%yY4byk8B>v-4S=+w4FW3c0I`{MQ374&T!tG128`wYHVg?}WE z*Ck`NVeDmM?C@JyyymnmeLDs}2vnrDEa;rg5tGMv-)Udjl|Oh)&aOU0!-~$? zTL#HrY3v#25t&Es`cxTJ3=%C)%?t2OJRX%fMuC2wzpuiGg1*!KzK!ovzYRR@M1h}6 zd5Dg_FZ>;Q=3>5Yy%w`tJF<`48{Jk4s*!zV`2WIow4BV^S?#pqHKXs#R5kbwKlZc5uB#f?_vKOCvS0Qu%o*4BqyB}^-}!)UG@u&+-3Dm8 z0c{7gi$3e)J{&#zqc?!B(60&@Ye4#2&_J+h|UyEmr4cBs1juC3b$bhKvg zH|}LEt=ZdoZzOTyYkVDq#?IV34{*n8j^4L!$92`3z31PHUZ`HPcjmqIcpo7KgB@zE zuoc}D_1~Yxe#nX8X$J0lhizMtj&_2;o}w9jAhtM=89AH-ZB@~ zYj2qvR}QB*vQZjn%^^yUBhN}SP>mfE)HpH}9mfLJw@6GkLjX97det}*Lq;+3#hA}@ zUU7uqA4w;UOak3~77xMGD~{{}9m_0|kX?-SG};Css|FtW+_6?xcOwkWk2JI(km;M~4V{Qf|AK=5c=sj1V5Rg?_KvX*c?{&S zpY2}2tS6pt@!~4yvtDI*9ANg33#|N;6j8)&+Qi6Zo$~SWoC3(i00KM zY;6r|QTL9upoF}4jA3bSnUZbfI(x@Fh^4(_oV&amO)&Q7@!m0RGw&VSXr1r3&QJ0= zPPEH9bKlALIa4i|$6%MZzN3vRby_8HEA>t*;?7JRVy_G#=L z`wQd}2}8D##Qk)I1&>2UDXuxbu-!8qUw_Vmg@+Y$rj!Jz?j0M7j&(1}FdL@h{t`*Z z$Fi`0RahBy$l(59nV@Q0zDis}HqJ8A>)@A8EaW|AOF_$Z94r>Lg84%hZ$6=jk#3e1oF^(^+B>a!{>+(MoV*3!j!gTD59LHq; zy8>`J{&xrH*5P0tf+zFmI>FCQQ&I028**e<{g2lLhn$OIt5OpCBKX1BaBCVfrltRT zuiH#TYW}xr@IYA9fUzUyCV`S_e%f%hMx^palu)(;W4{b-TvU@Csb`N#` zIS+Z!mc!RSSw8kpgki(p1Z>VbtPZg^s?H>DX5t=oaAMJv-w5itSgOk8up)@k1nW ztotUGjbfRBQ01eN@ zhoj@U2WUERGScB^U#FHH%ADfp_$7MMeLiYmLyTWj%8uGscLPmcmP~$>-)}u?U*7gr z-`IXhvd!GX%j4K^^RH>8!W`3hc4iLtuK5>s>kS-EzxTxPjPFy-`w~+bhxXCc5BXzG zsMpITIVOq}v@S|;W>tz-#-+c8dI4rojKe2pyNQyI^%=o^P00g1$;IR zk%WBeoQUA76Oe44h& z@`yB)ZPo|^>n!?Io$n1rr`jgdrDK~-pi9R#p9Nhyw)qO^ylu1l(8f!#Jv)v2)o~uS z`53;dM%bgp_W9W0aoAmT`1}Tecs6W}orYpQP5UfFpNSN-E=q7_wTiKGjv%nkrpooP zb0|91KAA2Z`)mbWI`;Vj=+d#z{|23>eVR|o+wuGTfsRQpLZ6{z2)J_$JXv z>}BsAHN$|f27EZ#DnHY4#!^Q~pQgPQLne`ive!C6V4a7u*P-ZCdu6(G?6n(o>DcS5 zpyRkMl8{f0^>|(4VD{Q040hQ0=OKLSWQHk>E7sqFJ*I50Y@cke>m)d0yzg=NjIU#% zGu37dMSVg>>oq?eCpsGEp=|bCiH0wQO{jB#q3BebWx8~1_F~YbW3#V=j$@ZdLO#`I z_kqA`j6HeE6mb)j)|z5jnYd{h{+{VO=0cinv%KH%YY%ljL?>>Bbz;|eW%y;->4eez z-4A@p^n+4-Ij-;Lc>ihT8^NdP#LO4z^P^tmugU%Kz2M7#e8Ycy@ILG~H@?45pZ~0q zW8%#(@psNP&+f7&g?FAP7lWSU=f*;uIW!7xtJUeTaajwZa z3s}%pj>bP@SpGP^IWD3-cp`n2{druTeXx)(tiAI==F#zYS7z3NY6uh&M%DUuiuc--K1{0b|B z_dZR)HJW3L1x&}+pR-`mTh9WPlkiJ*uh&p?P^&%GFdwF?;R`DX`Pe>X`AQ)l_aVy^ z!Xf0V#5H8=#K}nfZgo225XYU3D8Y3cY_AEwTYa*@+5894Na{FL0r?hMd3+LdCr=T- z1!4?C!>-+&I#mo?!;eFI%}QM3(Bg;A!Z>7(J{Wn*)X~R1a_H|5j+ENKeXxMXh1o}j z{})NJv#lJjz_S12qqxHk0L3WJ{$7alk>KatUm^)VQvJLaHp99Z&d-|!BkL^eS@rXw z=u|&vI-WC#B;;e6Wk2WlQH6X5^Ye8mmyVy`2fB?`9S8IC1*n&05lOUH_4AF$@bdF| z{>-xT({aQ4`HWM=BhTUe{4b_3wx1h&ItM6r(i;Pj>;#nr6UQZJf9!4le%};)_1>3N zld(TICA8mP_UP*a5#7hfiALhgeNq!IydrdE@T$N!{nz;x{>N{h_|49L(#N-{Tdz940SI&AMNW3hQY@EM%Blz^$dZQ1h1#`4LH=15?6nKK38x0l%0{a85V zanR2q9Y(+H#qAJD_)iHC+(r?fmkI*wEVQQ1>xZIa9}s1j1=G#o3oD6wSr*xEuScO= z;DnDc9gi`mGA6L;p}5_9|&77L3_9>h22%)T28{2R3EF5iEu6GR3BryVjLogdM5!P`xwtz z)A6yTD3^|ptpgn&!}(Y->gBOiB+(Al$9SKar;lNw^H81@%_vWQ4t$3xjLXMvsS3Rq z-nFjE|4iToV}%o|oPHeKw?p|GkM~Eazp?CI{${HE@b)*BT_j=mB|vbu3V)j?2&}W& z<@)o0q3Be9W4dCAr>J)laI(MEprUmAtsUjk@weMRmyW+pLcQtu8}GID^tT?j!wt7y z`!V?2GvODG`kSTp!#chl^*4PE$^Itm1)!1C_%@`!HMTc5bk#RDG`2RU^*&Ll*iJqC zz2A3CVO;Ue>-&{4OJ+XtJo-qDWh}dAEOS(RSo@cVCEO3BO^h!7H73b~WhIiDx5GFF!gENwin>FOIjK@vOV6VP)s4 z_O=egy@p*|Ib}xr_h>Ow7~8*$_YYWcpW?cQ&=a5exrnrGaY)M%A9mN9*E2;~CUKu$ z0wk+X*fp>D$;ni$K2IBpj@1rcoq`9`rDKOppj(P#xIJ%=gGOFc67s2b_zU$FJN#%nf{)ta5O&zGEP0`{A$Yj?{i)*7b{hNJo-&=n9uN81HXaPV z$j_%~!v38R^ZPd1cd&R(MDf_##0wePI34@dP_rk=x z$=n8>hm3Txjo2xT#p8^xl$c#X4a-(_b%U16i)TjZt|NaM&xGav67vQ1S;}3 zvtT-gKZk>1q3t=imXm2hMC!Amq3C#=7iE|a(@o$DD+&2{-Xq_ii}xubz;jOu`6_WO z#}N)F>BNzZpyPw-OD{~p5r z)ECT36#tDpuzC+waa7z!++b!PlNS$m}T4GcH*Z4k7!>O`wG+XWnQ2bzRcgi zI}&`k7;=gvd`0!;cGv~mG#_jt!dFyZt`m%`v#?p!mxrQLeVOSdNIZpnsxNn=BK9?w z?_j?Cb>yex%XforBaY#Gc^>Lb$Cs}FowqMHH6a#H5wpT!efbd9wqG`t@Al;rso&=h zzqqdIS?o3Q6_-Ag%U{B-y4!&M_F6jec|7#8@Cf&5ZbMq}+3X(Mr^lk)k>Jx_KBM|H z`waUFA8aZ^`Skh7lapyydVC&=PW5S~^O8^X>93=rbbR^>@Jq+1?+4vR9K-o^9qLWT zr>_UykUlMK<`~weKjNOP84p}BvJ$@)PZN`f%9$@-QPtD$3*6u5JD!gJ;zPxW6B9EY z-B`7{KV;$dzUCdb<@h!Ydcx12Umm<7aOIIa59fBI>*we)+t0<`%|etvoaf;)AfHGg zHmZJpHS9DUKW`U|tTT!kNsZk@(W!pUbdxL|d=m1hexB~0t((Ck9Y22(bQ^ID=jS~C zPsh(U4&~?g*#0LQyEj^~+lXzW(+t*!2{efntZcJ3inpFSG9F<>Cov(bFA zv3pd56uad(En>GE&yU7#bds_!%<3}R&yU9Lq5b@5>^9t-c)#@_#qN)|2Hv~h=lezf z%WG(R=j?RuvHxFM1Gl=u_TQsx;6wZG9MgR5|6-1=&b^s#f=xB_-1~@K181W-gg9MR zE?$@ze$PyuxmfR7H^aLUwd}u_-?u*Ty~KaMLB875?(XpR+p5a9_u`$2z> zeR2CA-=JA^0^Z`x4DQc(|Hu3N$4B>PK6S_b=rwdwXn)3(S85Uo|IQ!vM`MkNhX*Mq zyb~pSxuY8UeLnn%S|YzcGgv)Hp$Gb3T{ClgX`&=y@&?s%ldm6qf3!b*d>DN1+8@5= z|AI@F#W}E(ZuwEa54`CXI`M^_oBE^v#{R6pGp}(ibYjtqOg-_%uRg@**mgXODWUx# z``wRYYRFjIzsXqJXPOgVlZXca3`ex#C1#;_F<;ayt1H zP=0XcOH2tFLxa)%fxJ8SM~}~{x$U#hJeP|WEoaL7#iO4xD1XP4C-@-65BEoBMbVOD zYg$L$*B=c$@@#S9n8X5)-_7BBNRcju6I8{=U6FZZd3|c;`_d7$;spBZq)i47q3Hj7Di~-1(&RXSr;Fr!C2LC4Z zM$|dn8pe~LOJ@y(A82~6RpObu z8AF@pJ@&l*CQ>mjj`U}V+=g^~+3FVCmq(-Ak>JbRK9Pj4sJ?vkS)%v8fRFqvk&Wh1 z_63xuzmND;b6j=JiK?n14>a^w28uJO+OKhn&9;>({(S ze5Cs|w;^4>miGwo9Q{b}Yi^%NL-{rDS4k&EFBOcevuRp-j2?r^aZW zXQUIOuLh%ZV)U;-w-Lv1G5TE8n@)`8=OCUjy0LpzS5oW{NaOpR)6(C+e7>oC+piCY z{mWU~|DBb;qrXa#u(ABrJB&BVr!|uzUaR_ryeqS5Owrl?8LGdrv z?b|rOUs?3w3!wVGwU|-F{Kq!-$=)wwA}^(n^8Esqonw*g2fWwRRQKWiKBt!*m!Lh| zox-MSBt7w^+10vV3`JKemErPCSIiey3R-9OAGY}l3!aIJSU%wsOvmGn`i+7n;L`E4 z?|^Qd#e?}UKjyFc**Mgj&ikA^e>@xIMFMCf?s#chIJ}=7!uR*?Gb?fVS*hV?z7qDd zNDbDz6J-Xb#Ks)_UFva=`bhOXmVF4{<7wYv{q7mdE)v@!rxG08#lrW_Wu%mZjj8XR z4MnH=9@7;|{6xK~@A3C_((%2E!7Cl#`zh$s@x2+SHyz(w3OY~U!*{NoncMJlw^L6^ z|GPd5%#dOGUM7!5KEFSJ6tq%EN#S8q#z#z%PdRSj)1DBwAPk1h-!JQ=K5N&O$S)KMh4! zYVi|nn66j=IE#AKSj+RsT;#K#FbyB-eRXrWuJYpi~4!iGqTKeA!I@cVOY`-&Ot=47XjBi731^N9vrwBl&Y_5L2G8gui8 zin*fmtOcdve1FCvymRp@j5kQO?{mzpjsynIney1E%WgWu;)0Mk#~hdylVW!b%Auhb2P^}R03FOrCZB|vaji}*X#o@h1x4n?QNU#2U@ zA(E(9jlcZ7Af5R8budaN{@x9`bmA|sZ;ckh;mo?=r1~K589QkFwHBL(^+Ee*JBQzs z^@1sk%Ll6>UyS$%&M9Y4>>c&HQEMaD0iFWb^hn>pl(O6!>}Y~t`ug+o;G0u?@K5$s zvOV%a-L|48*wmi=Hp$_rA3ph@@rrtap8yJ@m{YiaycAAfkDsd-t?^7R9J0 zKI1`qAp+fAoeMAFis^dzrqyz4hs(A6`kt;H;3||%cX7K93HHYJO zKzOfHyDhiqITOLpSLMXt=i|N?iET#Sm&q{u0(0T^>toG0=Lg@K{y+BK20p6l&L6(> zl4KHwAtGvc5ho-_6vPlvgSvI{b^%541-rC$mjr{rE^2_VrMv#yfKfrI#%jANYE#R0 zacgae*wq$=u54>}wHv_gN3^!?v#yb(&prvD#*7dAzu$ZBnYp<$ckT@#A!E+(^SN{G z%WuxxJ-_#J&NZ`}+Bmzxc)?$FK7#=%_{>*vF9%y8YWxO)71FEI_hC*4zhS!t2zs{i z8wP0I@SE)-BO?`W$I5T)@T~lXc)TY-)UOyf%={(~_2avA;x}&t#|^&;pyGRtGFT4F zW&T!v^E&V@!F>Uuy;gq1wLP}{W`lcvBlm}u`@<$1hx;%9&3=8macH|wG1aDeIS%oi zuOXQrp3L_tcnDLl3k~w|%XcYs95XK@f_TqX|BD^o3_Y(p{+B>JH~g>`c-1&KKb(gh zKOFElgos^vYiw&o$9b!gA4+~WDEtuPa9uyfVaaUqkvC`G!9wVQfLL6Mz60(x5K`}J z8Lw`FrhkrluBO-LKE6>cHO~C1(p0RS&sFa>yb1YggX(FTuiY(E{pu3!jCaG@S?SK} z)qm?zBLCLoZ^+ViD=33KK+8ZW>fS#KCGmW&>Tl9ZS=8n6dDL(B1o-vo6L~vfhxmAf z``)>ziSIkS?|UNfGM;#!!joC*nGrsHx3w5gy^olmkL@}!Ce+5K{>Oda320^Ezs%Lk zXOXUn8@=0<>5;CIjlw^Y`*=o^jw$LA>{FMZR+rqz{YHNNSY3j}7sTpPr24<()9NCg z$Lo?|{;#PnyBmC3UD_M;Iz7~|K-GJ8f$BpaqdwVeUEpQ3yJQ|eOzygQuJ52ua6$Q3j^C@ zj5>TjxQzei6CLLQH8X~z-w`+s>Q6p|=j%q_wq-{rXZT)LrsQs$rQ+OItmbNOF!DmY zHv9J9d318tFWdPKFaMFre{k&JJd0(%y;Ib2!%k0u_mKl1;vX5rKhTb|OrCwHogHk? z-G)29+((G_s)qM|?A}Af$+(xlS^r1FuWz^7&XlDBwnIQC-H)O?6uCp&iDIaI>q2AD zYnV7!N@xz^d7|A+J6iyGY%(96`MKE+B7P+fmcqVCw5wxoJF`)J8}{{zJM?O5vxRw10($tQ}oj@)G1;Ue8@kZyxr0Mn7_)dXwfK zrR2C!ee-ap=O*CK(qvybt^=NHAccdE^Z9#+GYj54oa1>9|J1K@aIN4vpk2Rt*o$+l z#le0~e7l}Qgcx%y|&DSxj_TS;CZg5 zkDaTQ{vQIq|I>(r{_YUV4aEAtK zerMrnq-)K_kf#6q{l?%^Usb0gLZxeyqn~>7@L11kZ_e8XamCzF- z#iO6PNhM|sPpg~A?#Ol z&BGxNTlwvt+`a6Bz{@zh{;8haV)jA^y%4f3<96)ig(=#`8`R&p-!op#7444oCiC&z z=Cc6#1Wfq^Fj7t?pQ*?v$CM98T=IObI`;bWscLl9v6r6b$e3-6Zt8izYA}x^-g&u! z?`nzm_Stv5_iRJox5|6l8or9Wg3#26#Sx-lgv4oyJxE&6@|beXHB3ogiiy6y3Y~Ba z@-UBd5#vy%d`bHcY3geq=00)dHOhrSMn!^8V)QDbf=}Ffbh0=29c8L$)9Ry>b4F_; zN-4Uct#7+_?5{pLIlDpK-X4150#i=PG~|*QZ!z-7M(zRDHt&VLt=<7`GW5ur4};rS zzOPHE2tM-1o+W!HG2=WkN!Td_OyEnP-4#LrqClx@Q>G29sfVuM>p|) zb$f8z-73y}!AGudZ{S&Wd3zSq%uBHE8R9hGN*1dz>zi+ZaVOO`D?%H*i*$u^XykRzYh` zDkx-|u6IIk3O(~WltumOFOBpLrqHLp$rO6jgG^yW>@w1Q#`Cv~^nK(0F(Vy|$`ilX zNWaV!`Ef2TQ_e@^bH+Tie2w&gksfCXJWZbj-lf#*ka7(v?^hew-!#(4jQcx`>t7k^ z`^Nn)<2o0wn)%Ey(k~h5jYfK#k#1m${Ax{WKOHcxGx6S7 z&e=w~&`57F(sAe~?=X(5aohCS%)h-hszjO8reMBWC ziC^gMmf%wbu*)W?Q(?Ddshbg%7_UC8*{({_#fW6+(Xvgdh+ycmbMJ;9Lywl}zL>9Q z|F{8ms~#6B)2{Wqv$VLKX73gix0R}2s{VD4zggeKJKu=bG5;d%Kl$44-SFXDubr85 zDntJIU5`;tVhO+9e}jRe6urJ*$=B=Owo}R1^WU*E9_LfKzP=IBmI~Oq{xYMb3s8n= z^Nx0bOK;KLDz6kR@}g|h;(R{cZ^EaHFvXr}-Y7ncbnS`7%82D@Vw@?4$5^2$56|Pu zBSsWyn-(+Eo<+KP8}eiEBj&-Y{^s$&4I+-H*MnDyd0chu;-6~Ilh)*_W8t5QNSab~ z)v@tE6>&h1_O6ry-VObfd9zRX&M&~*FQQ*9lUG`=WuA?m3AXV)#qP7mwEOg3DFylH zY2={!_81}4N0rBjnJM|qD?fJs0>pRq(I`f#jr( z->J0*rD|S|1*o?chqTmtluf<=a=%hghWCR1Yq3y{BYnh)T8p?|e1tJBEpYTPCvY~Y zf0d->pFc0&VZ1fteyS8a({6q%*J-iLc>CD4%IDe2l6LXFl%j7P+w{B`-FK_M{gBU} zX7uo;NRs{KXK3t0|Cs>8B&mO;EL8k|z98|ub4~4~?t7u-`ZCLPrRCaeck%z#I4D=x zcZvR%SiBEjl-1g2u$R{?Teb8yeHv}D`TSD}CvtARJ0>8+(ju`1znIgYhBVElD<<=Y5 z-!#(AM%u&_`8;M^GZx6}e`1PqUNWvV-xIFejQf8u?tfrh_ZX@0MQJ`KDC>E6U&C=O z_axAs0C8&dIZZL1c>a5 zafAM!i1DBinUkNej8s0SCS-7t@gF9leoWE480-aJ7p_qV6W?RHMyx!MxsCU^#)N5!%6QZjs`6N-79*Xm`kpX9=l{(yI>u&jJvM7w zp86WT2J_ls@0QV8Of>M+6vU52%u&>5iLp+O&qRG#2N5UAe#-a6bnS_#k?#rCXgYK# zeYFf*#oE2lP7D!iQi^`DpKVp9C1|@VK}Nyx@C^QOxY87zO2X#=Jh;s1!ba z-J*_n{`Rkq{_$^oPh@Wki&&agW@hY~t$v{0_jLACC5WVnwSLplS2-T8XUw;8s_)p^{gYH<>nA@^ zrj5C-?L$T51DPg1@U3H?|HR52NY`KfP?_evZVhY;h?s?c{E+cm#&Mx?^x5lThQ`MA zpY4!0Ha5l*Z_V(H;l3RcnjXzJ{(IAP2u*vELR$kN8TBhSG2XC_s{K+%o8>#NFSk5r zj8_1kFBTU_d3`Gm)`ESVXp@*@zQ zUE_5wQ~WQ?6y;vZ6#rL^RI?>;eVcLJXy83+r2oVe<^SAx{4V07ZGIx~UN!D(wgImH*LePkaX*Cd#C#?*Wxhsw2UE18(MUBNAMMn1 zeB9q*+}Ct_T<_yG@_EC!uj%x-{u8f}FBL&P4=}~``NnmnalOn)?`Mkqo;1=OOi^x& zaZUY_&)baj_e_!R2gda$#`STgC}%9jBA-uSit9N>dbM%?M&tSpBW*P9YqkfJ*5PV< zkj4a{sTx>qkGBx7zaH5e7lZl03*#os04uPyJyxP$R>%Go&(CUm z%t8I^Y!4almhm0CaafD7RgD9~anR$8GTtr6;b|X-%hr9prY^SSo#Q&v(qi}D#iM=% zi1}i;H>~pW)cd|t-VE)0OtTcCpUc;09!p%pXl=n$ArZxOrZ!)bP34nB-FfL!(Z&3S zrkjAdxY139dQVAn%fxv;>ddwYeWR3(FoFJx6Ze#~!=oM{{=;mD7v_lpqTCs{HtQR6 z@F(gU5dT^~6Oa0kb>H6m7++l817~^TYsAcdNcpi3isT zB%}gQfBCU(?Of28`|lkvmI3HPU%sCQem-7JO=E0ty3!cyZcAhO_I1OW##ny=Vyx%m z24AHZcUKAoBNbz58m{?&Cp;^SF~2Yl0is+hjg_JxH#Bw&GIB#>TY=|>#u&qMLu2!S zmz2hCUA=bQvVO?0etg??2g(HWp|RI09xH!oPoA2$Q~O?CY2Cc@!cO1JI~$p#E6uU) z$!Jb=J3DAN%e6dK&;T*^^Ks2rD`;t3)E(W>Vjb|3(&BBaHmtv6-MZV>taZe$B6NB?{$0D7Kv_E$8>Dc4A2=x>o^ki#ndM`SQHZ^@w>^I`^ z+!~vvpU4cvC0JwAc6f7uEB?d(5wDmh28jCcp4p~;8-L<^Wt|uv7xgQ{IYw6<5)HQE z*Nq;(8+dzhungwO{FuL0f8reTa@-dn>TcDaKEi{fv1yE~+J5m1@c|-de!;l}fIj@9 z=S9w_%Thxc&nSACJNjS;bd772s+rwNS)6b5B;gxHqM=ANo4W6}7Ou(p?XQ3Julrv6 zLh%q`f7|g8@jN*X;m#P^nhxVl$GApqA0AR$qVW*03vFMrDNJ!eno9>BLV6S+Xw=F> z-U1D{;UTpmBO?_wW#u7ucvc=lyemz4iu$q6W*)-t9+1YJct|sF-0+Y#;O)iX#6!48 zi5njBIq>Xw$cBFK5a|n$z5tGMt1R1xdjs_a)XQ-w*U@7f5y-c76-2w#)(=+WG}Ac9 zhX-pMYQ9m!40E)>W|bNrK6losxF0B>k51M0B6TKZ%IIr2Tc77VbgN96lC90tH?L{X zu?y7Pit%b2bS%t;$CQSyvLG@xfBVrK!5@Yqn6!NZQP(MG+UxCV&!T5ZK9)Xz@O17C}oi_UyaeAL~UuW^ksz{1xCm#0;t zz~Ro*;&y|0TUtLQ^+8#A+GHJ7`{j5uk4;|BwLDjG%~IGeK!E%{D&&{6L zeQ00}?gwel;jmrud3Vy3ARzmj&Tv`dqYLkvK$pcvSVLx&i3%ruqba2dYiRll~r zhUrRimN50a?8a+n*3{RpUA1g|{ql9O?sq&Pf8{%(okt+wGXvO#2Ko3Up5QrFJn^3C zcO~z0!Xqy=`}&!m8-7>|ylNbSZ;isdM%v=w!!9I@d(l_IHZeX+KeqtJEega1QeIzZxh}R`CyD18Z&)gi{MBYc{47{_IO7R|9K?r zLjjCG60C9AHgt9v_v!m*zY~w=*0}5~xMv3960C7qJ3Ph-#DDld;w7se-=8@y+l4>z zJ+n@!;55x#UAheO(%r=&O2zcJ zu=6~U_w~xe_z3rZ`j?$`yGC!w+)z2``EpOU#~0XhV_s%k&imtfJb!&=kLPR8m;3iW zQU2+EC0w_=ZeHC){^lmx&xT`LKq*ejL%~MhJ>Gjgi*vB%Af%LyD%Vp6g0$U970(o$ zW?XjBwMu4A*0tH*vHo$Mvpnbc@;u``6Fif>Q$*j1e3_c>`IYVy=4ZY>PZ@7AO9Eb> z{9aOQ6ZuMCzOXd*wpb7HRxbioc}!XK%yr+mT@U0r2lTkOsCN0X^(&U%wzlT><;u*H zjqvHT%6>A(_*j1df~NCvgLr})uNDYK%4Y;?jL!~_G${VV{}C@)xf}v!T5Z6eNUNBt zqVW;IORRfIZO3yrwE7nCnsAWzc`!fbZ=FL?i*ntp^XD3XYw>>pqK(?V`KxA&<%G^M z|58D$&a}E&e@QV~9ZgAo!9|C==8aR&Rrem*)-XoJ0=kPXRQ>PNmM`zD%J`(>LhS54 zS5+?jv;DivZ#uNAxADm3JO8CS><{<)k3AfDB$8jz6qyv<89ny#_gnqZv(CtfW_|7r zmUno{wpL{y`bu6#_lc5*uAYXiRgohfH+cVSeB}>1gC5`?@khs=;f-c}+Rz#S_Cw_X zV0*hy6chWQat-_P@{WuOrO@~O&&#t9DTM`U9`-&zd*_n!+RjSPD<5^;*V?=3m@*^M zwW;Cf<=%sLmn%np*WfAWZ1=x>;t#0n=exU=F_-SYYGQuyA6h+y{~Yc9+!LMj^^9on zIO~`-@71cTLw_6}L>;{cUaeA&ywLEd`j4HVEMOk-M8^Wt`!Va6HSZPF?~mhAzgZ1k zKWcad_4{Fi7xfEP>}uCnUE)hVmyS`Fw)=a7N8jiUd#Ck!KOP@^G1`616CJnYsn&3> z_efT6@Kb*@-x8|-2o{M{$6T!T8?dB}U^d6h;Tj(eh$?+QgTdj7t3 zUPo}=OI55x2(?{u;H9cBA9}vq8zOEX>$(nql` z?2LZ)`FXwf9M6tU$_w}A^!{Tc7!4h{x+5!VZm_H)PN()K;*<6XYG?cR)MwkDR1db-st>iZg!3vFv=^vnwdbf`Yxkc?+G znPm_6&?X+|R+{z1t4;sKsq#AVo5K?WM1Cr+&H3fx0c8#I6Y`At|2YoyNgWamK1Y6T zWEsCzy%+!B94j6yH<>Ks-r!u@EI_o|s&|Hw!3u$dRNyVW{Z4Eh-yd0aiR-oTtM$%G zBFi#WU79`Eu$A95xu{6>8Pco>(qp#zp{f*Jxxcn*5vAF&g*(ADGlISTIjYV?zyhgvhEdGBXM13l*kt2&fOLzVwfAkTZCp=$GE$?d+mHdKUf7jTZx{RRAs;=@LDpqUMW9`^k z4$^DQ{^}~v!JXy)w{MxSx>NBz4T+nlu2DY_Qta4Wzj&_Gql^wd*xC~P_|uH&Il)ZG z&AecwBe-xyRmPz+I)g#)ffcCL*2?EPvx2*$A9rO$bKl5}Dxa`c!HTDiT0O1RYTLvY z+EwlpkOi4lvRhr<{(}g5A!|l&)+eKbKhyuc^1;@E-mFiN$8q$|=a4^Hr6@5Fxwi@u zsxw<15T+}h?>Z?1l7hG56>GgNByzE1{o!Qxt zeV1Q(;JT{IHQBeZ^4ZSJY~=GvR`l%0Gx46z>)rbK!j9~P??Y1NqE|AzPh2+T!24C< zL*6enR;nE#^+!?9isw25!QE9Y>Z|IQgTb~JIs=~7ouObpN(o{NRCV~287Q@|{e|+b z13&BZ1Xgq^q0aU%sefqyo%*ls_iC-$=u%$Y0h%1i@`~-Zkyko*F!)Bg%BwoGPk_#n z66F=Y6K4j&AFcAr4$msD?C`Aeig<4175TgydG#Ffb0e>gAwM_r>V4$rMqcH*lvn(2 zof~=Ox06@UptM0b$DN;KR%wZ`;i0qbHAz?T66MvRO@_Ssmxh2Qubzb^_F}{LAggXt z8`PI!!7Se2SiYXp>XYks{tC92(wo_HA?&Z6k;;xh;DyNO;7ieuqYt%aL?><@70vo= zQV{p&|FUWnBtsxDO0%ivZ2ToGuvr^_-0dB;xpGHmb^!nREF(I8b2elNr9`0O`{g;1 zUD+D`bv`V@S5dDs_mADF+lkrR@CCCf zNVkVJR*gQSOk1pGs4wGtPdZ*_+o5h~2%YmhAGW{TyX8~m;z-vc4I8Vx2N%QU%Gh|z zglg0WU!ck^z;}tO)c;3FzE6~yU)t}PrcC^HYhkb@dMxUXPR!1Tj_RT8%Z5D8f)qmg z=29jrN8WDucU70l$3F8%$154p?3h%}GFnE-tQ`4u!$$RM6WOBgw(Bjpv%?#DR;_Gr z>sE3g8AnkvE>SOQ-x)!V2g1F9-eBW)|5VT$=xK>S>VG!BLkTSE$csce zav~cc88acN0(n`GQw?1YqK%Ow4>WkM3RE_CWqQPUdas!b@Sh+>)(bDM$8p|&@#L-ezc}++5H9wAewkQ+lS5>P2rk;5)w{85y z>dqYBXA!jc6X*#as~sNyAyt{?Z@*jpj}JGh|MOu*)t?T$)amiB>df#U$1CoKM)OPc z;r7?m-?bl7Uv2+$wZ5JC2PzBO^-*?7`^)Na?VDe^4r#Rm3r$S)Y|wf|sIW2np1{3X z_hoL**y6w6_W&(H#2?5o)5afo^0pxRz(%&lIGO0Obd|4pXrll-`MS`ALtH!gYKLc) zuXcD=`AR%D@|E98awA_CBfn(6O{+b)9r?MDuUnCy8~M5$cze-rPWIqkDA&AhTlBNl z9^3`Ir1s!?-9;gsn@(}{S(m#1-u*(93FsqV;n^%xrkCx%zdQpnc8t2<5d4Kluh{t- zymQ}=&>#0?QrE@@ z%7bse(0ex|TE+ec;H%sODfG(*PuTbVh457>=ND`HGIec44ZD=0y8WK>w@f$>9?Y@u ztseQ*8$IWYU^GjsnWt=XdDfvC%9z>S1Dlc0^9|>z+3?nBwE~{@HzE^3HZm+Q1r}7AMCF!tz{klvdysnzLDqaJ~8Ld z4;HAjKYtkYR{a2W*0bdm2d`?&gO~Zf_QuHG?yxVv*Y~N`|DUk6-sst1pW5p?x-kN4 z^7yEV@$gY*l|5LM(W`vSHp8APo^#;AsuI|9`S2u%;7QhcCpQcDkE3)2*rIpN1?I#< z-m7%Xc^#SRlJ@cHX#B(E$-Z12rlYf%?5)_*n zBHC+}M{glNH}Z)7Q#bOc3wV1`u9G}!LAeu6^%MPUl}G&6VRCuY*Fothk1lcVpQH~M zV3kMnxD(%xe{p~LIJJV(=;NxL|Jof6J_~6S{QSAd!VXX7Pa}&u#$ETb=<%NB)=)IB zMgd<1XI_YB;H=7#*BZ!4cj{dC3?=I8`UR{v558C7KlI=5JU#{=-^B4se%^$SBJ?*t zP#&e^`S>q>@j$r;a>w`feG_UreV&l2?*-U(pBEB{bx|%_zW@FSD1BjbYisoLqrvEz z`N;q1dkon`tl-|rw&#OR97v#eVdO?dj-Pen_ z(`>db^H?yN(-W-72S@jz9p2uIBT8?^aY_nCp8opald9gX&w8?>d1nNoIlbFkE77he zAWfoq0Yu(zI=ES#-w~X@BkJAqLs%czz#3VgRve79z1rzlZte7VJg`PSf`{?2*7D~f ztQl*=HoXx2{77?aFgkYjG+-%F@9}3Np^6f;%~$@tsw~Js&!K1XE;{&3XUL1zcL$?q z6ev+ocWWy#9!Be*LF*qz>&K42al#$#HF%<29t|UU^WDh24qxz5NR+d#+Z{drDLh8d?9X`(F|E%uPF(RgW@&WN zmcYD*NgE%BjWB+r_p0fYKkUr*y%0U#6^iE0h6L&+FZNab05;JK!=lLA_ygEE{*B(! z8I`mtlxejSCht@V-irL{uu?IXRu5zk=55SWU=u0RaMx1`k09?u9>EJZKV}I<8yYE- ze4g-=sxtHaHsCINuicPKN0bXAT@N*QrY)F=cFac`KHC}XIUa~kJ|jCC>LPE4Y=r#F zLQ4=Knnf9?9C@?hL3QGU7ot5~0kk1Is(fa&0rr932Je9%K%V}rAy3`jneAuf>S_Ah zGJXMBmVr2u4>2KHMU!Y1!P~YKeK(#~(b1RTZ42~{uNVbO(O>xtq*)fES=P}}hbDFU z{kjKrbHg*}&3hW?+p2}XEeHNKtv@T#pS_x;gntIKf538__16cUsakc&TUv|W%#Jie z#_>N3tIE{hs*4Za(5B2>)%Mj1wVffqA9mRkl=gY#+zRy6VrAOA_U}gU-f2ytKhB!p z67Au;{wxqZM=69o^)P&u*`Mq7l!BQ#{$B5~EX?`9doP}KU~ARIu#zq?X69)9HA#tP zYxY!7v!_<&(YDQlJ#{u}NX(Fjvtll9zf3Jw1MOqf4?oOPqwx9tm{QQQsx#>Ilzva$ z4x8zt_JI1`_AK>3+Bd3y*Ur&0ubnejrdM9vUaDpxhmTVD{KDGM*MEKsS{}*rknOjV zhcWJB^jEsd#5S~1fSpYAg9n?zPA1ynS!JRfo>e9i&y7sH9u;>Z6NAXljZ9pE{M^XI z2=a3y6YGGt7aiy%6N^!!anEmR!p%0(L zdB}EnR-R#pXXP2hbHg+0P$4%wBZB&l->Y^LhvRogujL;MV4o5A>gP)u(>nvdT*EVHG`3RG7(03- z(%4Os#)gK*)=3&0sWevE9~zrwEH7}euJuV>SoYBs8}hzV=JXBtOuUG6)fZX!l=@=r z@TW8CO#+18mX8~JokE8)ucaog(2J(wod0*iv&u5&7seq#lxx)&uS7xA=bZG#TY%$6 zU)&13CLB)s;v|&oMqgYAJUe}HaX;wnlDY2bEEi=0VssWj@0@P>(Q0J;X!e!ae(Ki( z>{Gkm+FUQ;Ce6o9cA*%vW`82__3lmdbJ*c=%p$Kk{+B>JH)F9Dc-1(_LwMNPF8lDz ztZR$G9A3!f#`Ta=n58Nba%%Cvx!$I^9tdlgx zjvk3LR@omKleP<}P-xaVY5JgPaNfwS#0{OL^EE{VSGQ)0XHgU+PwQlkv)t3>)d zIzf}9RI9Bql5LlpO~Fm4`4BR;Y0vNZB&Dxvy&l{g2Rs?uBo*qA4z`P%IY+5tn>U++ zo07%`(RNv{2R9{+#rahn>U++n@)5l{R7fJK--gkN9(-IeYiK!*yhdiP?|dNn_BO%>I_X5dzxC!fMur3$Eky#rVX2 z{s1~!uG`c)Egfx_fzp^Mv?*z9FlkJ#+Z?epW(sXO)7U`$1KNJ4sr5zLr>A?}*~!W> z);*;xlj}B<(%Bb&-6qr+Q)ttX&ZK`p`UeKnKVS-NI*vu@9~g-3GW^%Nm|G{#Wo*;k zI{j4s0aIvG(%7KdE|SKmREh^N$H1kwq1rloypi{^4O*uKb&oBleSAd zwCPA^(sq%y%V63rL%D8qM8`Jey3M4%sxSPSGVuGMT(>#0X-ux$Ojp~*&3v&`{(+lK z!A-|`nFHKgePq*^T(>!5Y0MPdbfhuq9~hW_K(5o$#VddNL# zH5%aBH?g-AZ`9(b#xdx7(rUI#+*#$w^QB&ew-Seb&C6Ub*KM-r(lPGhhTo^QT_lYO zsu{dJX~E3a>zmTbwb6ZNl#d7>oGG~JD95DjGEmz^uG>r^%SMLn;$D`?*rtqa4q9yU zj^!(cblqlo>UsEVXS&YAXWi}R;iIG1tSO=XCiSZH)2rOfWwEtg@al(j-R4N9v6Yg> z$YavcKQK@lGle!C=Zg(^eZfekv2~KhMk#)4%OKe<{g7ocwkczqgBjZ#(si37 z*>=IYO&TvUwi&nCsb_uR=Zrzr59zwi5lv%ya8uIQ2&6GnaMN*Kru4y)^~S*c`T{Vs z^?Gnq(%1;3F;j5Uk;bHdU|{|MtlJ#!`l9p?B=--vS;u3$Zj<_=DY)rGXVO0){R4yQ zA20+fRU=TZGHpsLX>72*S)6G>yI+#XsUjZGD^u&lqn}ZJ-$cT6U4m}0FUCmD-;~9@LB-(*%{ikn?6yrmhyXl zslTC=VZqPRzJvhG~FX>+ ztCp>=U%rl2a|`DIQM8f&;d@OcA12~Hs;)$E5N^Srh{uEf=UC?XRO4FoKG*A;fw+X} zIEe3r$NGr>;8d|&|IayV=K9s*Pkcu#gKt*UuMFoXvkr*{x8V08Z0PsI9ne z#=$a}rycFiz#lKha{(g1GjKz+mCx$&;0A$&RN!&=^lLq+q+RsuDWqL)e`}%Lm6CR~ zkt)Whq+NU3HHBiG=aEX z=G+&R!c8s8qtKjBcw2H`vFgr~Om(InQx*y|dLQ(ZhjJ@J)IZWymu6e~rAzbsq!ya4 z1x>RLa?(JTW_txtXCzp4X^u&@hX;p>&{eIvbS0jd!A>6A;aPQQ;uV`RWVr<1GwafK zp&+({^-HBo*WLJjV`?vcy_w9DV*#`)6yp+49t_aCpoq`E@?9p zIOfbCY^r?RB%ZK|tayAzn1+Mn&IxaZj#Gz31Lo&uEY4``ct{(u!VNlN!lgJO4`+WA+bl~b&xuDH zPJrJy;k_@6UDpp?TH1Bet|JYQM{)cMTN0BwHZAtni|KuBvgHK7EE90JilLXw?GvY4kmwh0{sifZ&^lJ*bOZq)E zz8UxQn0*!wKp7a-bu25y+`=O#S3K_DR&c$!{q3cfqhwe-B zU>}Vs`0g|orHyyWZM;NhKfcvVwjq5qah@q{ycDv;6o8lXJLEQA68dEXUeYi7Ke`R^xlZ7H{D_g(1+B`9O4QR8DZaZUa`g4w zpY&uZ7w#P0ovCn5&nus0D!!J#=Ub6ZX6Ph2@4nW6M(@5Z<>Q9P-7S01^fXP_>DfVA_dKRkdJv5< z?|)&Y^Fln+=)5YFJ3o!-ob5OXI!8d?Lg%={{z(TqXPX7s(fMYK88>vkL}X;7V%%Hl z+z!u5=frbE=j20f=)4j6xuNr2z-z|gMCXf9t{XaU23~49*Mt1dbUrY-Ui{*su7*lw z>Mx^8)%#;0**mI~&U4;8toSDET&a@U6;OL|%JsTM=$Eoku+eu9R_x9T<8aM?$$Uv#)@(KAs`)dT9HE+v?+e!HbP>Ra*VVSiO~)LZrDVeg7@ox#8l zqoY<-b$YU&tqSaEuG*x&c{p>$nuA+#^?ucyJ)ZM#Q&*@;q4KErNzbG29agHwbq4%Z zo!J@J0;95O$wA!PqMzT0^UN(ue#T>Yol3y>*aGCrGd;~z7IbELe%`H&8KeGPx8liE z{qHnPSkdXj*%(#1a9y|J%XsH!ojKkWouhnbtLLdxCRKGeRQ$L+u;-cb$p>HPZder9 zqg*)tpfa^}{GyJ7_47Kjd{rGjPZT^XF#GInl^tH?&BHmK={s|t4QSfSd$=0i^2$eD z57kYYr~;LdRnZCda@!K6@M!C$O)O)~;_ZuA}M`DPH8 zR(;0~FMr_jcBN#_H$v5&=U>`|JH z9qBw%+SsIf0p#ZnzH>~#u+Tg1NE_QeZYynUeROedt}fU0Nf}OZeOAeAV}odC8++0z zwXwh9+QzOn+1OuoX=88EZ0rWj#$E**yFuL&v$0=-jlBvsc9Z(JI>1-=ei+$CpkQ#<^&7I$8^ zM_B-yn&E7O9e55lw=4Ze+T7CSCJhX(&8_b$;Ut^qUQ*(E9*Z{F9$|i+R`hQ->}~yxF^{Ez zHuur2uw@<#X0?pOc`OBZzXDw7;@okfuke|rZ$dE%nWTgKG5hlcf4AD-kAfe&kw4X< zW*koPhra7efhRz;;|$y| z`{OA0Qp=y4waF}wG(X4v8rUAaGJR6{#JqZ^gKAL+f_)RIIdahi9dA;<=%9@*+31-iZ9%(E2XmHREuib^6-e(E4`Z zIncT`p~aEbFLm!z4?w>K^r3amXTgSWQAMd-+e90)zqFq?u|?nP;)~>Wqa1ZZ`*!{`EA89iS!thmr8oo# z-ei^Yq%AkJ|0ptYL;L%H*Nnr7_G?|z{w`|3lQ{`8N1~cgxt$%)m{ZS=pHF;+e6>6IQ}X{`DOmU!{7jdhLFt z;4%2VFrgcFx98p5nUewD;la$8s>%bH&oZZ=!q*1>RRI30Y~Rz$v|`|b*Hq+oj`CyH zNydA~RT;mkEEjWO$}krO^Ikl;o!-C=oxW_~W#Y&x#M~KW+Lt@BeBL(C9QfEWK#)`5 zH!C=M8)m6g^_ito6;>}$^_eP*x;z2=Kl`Wco&u#1^_ugdgTL&5@qUx~%NB-~c>f~3 z{bg+1$?&qoNhW+m@*Xg zv+}Zf)Xxnst3`fpcp3GgW|Zs1%jTe5H+oDX@Er6QZK8@3FOxnq=`$k@aIAA|n(boB z-_bY(2->sS&-;OJr9eU|@Z#~To3&j&oW|nZQ)WNYXQt#NTF)bEo=Sgp=){RC`eqO=q03oyP3m55bWJ;Z*s5#V;aPP};!&>@AnIq;HNODYIZVB0r|h?4Og@ndyfW?fDAqVc5)5U>_HpSpk0Fp>?`QSj~m-xJ^-D z!+NV4^I-A9cFwG-g5B)xV>c_)U?o?%UypKGX91$_RvM=rpPI(q?UgdCxY%`kxfF3AKpz^v=y37;yVXS< z@87kkG+ywQOCd6aj%p&VHckp+c(9FT?UFbC;G<2TGsjxV^Zaz z+(!RB+71G0DDQ?4-$fZ;T+Q;DWvdhz-KfZA7hS7l=44%)?H%hM=Q+!BjxWzM-ZQ~7 z**it_8_;54zUNoEPsASJ#Mft(@LG&O9qVMjbt}qX{lhp|2eywqp#-S_K2Kchr8Rcx zYVhsb@2oW@m&TZQ;xrVozY2(od$Hx@C>qc3;=|_TtzN#rnd`oBdwtC^r1fj{bfq|3 zyL|P``sEwym6^3Q^+M(5&D!P5)~{H4+uEAjmn$<*{=4w!p?J0*)zN_Cywo^nV#h1? z;ZN)zCtk7IlowA~7Qw0y*x^}u1@X+ZDC$>?`=sLt4#Hce`lZqbnt|(vSF{1I1&0%_ zXh6A@z!MP3^kfyQbJdA2{}c9Q z`9W3S;LDwU?_YIh_#RfDQ1#tUUhVdT{%ikB-JUUH+c+;KciY6B{%5_$PAPs*mbO!h zT3*vxmPKFM_uI>P?gMTCcX{FbnaurfcPoKaoeMCt#=GUc_B%TQfjc|0wX5Gb%u~t1 z`%3C>s|rQDf0@4iHZe{~%lSCaOaxAKUN~DkM9SxOyl}k@GfbSvf;#~6+8i*By-d@9 z9|qYe1_*v*)t$`ynh>3M&t^QKz_yXFUrK}z`rRR8;kl! zYnu-}Ynf#%3U{{E{kq~}@#}TXQ;HtfZ1sCJTfIrWiMD#qOW2w88`>VE!otnL z{F4p2pPf^#UZYv-|9@6h$Coq4sK>H0v7>4v2x7{I1&w|K~B=JY=!WGijUO z7qiWC{?TNc(=La7UXZc>#`0S`D`2mC3;xi4pyFN3-SHM2N;wDS7~Vm7DBKvhC+ptK z`!Y8BxA^YI?xt0tQty{@LSgJ~n*RRDe6)c)k8P!Ya=#gSH3zka#?|+T=xiXaaF*<$HE`bMRmBA7(?m2u}&7PMzBZ|Sl#5;INOG=>aNJ9qeDG{?m;15|@cTl0 zTNUqbT3eFOm2tTz%lV*D5l8P6LAsbW4p3P{38`<*`@S1Tr$sW#^q5UQRml|08!8`CEwd`@b zCyV=i8jk6e>7#Qi{w*7C>9F%9sgV!Q9wFKv8;4^}iH`w7>c?0px?@83J823rH z5gY{b9G+AmSZ7tgLo!)2lU7xTLP1{c;gFdsn6ZH%8 zxcggFv^+GaG3%bpdo%9yZ}x2g=P3&nZwO6F`+0f!XdA}`+eqERJf2UA?<7t}(Kb~9 ztI_z*N~USRckV(x1qiyf+8((W!*2KvY1IsZ4y}C04$sPWh*xULP}Hv&_so1JY^q-> zzVi|O=Z5d(q2estiSN7)JU4u&81-}DJ92N8RFhWaT$CZ4i{f@~m4Vs84e)!VvV?=6 zKl57UJX{M1<3#wo(%BAXJ5I_Dw#Hm$>HDgTLw?c@MkfHQGH0=VJN7GNlU3#rZ=~44 zZq_BwDxU2+#(aHJU6*S|Hnp6kD*hZ*DOl7ou}oOQ))gaGnh(d`mi|sm>qTG>U;l-% zheb1UaWV@B$0o-hc|#>q0eqh53s10*Q!XgsZY&A*a*e)*g!Xb6MdXYc{%cB-(Wq5# z{XII8eMTFZeM{U8u!dVT!NK{RBLzRKLXFnLx{(F0_^nGKbh*6N^gA>8M)D0 z_W^G&4kx{p>+=2_cmhN_toHKfc;KM7y42TLy2p_E}~ zQ!(%4UEPA-(#L|{5>XeZx&>|JQH7!tk#5D2U_Y0KioKE0q;y}`mXEe^oUo0j#(uW) zp%QI#70s6qBBh<44)!zqLx7-jD<3l3r|d)GCF4VTMMg$ST!NJk?bYtae*~VD4-wCe z{Y?8*@X1tss0aDE;X_5JPz!LK_|V(Hb7Mb8T-eWUbQw8sM9v!_?QyJgYzlulP6xi0 zqh{U8)%x}-+IM;!*K!Dv=wdC$8#;ma@gXZyAOrU#`g19t1aR$2I?5e3mvyI{VXRmH z-&>;o%ef%z{55N48=5Vz^!;wIX$pWU#bmtjaXd%H^d$_(b<&gx0_=DNp)Hd8hy(YNxw!Xp6q@I?EC)H@5&_fiy0pPNxwR+voEZ=prl{+ z3f4}Le)a88B>n1L0{zC{XTSCMDAEyp8izKJk@%D>jd!0M{jN(wznqC7>6d*Vz{NYDk%dqj!$o`JTT=g*|n1@)~JB>fr$cPebT ze$a2Sz`C|^g46{i{R$b7nttPfbvdt%d~e`!^?uNAvcNjGJ&^KO%3ndgspE1t#{=tw zPQN3>7t;^=O%_Oz^UbLJh1LWztR^YeKCXUi-`x;oyMY!t5a8Wj;r@W zmLv5HVbRqKwjWPsl}P+p9*W?gW1%Nu(X@8-x) z@MVJuJ4bhCD%{ECseXLtpp5&USA=q}4f)e{ZTtCP6z=zZ>$95OvUQWbzMbpY(_!DY zBEcY$a$FOvd!;lX!0cvyJJ*k!LByr4>+9_Btn1r}H^Y>nsGoIx`(r4`&HDDu$ji<8 z_LqRyjKgVt`x2CU3Gf7n_FCicJMiEJfrM1xY3pNkde>IDJJY+d#j%V1DSGrm`tDEh zqS87>r+5G6h^J}nPLK9&?N@sIim&A_di>GEy(>751x&$-p!I9gnAX{jlcDv*Zyo4s z;kk!JI?#Hdc#%j2Em>)OE5?l*T3=$yi>G2tTWQ@6&r0jWb3^Noq98Z4-iZ9%(E2Xm zHREui^~EUH4Xtkno&&AB`__Tj&fEp9hiT|o_A~E#@jOs^_IpYJ_F*d?8~etAuchmi zQR=VH`9XI$L+Q=d5F_r$)0 z5WYGmG_Gt^`tEJRHk}MlNc_}+zP>(PzJJ1Y3$Wt}{KkPBo=`6`GE)3a11nFk!?W@P z;*}bCFcI~$%KzOc$PG_;4tcoY3BLzkGY%)7a2LvT!xOkylmkz2`Hh2t?fY8y;#C(m zwoF#XyrRuU*FQgQy&wwv@z!$z7`IqjnFTdA!bZW)F zbVvN>R_w#Ir`LN#!M*>A_`bUf+@!3-=ecE11U%(}ig20tJIFnEe*zx~qhAH^{c7J+ zxyN^}_C1yG4LPCQvQg=}KNj0_GCU;lvjzGZf9*TP7=+`H?{MBDi|rO5Xw<4#d;l77 z!$Wq6jEoe2)4<9@?C|CQTl|NABp&Yx5cRY2kU!y1Zg>cJgBubn<0nZH& zvEBDIZi>q970B-uXv3W2UsnmWOQjY`H4g6o#e+1!vCgq+o-e)+*Q0R=U_Jz^J-Z+G zuGF6BKLXEe&(fhP?b&!I`TB4r_Pe>~2Nv@@X?xbX-R~@YKLE;`oHUR-h4Jo<>4sLh zvlWBWjoh)bQ>}8x4$mrgMv^`2iq@q)i!s`L!Zc*T0R-pN@19DY5J8qFql+efia_6E zK-#l$z0%4P>dh||=i;qec>?i9iaqOwCk*sECeogz-XKPsJ_t`G58-${86JYU7ky)5 zCHg)G(w>d;1}hJd_N+dBO*X`0H#|hn$B^?e2Fsqkc=n~2X$z!{A7^{E)WCH9rVjl% z084y!ubhv8PGQ%G`50y!k3I|gZw=^ybZ&ysSNP1*_C?6UU(>;+En*uD;J7AOZCW`W zBf0;I^D!>dyG;8PnvvCiWj7z=;@PE_^pD;LIv=A!&d0!;68@`x(|Y2B3~djEamX_r zXx-diJ6f0itK_uK`510!-EKa{#dC^h_lwpqGd{WLVm`*WB=a%qFdt)6lKB{3L|aFx z;klfHpB5!FPn?9I?ZuET zKC5ItA*;-%%yQ$$UTqp5JQXs~YH!-%S$$T-<2?a_PZi?^<3|zWK?@4vyJ8(Pa1f8@ zWjGM&s6(PbGk)E~PuqY;T&MVH9m;jX2lfIl*&K|E=akIq48<3;_KNIF&nCXh|)iQ^x2(vHJdJY%cbW;2y zaRP?67eu=FtIV`4=+nwS-pBZN!#_xKX29Pxu=0;)MtdgY&7A^N-nc`@=t^ze@V6NTVF<9Gm7@0Q+z~kogxE&$*B-x#iF{yP4Rl%5Hy!*~$@Dv`{weL( zN(4EjxWzM-ZQ~7**itZ4~;n(KjwQwIcMwS?N=-RD8Z%}_`Y_U z@DFLf>iUlEF470#klC-7%<7l_OWLo}ejP0Pb?L3Q*J&GH7!DPu`4*+Z73(4>+tCp>=U%rm{y9MfytT)%J5NPA&X=nP6XlXt! zi6?w13r#pYTaF)a0?z>E0B;1Jkp)E0mTr}ozj{u z=`Qx2XLSBbNp~EUBa!anUvUVBo#mZ-e=Y58Kp%P6Us*^0L%Pa3);*=HTQ~e^j&fLl zkU9Cd!B;C}*nELtq=KhgWt|SHsvYGwaU8rD2TGiN!G0djvHC`81R~K1dPK@ z))k>#H?od%0qta6{L2e&XwLnd-efvvQ~8=sUohj{P2~@i?b_oF3r#bKcG~Hf)N#_4 z?pXJfbXPn4=}zjHgQH`{znI`mchb)w460LWKY=`BAS}y#+yT3c$rRdIX5ce|Ri@bC zQC67k9pbr>0ky!Z#xdyo6wuz`;v#A9ptp7K_1Q6k?{5(O3@dA-p8?%&)x8$tURZw} z+OM7NmCk;K_?HfxWk6|(w0BIy0Td}lgnrlT+jF*ehCj_odnZxvIwkhb5Xw4f@60rP zp8$$R?eM2NY40S`-Kp@YYYW(2>X_2rk@k+A&ubsV{b-XSAnY+~d}lv!lJ3g}HgvNo zuKf{3O&J?A8TuvbXsf4de84IJg}#!JoDfKNH>+wF-2BW&)=Jn#7Q3}QVLTgdu^+zk__!3kkDGvGy4jhy zPpmMGWd7*FTI&}4@$aO2;asKt@8#lynd`oBdwtC^r1fj{bfq{O>UHI8ivZyt&c_Y5 zQ~0G93j`zOGlF$pgdJWnaK(T4KjMXXVt^>u>X%-PKe?gHdgSBAFTEXj%{b_nrvKYc zE>@!4sdz3x)ZI##ci};5y3~WQj&#|NZ^ZF?vVcBvv3OS-zG!@Bmr|)reYAXir_U37 zx3ybYw66Qa?2LC7bt&bGx=zgA3!LKJb@Px`F-?@2VJ&O@hkJUJg#wMrFh7@GA_I5S|u|l>)LGZSpT?Fy~mJPsiW6vAZs(k9%ae*fQT_t z?IY&nP~32xuT-jch4w4xCLdQE7J^<^n{arl51B-IwZpU0EAi%-@)YHAD463&jVQu&VLN9v z#)|a7rW}iI6(zY|)Ve>;sT+%WVAE+VmP-3VkUdh5CJP7IzNle=n!Y0Ki&)<;##uOa z6`yZo)mOd%_J!sMcBD&bUudHt@td(jZ(opLrF{{%N%&$$kbU8bUZs5@?TaC>FXUM4 zmm^l%7lUVC=&Ljx^_UX(@r&)c;oZki>f3x`dgGoGTEs92xnmcr;IrWttDu||kSsPq zzZ;v(x+jZGB>Oh-aMnZE4gutagnS%qqwsS^aBc?ul_&Z+BW5I=3%p{}IZ+}w!Z-wo za%bR%+0V)N0Q=i%zI-)s-1s@^{DEpXh>+@rv2!r?@7g(%kz&DpLGi}`bJ)`EeKG&jfn z9t3;!&hI1Rlmf*1O0-6g4mY&OK;Lkt z#kk)vP80cP8(+Dg#p`iy27Ndr%0D~2V*FYBhxrhXbSJ=$7OU~6Tp&5o;$6UTLyOM= zuL*|}EnbOo-Oyqk@Eqiy7U*-LMQMjiJDfDYu|9~lj~3{YV^PNW$cxP$Y3ef7I0k)R z*tm|O1^S%E;z0MOly;dbfU$P+do#PX3u>fYPz<^i^h+AP9>++r3m6n}qD5&JNV{Mt>;gF!`?F9& z#^(mjMlEr-zEAQ+$rlHmFP6Al>n6vd9E*cL7TvAyl4DVh#lato?$$2Ny`;qT8sH+` z8QCYk$d!hk3yXKH>sI`u-c<^fsf;&b?O_Gi75>s#V|ZhS&woanXLevuYxjw(#>nJD}_nhLG9{|Tq9CIAl1&)ayAGLBgy*NF9R zF}<`A2hT=yw?<6rLQ)qZKPKNDys@Zn2r2!zGNw-1dRk-ZC6%t$SxCJ+J@yfCtC!bc z+zsdXg>|T(0HGh};|A$P>g9URurCNFp_jX&d8rFYU1;!iA$M!5V z#?;LV;!ox^n&vfPg?Lu=1z01-cDRVG;HzT8+lFI11aOQJ@^SFh3ma|;Z<;_K7K!t+ z?eL26U-2JiLp*Z~PLyknt*peK=;L#WtuzA1O>AWs@S1Qq#a6gBy8w6sMBS}6+y*>I z9b3`AEGBgosjF}don~Fd)w&$1t4Lji{Fr=q@M0@ByIQXz$D$mILogP#;EI!smU^?$ zhNu^w{2Ho4WaCP2u9154NYx)r%@g&gPf>CNkEYHRg1E1c}=C?Dpy-{)#K8)fmU zyw>`g)+KpgiR^9tP4?GX%Ud(|f2YGY#`mAfbnm;1y1u2<&AU_kwfa_gEuaV|>AL?F z>z+a`@MWx7GkbW;1hzo{^%g=t4!&;TOSy$NO`s2jL|=*>o>e9gFKo(Blxy{+@Y}c4 z>79HjcLB$ZFXcJlHQ{jbrEtHU^MEHnwAboO;Xc~QeJOnP`g)zApu@Xcw`g?O(E6KE z6I;D~=n!A3s;iqf|A+!=9Km$BQqrNKj7&Pz*DATAL-+fvzN9mSK5>SJJCrd>r^n}g z>k*uJ-pW()wW*@#_F$Dr1nWN{$-X^hmW7-fpRTfyb$5`3>xMfG(#{hgWKuqE@Kp<0 zXcsTAuGz4|v(g~(!Z-woa;>tE`z*SVg&UBO8(Fvmcy452Dav&t3mNyYmxcNoEjKhc zx7htYke{PWKpz^s=x}kMp~LGRo42vUmvK#*GGjefY-PQ>sYCJK-Qmg5ul?`7@=|IYm*u>?y? z)0K|dCI>pM9qx3@HV6>(l#d%6E`p951%i?4Ln%?GwZkhm@)Ow*uT)$h73Es#_(>F$ zi|0-{?QY<>q2oURuL*~fPJ0*1bwkI`0neU}^>tTn=vex}r5~I$z_EVnV=|h3rOh>V zGZsq+=;x63m7`2pStI=%Bh|j@2OUcLYBcy^9E8@P-%0g-3pe)FaHqk-c*A4*Q9kam z7ldABXE#avDwSTQueEa{3#EOf4?;8L`IYVyrlEywWqUyp*E?5p8U z$83WDVdq%sxKSV&spwHF9oyj*hZuOl7GIP!?4!=a5M zHzSU$N01py?)^_0N7lX_LK>8D>5DrhMcb#*dXEMw4GgH2Eas$k&QE^3`AHI5J+Qj3a|Stvc-p@N?kR%Q*6?`kA-N zJv=oLrTO{H9@bjiuEsI=-+!Yzq3_@6#&>>7;>gmzQk2_PZCGA=(K3w&`uaI!92w)@ zDicPApF`if)EylTJdP~wD_a^|H{9b-g`g1u!p^bApJW_a?;-1&l@#-IXq|crwl`Mz@aRgGR)753#Ptkt&W%`)at;G20+OwA4z+jRL_)MGwh1vh92j z+E=dWSjLfM9GSF7zA^~&bnjTcq91YO68Gzocj%0u&)SdIT9=f+o4vQy+xA*^-kxuT zoz`28MVr%god)ZkivOeI*Q_ZS-fNG!Pq+X({y$$J7^xlqx5F#O|HOZo1@Xc>F+h}S z^^?!XpGXr<>oisZ$IUv8$AH&_BVZhMG*^Uj-K^7~AKzx323~zXV#Wicxw}boqZ(R$ zZLf{W+oMN`gJ`39FGXGp;5$!Onq%D^Xl|vXxkUfP$e_7?#D`1VuW{shEI=PQrxfi) zjLGw^w!V1!b9?estX0J7;#72(hfLCy?pSvRx?4Bg>5gp>AY@KHZt(Srx$g@Ff|2U4 zK5-I`=W* zf%@;u%WFEzd|HIp<9*jyJN~m-dfq|5vHBe>C1E zep30I-Pk`h(&vy6za1g=Pd{i*+COnlsZ(Amx^rXy40pPd_D`aJ{S?_h?&)rT`(Q}> z$JzcF?sO>apF}#m63VI@Kg4R_+4~`6%vIVyajAY9?VsD%uXZ1Eom=dFF5Me!l*t!8 zO36_?Q%-z(d{1hh7w7Q~tO@`|$tku?U%Pzu%=+aU z>Xn(bHT7bu0&mtXU$%b5(%aV7+`e3yS$5;KGi&PW*REQ&zJB>So98E$8RP5vj0yh{c?@3g??8``ZdO?7^jkcQ_-*cSg@quQ%=8J zA8euDb&`H1{q~X5spYTxnDX3y#1B5unP+S+2leON7d?fWT9ikjMW67txl_Db}wUf(scviidc*UkXSuTP1%zAYL3Sv80zf^j4J)XPKtG5HM z8HbZz&F|aJ0-gZT-ZOB+tbaG*!3_clsle0qY8j)JKAQNL;Mh1#F>2a)uKo5>M?B>^ zBG(yPWXZ}JvJH+0>7!v!NFPmV9nt-IWl6uMoPN1R*+ReTB>n1S8`F8Dk0zBa*pIc& z(#A7J789XS>$g(*UTG)v*Tzev>spPjX>UjyPw#UpT}vBJ?-#?ybFEj)wa+4;c=GW> z`Y*^47$+sruV4mYU*+Q_@r12z#p5%Ab&kCq-VETH<9Nh#<8P=1UNsKZmk0eEo33^>Qp+^7AKC45)?ktOK-cpM%VG7cYm z4cdtqr&d{F9?L`&c%(0J&ilj*^TYts5y9#&Oyf8_MvaWa>u**69b)>8$Khl2E93Cu zeF$2V^lNM5VbsVtycjP`hnRljarhYh$~e4uACi9co=D+i#i)^Sc%5#=XwmzO-ybu> zKm_e+Xr z;d3)3+5-4l#l@F$dz8|-m+})dfa;uYRV`FK9zpGFOHm)L`?~(9&w3tZgsg`@S1?1Q z^g|_I50B2biNb%8=2>%pQu^U|a7fT+$8+nN9Xq?tDo5<_tiD3GG5A_k%8jq^7S!3z z9Gd>Dg})ei3ed?#QLJ-l>hU1ynjH+Ecm!V3F8lFR*mtgJ*CqllX*Vv{B<J3Ol{O*}Vo_q$L(H@b8^@^hn0ZwFp84ma!H-RRO=Q|Qw1sJk;w z%e4`5ZG<1=l4JdpuZ^Hx7xVf%k45Q|q20&bHsX+Mk3!dS#3t%4bwjBe{$KXqH#Uyz z$`>sDk;KrF%p{tLoM@72S)Ng1hi=KTOzk+CrbScqS{j*=w9uPXo=B-FQ&=h?MRM0! z7!x6X=IJ3umLKxLyKC$U3xDtje-H=<2oQTsC(27^Gr+TV=hGMunB7@mW@PNH{PbpG zc!Fquzq)n0i?_SFF4bM#)v9xd%ldb^>Q>eH-E+@5_ns07Yt%QaM%)#@#t$qO(4ZiMFdJmp?QVF#yemh{x zRVKk!@yprmieJUABYrF4_SEsKw%mDd&r&#P-8jOkVf8A0Ig4HKtN3-qZzZ&zgkQDg z)Rs%lmP7M(IWmboNft-;?dJq`Q1Tr1S4@zwG9PCUqrFS31Ecdtvi41Pw%S!<4$Q{6 z~Ac@ z@fE}K$#vr5-~1K>=LnQS#wSq;KI<(gtQ!mK`xO+_Z61q&&fvex92w3xUqO+1K|CMN zZ_i8Eh3kGE`-S){NOt`DC=MJmhl2mYcb2cd68%mdOVupSyxilA(Qd_A5zjzmkOG+t zoK>RK4mc~07oP{9vyCy{ zgOIEju!FBsblHe7giG_9Yrhv1$7f@Ve17Dda$Q@Ojo?DmHA%YcGF zzB6x+e!S_Q9zHz!aqmBUalH8E&hdKv%ALXK%)c*T5q#tP`#oR##f|M;GTFFa#R<~c#+cxWHz(@_ ztP@AluZpu{Y>dV6+5IZ=`6xniUAte^-S*A~beY;akhRwNAsp*^`G$BxFlb_>)N>NZhOZamul~*y+hrUioLVEI9)EEszg!~?VZQmi*=_3+O3SHJsI&;Rj*r+WYQ`u=*UhK3ivb!ln(9F|L$&2m=O+8tZnh3W`NKgreu&j~}gl=j`$195z| z9w46|Ij3CL)&tMsLPOx&f|I&?x4_>2sMxEFi8I(^#8t6Z^;uAebAr7}#5ECn``o{Qam_RY>-1h} z=iaxCu4_DoXb{i7TlF04o}}j(dCfA`qJ0k0HwD}mU#a*ZN?4DQdEK@4PASTSb>S;U z*2z*r@lk~2y0)Gx;RHiqO44&v;BnD&)Nw3Hdd|mneeelkGay^fQ4crJbCt+zBGwM# zqcZ^|kJWqERAwF4zWk5HfuRq2@0`t{Yv3bq5;loBAACY`zcx0n;6MXxR-&&- z*i>JH`XYz{%6iLVuc198p0OlZ9BI-Qq4v<1&jsJ(v+W^xrL(LDqB>gI;{xQ7ZJ+3Y z=dd0nX&2QO(NGUmBC?6tQ+p^7FXp+9QZz2>WDjK=Yg;2XCwFRNtrX$mY8=+$_==I= z@b~2NQH12WcAu++3sDax^|_|Np8WDg6G@H z*eqo!(H_b;HhB+1f{_AtP##4OP6u)~P4aP{kX+ZsX1CizuGmz2NbMnF zUkDJu8@2s- z=$VhlQr?854Yu3eumS+5H5{K)W%)o_=@5A*WlJ{*FU#Nd*+XPm%2d+!-Nx*R~HWj*l{nbIr>s$mb%9W$;a* zFgFtmu}4`?$$1TI*c!ns^@+Y0ztl6-nTuIqzO2%7=f{j4Or$2Fca zqIQowYRKH(=abxnvn1L*8OI~vS?#w=b2$QtEEo zIte&)kEb@7Q;Va7XtU-ohp@reV#YBh@=cMF^+G6D;!hai!3c@W+4f5upKZU8&ySo> zu4`kglR34b^^^OxF&3LcIC%9Nh@&>C%kVG}KW#i`ocf?!=Zw4PvU0|8rhUd*+l=3x zaKTxEE;~6n{LM!>6+CG^lKKhMPe5IhqMyJ$KH6lPuYQ8(muIKdPhj`0@?yWZ`i7g$ z37mWTCF2+q+X2nG+An+vAbtbI57x{-YzDMZ`^6b!P3kgKR_&LJ<4oey z_DhQP%cbQx_c-UF;@yAu>OODK>)CzhH@|y3Yd$OScp81l_{z3WcbbK0QaQe9-O)ab zGNf%uF7a9U5e^=!|Gl~8MLhgqKIz%B&wpe2EVgE6=H_QEV;{zS;%A>nV0$Cu(k{=; z4X2s^_Y0_#+$V2~NkpYTyq|afX?8*%NVwoz;_LW*Wfwh@cRg^%kOUpN!{%} z+Y2}_DNI-j-`PNf+~cQ;U%t=Q;+OMNZT!wEegkP0IaT~N#IJK)R`J_<{Bq8#jo(GZ zui`hNZxi&d^W51(``z;w|KFzZtjwKd|9R-gJ$t@$-TM)G(RX^U54~lNvDg)({7Xy@cZ~{pwf2cMT<}U(NYnF8%5i@HOaHYm8av;8tucVn*fxW7R98Org-`XCVeC z>y*uC%Xb6YQGWu@L;562l~ZP>=EgX=PItu|h~ULK3Q9j*%gZM{rB>R_Qby?g~H;JfQq8_yNj8i&_7 zJTX97Pr=43U;M8%4livDm(BPKHyVe>!;i$_v88eN=&Pvc2(|HI{e{G@^E_s?@mg!+ z5x>@Zhbl$ycyMtwBY%hfo171tVvH*X|PFRPEnJRih9iEE9+YaG7Psu43Cio;VDo#%S1 zjhBLrSMm2(b&1B|8|xB{!>`jN8izNJBlzD;U+`{xtkpPt6~7vXSNujTlq4I^HD0G< zts_9M^q$PVR>t9h!@hct%Ttf zzj%(Vu<3-Q8_&pGf{o{lYqjyz#!Jt}Tby2;ttO^V`o`O# zqI+J=cTGdEF0W=@^3oR~ny5h>K6v<%NIc&~WJdhGW#^S456oS{LeZd1bKTCN8E3zx z9m|_TrTDIr@~fNyk4p~CjpU|(9Oo3`vmx2B_!n_t(i{r@3m?XH1sIlSykfXDc3vU! ztP?R@jmAeX%vte@VLk(qRmE^)3`;~_G28(RS0nNf40C3@VpuWECtxT^4@*=&bqqh4 zk8eC}NDo(|?-2}h7QAAZ&p`DspMvKlVOS#YNf=h&jQVEM_RUBHK1mkUH{%w6-;h43 zM&Kj*BnZLZQ!zaC&D75~%I^lY!Z#yPc*Srh?7GUN*$9R?8(#Z_d%QGq zZP9pFrq5{B%>O=o363#2-mc_Fsz2AA4?BpkZ|M8(X@1+C-b7@ki~Lq1F#=iWI^8-Ko(BIti@#cSi zxAeb!==T*57e4O0UAo!VU--E9pZxJJj=%K}^8@wzm40wK^Y2So;G^i@>;Hb=U-bT< z=WD+upEtngg3ptm`1ZH&d)Gd9NJ_-u^j#O`s&nA$xN ze6`Lm;bQk>9iM9V)b=%7WcN7ZQ|%tLd#D>zv3o9Do<6@cIVlmJq;WbU`wlw$p|6?F z@H!t^Y1Qkk=l|MTX@N~_vRi#!jpM4p!(LdJT?o?M?Z7?v;s-mqq}mx?{MMzV>2p{v zT{g>ES<~36=auk?NF~S>v5@4CJ_8;Xf7eUkTS0M&t+H<_WW>8Rw)z|n)b)3TSd*wv zGS-?K!{BYsYs@Fa*<$u_CN>XcO4cc3lr8Zw#Mw1z+dr;j7*3vWp8yKnOY<3r;~dTkK*(5-rnb&vNogm^1wA8*lq zMjYNsxYsC&{MmRbMVYWJe73)Vd_IbhT$i?0bj;8gPT-=~rtmu#yiupQ=rteLEr3@D zn*rH)qutX;uSp~)32$o8s69grP}W->#|hhh*ZF@VP5PHht2ysuVOn37?HFlm*`Ucf z+d8&!o$gSB)HSAHTL{DznaxIrdTiTgN}X@-N44e(>V)n_JHxzj@!(;hUc;eEp;T zpVqT&=(iI3JXW6C-v5K1qrc`*wXU^ucpu4jPPVb=^96(yr}ItptWno>E7n-|#QxQ?$pNca%PH2v z0BJJTnv0K?@*W>uHhEgJj5Dz#&}?MRf7k8t(Nkf7G!bV_$43uqeDpkgc*`cIYL@X9 z?Pmz~3cw!iW$~AnupT8IBiX)#Qn0uBPxy-1CF?v|Lh(_AN`l?cMt|hlVq{^@t&|};62E>Ju}U=Ez9kGmg6^F?>h(srRigho`byRtP01VA@!kR z&GYO&R&M-sVZzZwtUd1TJGfyws|{kMM-eN17O~RzKdG@&$w4Z3H2FretowX67$J%6 zQNT7|yVyJ@g&|xTk*KwK;`nSll8^R{kX+ZcdCIuZ5SWtu=2yVe>Ub%ifsov<9WQ0> zkw)>-Q(^MZBs{9kqc%_4HqYcU!{2-qBmI+PapW=gIc{$lV64*(7_YXs?|tvVz7PI( ze*VZ|@6)$_cmIyJdmfZMjcg$wfa})S4(py6+gZ4nX*-DbAS7)v+d;nOGEJKcfkF7@oyS+vabJmc-4D& z)BB$9eeielrPX&nGk@gIyib`vs2|z+05|5GWIBXoBjYIPJJV8iuUArH81{WFvPm)jKMew-vLth8q3QAHxl;bUY@Cjiv zAiEzrhXalJp(h=2s6GkxNe}~+^|Z!tpBQ)ZNgUdMzdAH2DmvjlZ_pd~acLD_KE8AO z*8C)w18>#FiFOz`1^+*V|D)RnzT5l5o;K?NY28d^m}7KXq+aVsj<7ANkpYTysABd9dQ5f3D#N z*HL&4)|=Dn?{&=c9vfr6T)}*~2J_{0nCC=C#XKGYNHO0C^AnSklWuyx+3{9ux3~B?9|JPG zu#o*cMAS1vqUQ?OL0us_=Sg7*m!d~(`!0@;dQ*PGQ;^T+N=R~D+rBH|N7R2w_T3rq zxailHz_)_Jdv2s(cj3AP@CacuAX~pu569bg6O(Pruh-vrTqB=vxB5_6_xgJB`EM+n zj?CESvfDCMMgMU$0;D>n+VLXnwr_P&VF5*y{&J z%)dCib$5QfiAl|`H++6$Ns>puc5HZhY3cICbIVIJixCk?T&?%L+31htD**-UL^EFL zv(cv!B_1Q$eYQA0_Qj$;4Dz}3vC80^LZPpRg&3f2v3(dfux}fRkkrraW4#B4XuneU zjOw45bk48WE%0* zC2W~&=k$_34Mj@U3!z+zzkqf}ltkui-4n-W_p4m(nC{MF2|LCWV=c(9cYig%-eKg| zDpuEt?8j?cy-`PerUlIz;OyD40V{k|mM-4*b- z^eeA}Zv`dEcUQu7eeem%{o49&9tRrv?!xIJiDUG2Y=(}_AOg)m%!9mQr6vnL=q-eDqYi^6TCHmHG~r5g-Na zKyjUWk> zDM+!FQ$JlB^XpY(rAHAfeHO9O_xEY6)QXiZYkobpN4Cx58ZYhc{CX3UnqN*qQFmuZJ<&j(JU*&2OpryZFLP`OD`nElw^5zut?QUoXHs7(O4J>t2i{kS)<%LTeGn?sdvgACI1`un-gW4xI4{Cd*X z@*T>00qcB~GG;0+rj7w|UXLE^Iryb<73pUf-`?$;S`dCEI!PM0epU5Gl=3)W|;>TRTZgK1@>X-{1b3q)YH|FBRWE=D5J(qj`u;$GR+DqGh$xAGzU3v4? zZvXqDVr_PT!p1QUnr9+_UGOhASZi0_JTK>VjONV?aAoT>SARiw=gmX^F${X{dwk#i z;uB94pD6nNyt;TR zVXq$?G5^GWVb2@x_L!&U&C{5t_?@`yTn-7e{myyw_EQyrlH2}Q>a_i9znAwuR`zq| zNqfuISJn$y=j-fr+_UTZSk5`~n#9?s^NzFZ=gSjpDbDx=47DZ)IBgjdm`U4~`T1wO zorgc@>q+v_4dV8?H3rJMC&oa#ARnF`lcvPkdacBr5i(tv+V9AgB0O9bKHGOdJ|9I$ zFn{maGH!U&IH<-!iGeiZpzitb-1}J94Zzp?vG(@8?}gd#4tqP02~V~f=OFnk?!Q}g z0qdTq3o@PyZ8E5^WZ7=YICl%3VZH(@DzKgU@zl2@DzLLVb3`S-eU&?@41Wr{0*ZT*7Z62KHvYo zhirF$H_uVmf5u*?U)^rp@4UxzFk>9H=3p+OVKZW5S~%uv_RVVWKd#@|-8q;s4qJ2I z>HN`9&ME($jHNo~zB}MPfAqHo)D>NDpEu|Y{P@mqes|~itx}lzj{eQ)92}096rxQz zx_#igy+7<}v+qGHYEu*1H`}CA!7|!f(f;1F?r0w@Vb)!U>(PD;x4($Ovv9q>Z$ffl zUGUDHHR~5HEze;iGKt6Jy`$VP?;U;KgP5Ybkuj&2XXb`$rfG9$dFI^m^Jgzyp1w5W z4d4B|?JuBCywA-jqys3?XCrMpzk|lP(IphpRs4v2^a1eqFVPyd*pC zT^t|lBfsJA$hVg(A@RDTB1*J=oEt6moa4|_&i<#-*psTgXiJ- zcz$lny<*klcVrK7B_yf4?elmI2PTCHOX1@iJ->8fvVD2)h<9eadm+qvSKHr8ceSlfl`7QiEf&46tE zN=zOTCM<=|=-08f<-L37cJA}ul@~PcT_A~h#acMk%1<0Owa-0N0LrE4IUSrb`^XsI;}P16UQ{) zo#wl%^mB-(&iO0RzjDlBGSXz8pn-hnyF=ef^90%bD%ZKSBOPq-ec)4wSS8suOyfL3 zV{OZKH<0gqcj#9s#`20W=X`gMx!W$+4dB<=F2_FVf9uzu85sZiNBuv2ppG50(=-vm zfA&$I+TQb`?E<-z+^zVqPGmYL3an=gGT)>GE){*{h@G5X5((Q$4?BY*L!Hs!(lRlf7! z0cQw^g0kGV5^S-avaUFD8#|qdGuJ$LOza&{a$eUrfo)K&&!E>tMu)~92x6o4a^gi} zqrZ=nJk8kX)7>2#<$Wak6Y!BRP?m8ReK&D9Jj$DhkP(I2yhw3;wm*S?HSn#V(6(mbb$Na}CdF|_1?(4+`?dAm91b+pcVU23Z5;i+ zF=eQe@logecn5>eK0qrZ>x92Dz*wgfyuAw_dVR$=Hofod`QJV>^gwB~_~!hP-ktDx z^?mvS6I6hlPkdOO>nRfJV{5q1RfV1@h13IP?B^6 z`(Qr!gyep09q}R#G|~~yx$|0#OHXl`jLVGY)l*#7_T5^AOXs|L2i*1LPfR0GM_(eR z?CxKEW@v1krra(2wxW@Vixcg^v2KmYvhInxG2{95cn?CNqYBu;S1r2nv@nEABL=m) zF^*2sWpL zAzT{qsKsU+pN&oOai5S}mvxEyHs*057i_NJcP{uIqzONbc9h<`o=h zgiX!8r(?fGcDU@MZ=>D0_dLzL7qp>lzv}AgO*W7z}pOm|#+73t8+eK{`({2~TVei^5YP%TtP&(Nzy5`H$c2V2KwA)3^AEhxw@$+@Mzv!AjO4~(k z7t?MRUGpocEUGM~E{l%&hg23-7E_l+$NW4hiz+6Iw6EJW7l^it+AgNuF1qHw zP+3%2Oj{ORb3Ujnsw}20i>|p3R2Eeh)0Rb@>#yT_@2at zTyS;N0P0<8Scsy>=_cSocJXEoK{I zf-B0CtQW9Oxe|=U=_ngxaeT$_d{_jO7hUE$SAV3*Z(Vx3`!+u?J~W=B&j#`IyA^A! zdm`5Gxyvl;vuGba4r`?VA=Q7X z(Z_Xt@CjivAX}d?$5kVJ77i6wKY@-F_9#Q0oBusA>Y9t7>2_ajnAz#Y>HTalvfS=x z*^Y5-_tUUr3PDS6{@rc6@0x32)0a1JJp7$j$BWMHCept2bYMS?aFFN<2K6(+<+8oImMb|zK~{Pq@}#aZk7?e$vDnLpRk^?Ucfs0 zUSi9{#bs<;CXTNdo)3$FT;n&cG1AjGtBWmj6?`tX496ny83^%NkZfBfDMotAF&E0n ze)sQFzG^D7&bQ$0KCJPZ^GmbS%Lw3rvaHvlefl`Om3R{o68W?7R*LX&RrqYYkAYy^6WIsTi;v-? zFoa7UBiS}j9G{Ix^3lE#lIz+wPq)WQPif8~wRu7zCuTZn^SI_L8ad$Z@A`>p2-f+# z`c}P%```C`?}NV^Dy_~R`Lo_n{ii=azT@p4zq*fpmOG#xulL36Teo@K7TSZAZXL(W zx+jjIS-6;KTZs1{B<*qmJNT+aAJC^8B_1Q$`XG+a)(7PCd4iDSy0$(zjSCHdXA25> zSZKR_1qF4R$0DE?@ZZG;_8RzBPtx>-yL)gw23#TWA&s8u`Fnb2W`T zcF;F8HTdnPkB;~B$QAh>_6F}l>hgv;v<`!q|F*a9eec1(5B_#&{>b6pPa6b2D0>>= z&&P?o6@RRIBK~HxjX&Olkl>(z9emA#zqo#ujlVd)Vt78e4*7i9z*4Sjcwr!QTN~*9Wf%TXRc&^ib?1OF!`=H+HJD;iTg_^yM^x$5|a<}S1);$r2&E-DA%?1;2B)VMGwA+bGhij*TLta2RY^< zT0d+CWb45>9B8BmH6NMgBNN%-vXg!Z*L-A$HZaF0yrGItxX&B(27c_V-ucb%?i{~0 zKgs35Ti)At`@bW^6BnOC8Qnhc-QFMev{?^G>t-s${?<0L8vd6zC&xFfJKBfdIol>7 zuJ4i!EV=zf6rP3mSYJ;}&rF}Yc=qD{3-D)~^$VAl=hi#77cb!FL2qyn#xtMgAPi?d z!(I%C-^nEftHCF3F3-#jFU`ELMh|dYP75tujTz@FsmNztk?I_8c zc^Es%pTx)d$ZvQao^LN#LX!Fwu^p}7E0Ox~?MwYev5srbhd&QiT=dU1{NOqYufclr ze7t{d%ROM#W32ZOS3;7y+xq8q9GDa)EQL?<0J-LUYZd0b-N$eJ`3ZyiMwq8;-0PU< zJvPRCxq|s}4d%=1Fuxt=Qq1EafE4qMFn_{5zh0BMzt(PV@pC?3YccCN_NZfoM8_4d zgL*>r&6C0qE=7mfKF&Bk>P-0!PeDGPDga;!eGG}8fj?cyz`TWTF01!Gsi=Yp}FxNfw5*bK!=3EIIAG=%vVr_V}I zBrf`F3a4?=XVhgb`pn05eeeolGay@^H6EjXVpQ|%X*@t=hs(~z17N>6<``;rzR23` z`_)e{oBe!VS@spUw)<)L3JPIc&xK%jqwT(Pe!TELmr zJr&82?akh&u}Uu9OFjJU;Sh&ND2FNcI4+_WLd5=O(zvBG$1K&;O}q~wxm(H}?@@G9 zNf^SVJSAH<#qrtrBcG2VB-eceJEHMY*Eu0m_?-*>h`nnleBZndugmvu>$)Ota1Zti z$^F{+Ydk09#OSGZ<=e}9EJyS01)^%>%r&0lIxgWfuHu5TtKcKnh%=TroH1rvz;U5C zoF$D*Xk)%Tjpv+4JV*2G1tM$Xt%SXPaK!wJ(`((GZx4D+^X;8)IQYD#6Q}+JyN`7P z5NU}&p-uVr)^7iM^(Sb)y`W*Y+x^`56P)wyxqmb171QZk7t^6Hfp%$}AAx!`Ykq`4 zFv5TJ{02if##?3G>-i1VI}H}6d8)u~07qXI{RYyvVLfHNfOX!Z_zh@(M2W{pw%;I* z&&C<~e4ZdAxvuRu=ze>~1Z?&_zHfi=i6@FrAZ^m)#eJB!ZW4y?D;5uO8v95KW2Z+E zJAD?h)A#pj>~uXAv!7>gmjD7w!Gw*)=OR2@jl*IbpN&QG5qCmzT^oy2xX=)ol6>ed zg2%xA+_+34i>HRn8gO~!Nj zJ|AY;D+XEi`YRdsg6+mJRetNSTl;1X->Jm>w`}J&@k3eVLfYg4)+xKvFFVPD5t25~ z?w7^!*}8yye&l>|U0WBp#&ec%E*D+!D)?MLe;%`3M)1e& zoa0Y(?A6RA$P515bL_eMAFi9mZ=L_4lHsz543|Wo$!>|Q#@PET+M{mOeXM(;Un1lA z^*Ut-`FM6hak}q0$eD{BG>;Rx=)P;APc4PeA^L@{Z=hgE?$gmU~6tGU2)4r#9IC1z(8cU>k^>iMc$PSmC^g}r3)!Tr7 z`nTrhD*Z5%SI=bCn+mh)ZN+^@V?sL&q=Ns{t@nCMJ>IjB=oCAr-c`sB`REg-7?F?bc22!9?2D2Sx!U|%aeN2xWBCowL%zLS z35nMw6;U|ep@c$uIa0qyIrZki>(cjo1$@_0cn#hsugm+l$5?ROoJ&r<*T6T4-wVk- ziVwVfIrWHlX4HEz%&1q}--}{i^Jp@UW_(UPBwkpDdA6V3fcfY<7EIZge<^|~$}9Qm zVSYk{I$VluYfimJm>+9rPQ9rlyN+|6y4A13y4Tm)l}RFH&8c_y-&J%S>v0C}!9};e z1ilp%wk3^p>n=1TK6r$rU9scKjmNH!x#!etI(Oy$rQG98=3)VqSsYVEc@q-7SHKR+ zmiSMe6ozmqa%acx;`rD%mEZ6b|tac%d{;G8b){zm)-1y(d9sk@D}q;@}?g5@X94cX`Zo!@JwGL_gH^Xhq9fi-vx z=rfMS+_)`t&tq*d`+4)S>@(i+##&?PIa-iG3{1 zn-{3~y!Nr2^X4_#$3jkt#4+XfKGqPF0c~U)QcZf57Jk>WUXDENW7YZ&82>B;t%Ug} zdUB)oOxtqgd5vuu`bfG}r?KwIIt_stP?mAV`w)_K${1x!;-7K3BJB8Q9G|VzTw^n? z@z2w!tBc>@D)?4V*tW3neuq$OA6;v5G)Eq!`R?O0-JK&3c+(tt z=QT%O0D(Y%b<}szt{i#WN;gOI9-q-1d3D?Uyu@ctIp@f0Ex>sLnUt{(%lci}^?ulUB6_q{zoyZ@=1 zqrF29lvayxA}f%GtU!CbJ-7ef9v`zSctYmi9xTST4}7op`#lqbzqqm88@;bc3+Hq+$SX0eFQtA^J`{tA^Lxl#v@+^kBfi#C*WH_ zp-yDsb$Ncj)wL!7%??I+efQ8#8hcivvU+>k^^6|l|MEwR@#!VoS+N^Czx z93SpU;($3gajuA?4TG3KFh)oE{%xPes3d=&&DVD>Rs2y=MpY71m2{+>yN+MQdkq`CEiHk9pGeH~$P z>&@-I0K3YpU%0e9x8BIo+J>*On zcl)Nmp~u~GnuiTorEgfxrODiSFKBK($Pi_X`2!ncK0db|k}q7q&x1$Je44anHMbt0 zNNqmN3A4NMUvO??o_sEte+4ICdyU8LHOi+skK-==&1>Mhj>2|@=j=z}`E6e*=jOWP z(|jF#llZ-m+^_MKo^;Nw_xK@q%nzB1R4_k)-gu||DRTc@2H!-yaIxyA^oAF|b!ln( z9F|L$&2m=OY9@H-_j7Goyn$!BE%Jax#%$Z?J@7nPhfid2V$x0js4Px)#z&czT96=+t$zV=fn!MU}e@sIr*0EV|}?P+3%2Oj{OR^B<@zsw}20 zi#pd|=laWBsZRU4UFZ61yQuAA+U=t2Jam;smBn;r5u+C;&7{<%u@TLFPkin6IKB#2 zn+J9n7ES<99c!y=$e^Ehtm(HdDWpXdkymc#25XMv zPn*_jt81GSYuW$aCEIr)(JyS%i4Do=7|q>5Ucrr>b2W}Hw^(x=UpunDXi^{h$+?eT zH4nd%V`q>Vf_AU1{(O`9;wAfycR)Q}?~B{FZVPfk@tu))tkd~;qWNN~k`z?WGv+#*4TZl++fXd40yBtgP*OwyU8o$`g@nOXH>7{8EZPmUF{hv8&JpXnJ|e) z>h{d4*QDHEhg#+rL>cIK-Gt@j&mZrs13pRil~ z#jJa>zj%2u>o^l%Enl9j7qHIPDe;*R9*mHA)wSQ;isQ3!Mm|4sKDn;#FXp%DhQOCJ z?%*_dT*e(-1>Xuv(zt`2xULJ%j)LzP&L@P;fK0dmKDtvTK$D2GrsFexn@x14@z{ew z)UI3c#=1M;t(-uNxN#&|OUnk2mG_)Z<)Nu5L8lFoM?*!G(MO_D5* z>}#%%wYHl3K2{K%$#QH)`Zo|a?PKvFfY`^{ZB~Q-(s#0LndCl}Nnn$VvxClKV6K_U ztg~g-)NcTP@p2HH$uib-yjiVI<2Y&;tR;@4K4pS4iCAmao_Vl$^U(MM<4JzHJlHeS zXdSbRH??PK@kV>b1#b@aOfc{u32$o8s6CUqJrgD&N|ME9?HSL{yFIgTksabJxA|(% z)VBGwX9|HOWBy??pbgtIVS**aS>L*Ezpfv77=CLve8yZv$MRD?lYPariZeW?Zj8;e z1ZQFLD8*UYI9pVln8f@BHR>caGos#w3>mZ`JAm+R{Rw z!pi9Of$#SIu&2#qVPrIwsYxFqfsN-XZ;~np%RY>PV!T?2>wh2{SaSPID6~6ykM-@J z>6z(s7tbzV+<(D4d)91RxU@Wnjp!`r#S11*If%xZ{@uY(Y|I~Vd1h{SY379`Z@4_Y zBv9kd^31vA=Q%p+(u_Ae`n6-j(@RU2FP>XonpwnUoaqbTrIWy@Vg}IZ+4k_vGXHL*cf(p$Tk9iM*tTQOKXf$NI=`u>0tDSy*Io?D zgfP5}( z!5fkKHEIi%a6Xr|;8pOgp%D8lacw~v*ZnGv3(5W3ZNUv3XwVi+v@yROA_lcOpRy`M zJ<+Y>URn2g7>;V}S=d=jIL_LIoVV>0N{q>hJ@K^k{ICZnEg z8!0va#g?#Tn;3{voNUMO(FTu>jUb;(Jhbih3{pZcVRzEli01oPThyLez*Ke3Z&%~T z>IQq}!AN5uZGr7ONSLQSG1;#CcK!LDt2m2%5Lw5W^r(~5tOYj{mYkoUm%Ens>`+O9kIJ|W-KI5X-67oR+ zZ<^n(;b7Am<6Z3;#wW#(Kz!UlX-Ry>IlrCzSnq2_@m9uq^V@T4x7D6OyPx?Sck0Kg zombJKyj!$qobmuQn|tL-&T~o9o|#7bxC5m(qyA#)+n|bS&+s9DT9iwY_KX|On$K_7 zulenaJ(G33Mdy(S_6m?Wc2%TbRl<6dc#LHG4@$w_>ObM@Mtf#=^)`ZM!A;vw=U~q` z;Z5T+8lNHdhEP(oXEeVZA&fRH-F!fpt9Fss(LPqy&&=o14L)P)Jt5IucAKA&uN&h! zpK<(dv3p(!&YK6V^Bd$nk0j=)Db64icHb&DIMe)gL8FkqKGXbme9*bYndY|(aK?Yl zV2xuUlk*&Cemg#A8*AM#uE(YCm^iLS^V^-*_$LuyY$q90%Iz}B6bjoBmel9~r7h_4{B|eWnBQ(H?|Fb0HNRbeyPVp6C)$|buB2Gg{B{Ie zZn5T^->$j%TxlTRbEg&;vY*>d>^R~<)(co?-%rLqF`gDB=@;5#pW^szoaH1wcVf~t zx81(x#?SYTzq@5J0c!(zf!&%PnRTyc14i>BFLps*JKl#-9M&`sgn2^tn3IIK!3oW4 zr+Mu}FLBwyxB+Y#x11!+=Ybekzk%kp3mQzjkCl^n@rg<2ymn36GFx+R%S=Zt*pH?@SME7{L$r}L(2=c@SVd=}U+gv7om$+l+_=1sw#al@O= zo6>nx^d$_Tq%?2p#AN&O+NnLGdF|L-c4chl!Jy{mUtGJN=*K!W(WV@d_iG#!Iajit z+fIGPwR(*?S6YL$_T;wf8~1i=ZadmEn%l0PZYyD@&jTSzZ0HeeN5|H7d2T!OBQ>|3 z&h0Ql&i+wHV>Io{ZKpPk=C%ujz8hmSyA51}|95ZGv?sTnm-`rv=C-4t+BoZm7>x_g z67sH~f906lZeMe;(4=n;vH#kwW6fCi=&mETle61O&AbK3DacVpkGz>0?yXTv1+tu&`y@C2L5|Ko-;&1uI6om-q~PP;bY zOmo`h8fTi*F2EW8HKWs*hbq}$pgHaMoNb+!n>h-a)9$>+J&6G0FY9RB(>15vff3)( z)Zn+DK04mhBbF2IVQ(-$+}x4p{ni|+40m%UeV73s{chTN?6z(s7tbzV+<(D4d)91RxU@Wnjpx6yeD=cS>GK>p!+ds>8|Jeck@+Ezi64l}4DS>}D17d><@^F=&g^zzLQWJe$xE`^fjGVc;FaI-cjVj4m5`)M}V!$R|EJ`Vpce?W&yBiM+_6OW5b+1QBV%Wb>grd)OtIiDv5TPE{36KoMb zvToyywnvoWa2CgB<19b6jH6C#I+xvluDR?Gy@oxLdAu=JDHMmdk}!nJIK0L2*?1$L zk0K=3W#2Fwd+KD~hk{fNOSxaW51Ek5ZcKC8X>M+j9WKSDqG**-rcl~u&$KC*-8;9p z7IKa%={JarbB2M<;d!TW?t}V4dx__~_z%0=ADXj?cDby1{qg zqSF%Npqj((e8T~zH4bTw&Cr$?++o$bfzp!LOq+7psVzev)^ZS>(b!DY4@6n+23uw~ zD;m<>+cNFRVK=$)3E~9zuf)~+DE)qBYmFBVIgYL%uRUwcN^DoYh zN$g)~9=qTHrjIktW5)-bTbyYgyEfrW^VsDYXPU<@z#0EFqtiJ4DmnJ4dF=R{ZJpK) zK5&=5W1_!6^Vn(ZlK=p9++WbpV!ly<7>2J|GfxRCEqOm*=rV{(nV-DJL#I|O=VGKF?CsV%!8(~sIr*4 zERIb&_0?4tRTfj1Ma`w9K1=igNwl3hIK~P6MYp^o+AeCln0mYDm}^R9QDrf8Su{ib z6MefXizrr$2Q*dKhd-nNnET6q_dHVbkJ}OquJl>*x`Z&CmaIaAkX|VBDiZWqc_-wsKJ|9I$ zuKNgfMDyB>;RMX_vjv4bEX-~76%@1u^H>Blh5yW7CM4J8GCC)G1=}n<2Mf=~^V>Ou zeEhJ0{X%j+8*e9Z;FvIBDSYPj;{$%0pFn-8p?pv_qOw@V_7n8pfITcZIsn;}rhT1cbeG=urqxOtr{)}dQ#z{UbK7(#; z^I7-gHh(z?gl4&aMcY|O)(hA{8HJxHpgj7FcZc`Rh3G5Whn46vcFYaZZ2#)Ys@I!@ zwR?Ze!Ez7?%`(>5PZWy78snBx64|r;#c_Py*uQeYTEaKDCPq)WhE@*L&xhAMNE@53zRfgfL4z4M#j-8p{i8+67tC0dK`2bd(+5AXF~7v+nYrPbPY`lv zdFI^m^PE+CX~r8K{o1kN>7}L17tbv(%`D+`b7DV$zb7Bp9}2hS4NYJ>O5`Oyj6(h-KGsKmgH?~`+sl=Zq<*x&qV;mm%d%&v4_|G46B_yf4Js#(E9GDa)EQPN! zPuelZ+My>7I%9sPX~gPc-rL>#tY99G=T9iBcR)Q}?~B{FZd)f4J8>+lxaT{m%C9_C z>;%~M1^@Y5-`b{Z@GQLNdhNiTas~Zp3aT6B+NPk4rXY|TwgEv~fP@LGYcD4A z^ZdPhKf{aPiu)94C)xtmOGvP0w*}01!DmNY@L37g?6%;joG4t9mt?mEaeQ`LKt7kY z;EhQA8np#WIG;;f@GAJ$P>6k&xVE5->wXo-h2(ziw%`U1G-wM>v@yqB?qdgwn&U1I z*CPIlymCiQ@@}1ISB|^2+sAXC6Jl{%bKDVIxy4$$a@_Sb_GMCk-^+757B$BmVOE2) z5$yAMASB8G=@At6>q;o3C!q-0zfH=ybs9V_{l}}|TR~xenI*3OxD(ec;J6Sr1G4*% z3G)?Cv@yqBpU&-AT3*x~cY&PRdaZ=LesIM6i^E%&=eRqeIqrtfH*{pwI5h9xe@R~i z+r_B=G9qFXzdhSg@`L*NcuLcr>qyS&h}Y!5bcjBN!xAfpg2AoXXNuECzR{nd-hCw zbXxEDyM2>e8)J?3TetcSSoeA{t!M-rw#+m|D$7{oeF%xn7qEkP60Al0NaW=)l8v=E zJ{xPf(P^6B?!4ME1}nsj8A4#T%UDdIw9S@r&Tr>FCgPfD2r6SD_^k$=*Fhgv_H*26 zyI(v0h;yiR8+Zo)MbFuOgM@kNCq|uf+_{fA9i_Z`a@0j^TUlR-Cc!4mi{Nc6d(t z#aY|(+x2Sa80a)oLTG-wntoO{_=_JDfMQ9^k~Z!)Xit8--tnRSPv$;0 zqxtP9qqa?xAFOG9JMCi;0j9m~XdkP6`Rz(cK4bPPyVaM)x+nXxG`}5Xz8l;90xKTU zUH7q^^V>BSoAGw!-DjNr+;-wWqDaX)WsI_w=h%!3&JtrY&bjTH#94wJ!}r>)`iyl? z)@RwzYbV&k?I_Op5J0V)pZ3h~Hy`yK#!WZppYygdt6gnQqpjw4g8%n^-?4m=H>%?~ zt3ED1k8bc8xahRRaXp&X?!5X8DDfHa8Mx-PJ22v$Q}_RXghE{ zQoly+z&w8E(hgh$-x><9!4lUFOyRmN`Rvxf*PtC3YgazI()QBLcZM4KFb8nI-RfIm z-RogEI)AUM`RwqNavLicYgazI(pF%tn0KscKD%6F%{iZ4bAHTc29Dn>B73CWr{%WL zy|34T=^X0E#0!^xC*OTe{Fr0TIqeP{aP}R&X&z+7mgHREzuYo<^SQobAN9ZWvn@m8 z4~&2PqyC@Piy`b3;9>duC{J(i|3S~wzuwN>-P*t8eI)lUgJ~X_#$oi`h)q?%z43L6 zpW`Ujqa>KJ=P$~=qnuLxfG4S$!L z{+DyEyXI^i^(zo-i_?@X#ad3WW~Nl7K0ZqQ3dEY`yJK6ETfL_F?#}D@C?de_(n#g4h>yKBy#S-X9I?&mK8 zYeAq??V0YgXIg_b6DUp2$KpN?P;*Pd54~q;-PfmqGtGGi-C*mqoaB~-PHRujyS{O6 zx8}T~?_gPT-qpcd3Hy8$A@RlAvCuBhc?Y~{&O7xT7%8V6(pld@dve}+7-QYz=Y1@i z=DefS+x@I=h=o3A;2QkDd*6Wxh9=uH&G`;IjIr*4_ke!6=={Z~pN=u_ZXIvNx+jk} z!>1`UzhsWFraAAlj}}D;#qrtwt8VaP@firo{o1jaggjgr*Xf!cs5zVsX3C>VFjYkcSlcfW;WzPqp3F(USVgt)Hx z?#y_(Xui9-{pCtCP_AtTG~b;FP`DIK+wH(a44>T&kk6$Z=<RGcPQ8!{zBEmBrL$(J`l%wu>r@ zsmr2c&MB2emBrL$(J?2J%A(3*>awUgi!{a^I%DW#5x)|5l~JZp+UC=7%vq%EqPB~v zw~MDHCK-TDnwO`tsIr*8EV|{qQCU=3OkWn=^1`Srsw}22i<&b<=kvlq0d?MXam$&a z?V`4e>9>n+IYm?!RTk5iMdR#NJ6hw>9oNy0IXARj)OIoTcF{2}h03DJV(PN!n7ct` zQDrf8S#->Apt7j4n7SB{2dGn2t6 z9Y1lL&PZ{@H#9Z)?Wd29_w>k&LdK5v2JL&;)O*Yw0jkW89>grhwVqt(om;rLu#o9I zSd=p%SubD*Uu9o-ATBqmJvTOvk2yxFQsa59IaEjRBhH20g2KA744`}k1$C>;wLOh( zm$|lA!MB3KbFlDyJik5Hb|!m z+kxlbivhPgx#VEn;l*z`Pi4D2GdEnGIk)^g-`u5{R?j~dT%lHh%yC&jp}Z)@_%y26 z*(k=s>Fnw2u`M~r7`|$!7^})DWi~H*ES#pFjIn*q|9p#n({5?uBED#sWvoTN zeIvTf)@LOGBtp_Rvipps2oG0o zGMMkf%s;k4Yy)_teje24zp-o##f6Kr)0uAXqjx9kh4B8=e!+tXp9Pn8d!OVZ2-7R1 zkFmV_2o@D%#fY3zR&!&&xazS3?!N9d)4^Nk>pu2T|69jDzVa`}Z+`IN@tc3Oc>LzC z=MUffFMGcJQU6cpk9cp}`GM)H68bz=p4#63gPxALdt#fvj6f(T%YH4kfkM*$ z7O;czC3a3!p2#b*XSe%te8tFb_gmYWL58$EDqW34ALkN$vhF zT(H>@Eb3R0}Cf3ms3nq!Xdk$vvp zK6u3df1SPK`8kh?E+Z(Kah!=hVLfG??Kxkk=rsBPq9kp+t<&Q8Y@O!nS9lT^a?xq0 zQ8^c#b`^XsI*sFd3XvO@`?Ymi<8LIR|LB;%yxIPv=jZ;Lk_#7?5flZfPRprI)BNn` zH#VqEzoC+v-@q|Hd(-`^-n{p(5E#vPn=gGT)>GEmw_u+_`&WD_ReiPL{*`0y`KEE! zpLd)gI10*g-%7B>ddj-utW|c536Lh`8XDPO^bIA?1$vbYpfwk$Z`|9h<2y0Fa~T0p zP?qr)jZMVit;Cy%ka^{`-^?pTc(^Kjw%>q!K8lcB*Y<^v;RG&zgDITI#cx2Lfs5b3 z$8`%*IV`amkgeBF;=r-+7#G4PG0;=`?Etl9LiwO$6YldsoAeczRyh;2b_`6k zow>(jptD(@3!3Hlr>n0xjrgY@VwDSN%k4J5v9EYS=YodMu$kB=`vVE%3}!FtTu{&M zSGmSxx_iF$#4|b<)PO8?jOkp^++s}Uf<}Am&5h+5bkS!z7qkXzB|JADMJUcsP(o*| zQ+@(pDu-oUpRw_nxe1*Mx-_hQf>4eqL(!I}jO{5D+RQA(0A)R$m?!KP*EuwrFA8s= zO3}G7ZuU#I=f+4|%R7|y0@f*?osM^Qz5UWIjOBYS=O^U-~*t=YsM%+gQs@|54|HYFv~60MUNxWL)%=&IJwLLo;o@TmMSu zg7QJzZGLY0S2`E8O*qrJpt;6b7$DWTpaI;PvSpmccj{cw;6dAZt%SXPaK!wJi-C6c zTu}H8bS|jcGNGJz)|NS;b3r5RO*8h4Lkx6L=YrPSGOqqBS6^{9=YpPap9|XLoNI4& z4I@2sJ?DBc>+?Z%&UNjag!CEnd|5pm*(; z>+U%VC!W#ypwZ|HU0)KY#3LJ zJ$BGJ|Lq$_QLp=6PVtRjeC8jwjNW{%?`K>5Y>={!)K2TJTw*3-#zb3(rfDqzMk^%$tm z0}Y?UE2LL;-H0yoW!;JN&YOI2U>lI>0?djf%0kR7Hc{WGyq#OIAh-< z(T>r1puuytah8vH3g|!TJka3%^ItPqa~eaZ-vq6TwcPX{bsngWoeohJkTm2 z159oXbTQjWHyb9~^U$PE!<&@#0@itdIuDdjdm=sXYfRlXR{TQ?8% zFDr9EIRmtDezxuS@hF2`(=*fOE_yw?d9o+Ie9YTCxaHUv~cxl)%*~T0D@j`KU8xw|bDNpo| zuuXeFa2dx}1dsfNry!rtm5}7RcN_C8<2){Q%#Xn5V#n-3W&N;jTu9w*JBIU8Lc(|U!sY4nOJh3kQyvVKsoOC+?=yJX zcDwIt%akCz#6nUYvoqjvY4=|OpG&*XcuXOvx%np;vfKS6|CP@BtUko_v8MAr`LuJ3 zHJ$evfUOyvvG0*+$LPGz;5pkkbB%wxj^#OxtGMX2tKf6dX*(TtTH{>P=s)Vb&*1&@ zUo%*9@`LNV&)`|xSj$cSQRjW?Sn05}p$!uCSkl)ug~E1(C3U}ne*Y6sxw$sqt$(HS zKKY#OHa|E0E1mbr*WXm%$_-~a?~~6tw>Z;zpM3olYQ~mv8po;gK7(g%GZys-x4^(We~ei>NHBET%4tj&mwh7F8Bg zmqnd(pyPBhGET?!TT|LDYP*ppZ~#5u3wZ;d0rlGpG)Z_pd~@$p-KF?#1Wzq`XS@YYt`{~b_|*Zbo3t=qgE z;q%~P2xWBpz;}Cp*wg0xhJBG*a6VoCy8L0)Y<7mN&)a12ZwcxyJ9!^}ARAb6`%5T% zJY27zHzY{rc=p1jGe3#s3x?&wpdtq$FFsu&{vNa}M($CZljJ(I66v^BMMH z=T0seKp9^AR-6m}^32?D%@8E+EYF-Q7vS%_^c>2oN|gc$2m6qJ^8r)P`E8`Xbjs?A}{G-6!ItWu|Dz} ztOj`%_i`m9sb3M>(fYj{sUP3I)Nd5)xaNHLb8ikSE^~@r0pE2LUW4`K`FQ`_mV3ae z#~dU78COD*y4!P#Uc-S&VZu`QjNqIYpD>}Vw&4ATiuYFGJxJ80c&`e!$hG3VG2UJ0 zC$vJp|4)kdR^fe7^?McTTvNQ8=aHn}UFU$b0`LE;;{9&%K4s4LzT?;FLt&dF2TQu@N3wk=)fNQ%}2#I3;ncdz561Kmj|+C*#a*KC#{Y2t3g-^>KXs{zh~RJo#M4z?Z={ zg~Ix>#EpT!fn(cHgrt79EWQVZdVNwE1MfOVx)r)deMx3c2H#cFz9fuPP~9WauePN; ziKH>HryS>@w*v3#OKKtBF;YSCE>f;|mnV^kcgMN@t-!nblI|YwwYH_=U1Xd~>EGVV z;}Glh)9wCzBHlHhg4&iLaEKYPZ@H_zw&j?6K7}XtJLgl_VQ$FEr{L}GeYToU0Ty(r zQBH*&cotdBsX)7s#gMdmW~*L~g-;7Bmi(P>ZPVw#v+$nlja}GNu4GmyN7F2ntuzZ| zlV-v6K`|je$g_ZdJa6xo?B-cu{e+=4&F8(j9dQ-UW zSGW?A)ZNxeYdA0|Ojrt^@iC3L=UHfZJMg#K4&Z(8-L|eB2+}WTJ5Wd7wH;{O4mjsu zXni{{s{Mghw*x_125kql9jKY7ozx$2&dbpHcHpqK1I@Mr>pfNF3qiUDZ3na+*l;_b z`5JUijo6A@cG6enoUftfI!S$1Y&u(PqfYajLA(@B4fR!3eKKmJCfKO1c^q2a4ydoH z_3c2A-a*>|KG={%-)cM1xE*lL@6h^oKz&t^)#myGH8!gD2c!Yec3@qME6G=-c^}k9 z6`jdtCv8;cybmqcN%I;<4Rz8mmXw2ykEgKGL6k2r9fbBx@hpV|XZLd7^iSkwv6TDW z=y(d}d=M>f2X1LQfcM6}X)D_Sj;K&yRTUV53vCA)+o-PJAV1Xlc0g^^6xsofsL*ym z+kp-D2VC<9hgt%cJx}(0Ta6rYr z$M@|oKJi5HiK6d6UfhRyKKrre`}>N;g9i@ye(U?D>Z_s%wA@CWR-F_=D_E$FYMw?? z{KPrmMC<#e>Z?kj9pH!xwNa}rfwlvV?SN|@iq^LS>Z@wL9jLWYwH>H70$9^_z_A_B z{1j@VhR7jiI%1|D)}h}F{{3``kmFMZm&J|x!%J!KlPyZaPNOO^3QkX=Z_q}>G{2@eeZdD|M~r) z@%bY?kM+Jg@gF^J{)o5t*Xp&4XKx zeWLeM{X2Soujey;J9{4J`E1YUdv{lBEN7^;S=`g_eR!vOgn0ng|Dtc*o8s}lb@?aP zpN+>Qn}IoNA9{_nNqJV*yGv}6{XC{J6Gv07(^N8|3gye1u*ui_0JPLEd5H97Z+Id9d z_=@5Au-09`X&KFrNeJHjhO>FX6vS&WJa`w}QfR zu<(35znwGUD6YE)`-S9w?U=?D95^OSSPEa|^-oR))5Vjq8Mu>x&SY%cHunw1B{>NMQc@LFV-}%g6 z-M@M8uRrt##&7mqc>3n%-s3k1=I$RndUH!(&zBZI^fqsP|E+(xb>Hz@cZ$I2==_nd z-R$duW_^BmeBeFr%m2-XUf=)wesTQJIJu}}2i{)&@XnuXdY9Xt4@BcPhVP&L=4Oq~ z9mDe#dI2j>ZQu31E#Ke#7n}Y~|JA;K+xvr_|6=ghfBCCl{<~k?*zP@j-=9`DM(;aP z-59&CTiXQQvrC&$&Ul-^`w$Xr7O(^2UTG6v7lv@jV>_E-vX9dGopqo=kIYo>Li%DHQsQS%?A3y4`QQfqmOhgyej7zwtdV z)XS3@={E+E$0S)C+2<~cuUN8ZY`Xa)TTz#|ejx9&)AAa9p4A?|o37Ghgkqh~C+=gan@J{U(gjaehi~M*SvgpVjI= z+Gj4fbg|Ev!XOEkhc?g`doIB~qjfg(!PB4EK6w1*C+1+E{Z~hC?tJ7~*lI^_ZZcL{ ze|;;>e+ZUZ8Ftzu%dpe_pZERoFE+N*0=^_W?FwYS#!mZJRcq|&`;J#P?h!kU_w1sx z%NcJQcppNdI}6wWcvN)u8^RDSd5mP+X>okE&L$uAtdLyS*4ejkAs3y!6?`r_n|%Nm zolU=`OWQyfeS*#oqHjrUgW74+-tf7_#a71)M83Eb8>xVGyxxjzM|C6lc#LGrb{rpN z7Jb|K;79mJJ{MUmgKr8YZ9DDJ$M+vHu{85PNft-Ua8W1!{;TF;ReT1zz)7%*h&FSgiBeN zS6^#)#qkyKL-`HQK|Y@=A<1>^ekJ|v?Dr*&2bl$rOTY4E@U5T>goW4T`R#t?UR-w% z_6tef?SADM9H`r`JQz&ot3WTwj#Hn4`V``1@dku&n+PJ7ak3Z}`+fA_KJ_W!xwUeP zE_Iqy+m9e{mfL>bhY;nDR6wDON!wq-dXz-|Y@b^x%7k^{v)g|1`6xniUAyh?TA#wf z$JD2Qm)jA%A-Jn}t74BBE1~!(LiZlt9^aTxq3QW5-rnu+AN#2Pt>YhG`IqB2KX~!@ z&7`Sp+be+sL|_X_oFpPlj&u>2Cr)7$%h&~x~kfgI9$#_&|PqO z73XomY^|CUx%OhLUQuHit$;#Bw_(Hqvi&oV)05w_P)x({*-R z>Gl>s$wuQi;BK|iSa+9pKkM@sX|D)L`&+;czEbhmMd!kj*Szjpe_b4(-4`UE&l80t z*R^f55-#M@7d(UWxby|-*K_F$?!t8+l*(Z#_iNi|&*4Cljpi~>s@ZwM-fH7H*pP!T7O*hxSzlv0^1@9P7w__q=AWnaZrQy}VU#@9S@`-Tvi}muQ1=&_uWP z4Ow@W_CM=$5-D>+(he7}gRfTlhGW7IE=30IzF{0+F+87~hJ3zkU@6zN`-b$3vwlf& zvNCvF+W#McZv};RCkwC3^V^u)gX`|Wej&ME8*`^|;FvIBDSVGUQEcmYU1Cn>05jq7 z?1IiotnF`=Ae%mlP#oU6cD(Kr``bERw}Q9+#=eiOc;MZt-&l7i{ibsgYvRo%JUbsn z=-$KIfsKvV-QV1t#9$m&bxtBs*LeKZy+0=rdQRsg*5Gaefb;)<_TD}?uIsuJeE1*< zfglOnN<_sfZ8r%!h((dzKsV5sk;e@Z1gVHJC`&crY?Ki|H6?JCvOoe%CmzdSMM0Xy7s_~%d3niO3$qxd;BWWBUFNrRk6a;@Q zd}i`y7@oQsHE5NhS1AEYJU*P`ac}+bqi4(Q-K!Eq`<~ki* z1>QU0^WJ;T#4o??&1l+#XJ}>KOZr@<%6rv%ZxwmZuI@0#Tsaxf#jn(RY0R3~_08M< zX~&=6aC%0UwqX8^w&465UCXm1_Kb6$#7&$danB6q-uQc&d!x&kBeAPIN1}^YYwiu! z3aMHyk9omIXAqcV_Tb7@A6q~^lsAY3;7%ZqW{u3 zKwTsL7xh&TL=TyIHw@3zyTm&hxS+Ia>fI}7$VTt}1lO|ByR09v(Yr4L&qnXQ4ZH}w ztM!FiU+7XgNM&96qJlPHMZR@5mCC!rxO$UpWHXte9MW40t6>9*|D`tI)Es7?e{^p4 zbkge$)ds9>1MUv!De^Gk1NdK+^CgDyUY+xjI=8Nzb4NYftZ@$ByN$gyJEir8roC0b zyGvma2(!1EzTWUbqu#JVeD=m|%4bQh-4hxo&C7Ng+mzwr*N`uQz;guCuL;9zVLq#@ z-3#F}?N`!%CGsA9_|@)L+E>We&i4$V#d_xw^egv{vT|>wcs9>9tBu8bx3RI3Ubn~R z5D1g~MM3b_VX{9A&y@YdOJNa^cK6^wurH~3^L>WFS<6tam2D`${Z&T!ZC2~{z(cLa zZ-v_VtPSM1B1BkJ{ZKc)MYHNR-n*54)4ILZkl0GYL8?+my7Q zo0aEy?^ZmQ@R~h7hk)32X&j*4DDi|bLGagMHf0!|spE*33S3j#HEqhK9SdS)pmv^W z2+wIeLE{PJ0rKLi#}h_!YadVe6}7k6H+oj*5o|$wYY0+)8P+78@Db%Vm)~ZST@$47 zyK4QGf-%__um#1oG;+~p( z1xTNSG!}k#(G8Q>4ua69sT(GPNZ1yp`Mz>i6<-BW(7 zw$)aVA1mkb4C6-@PPj1HeeU3q@wPUR0F-I{SeD^6Z^zJ&-Q$(q*f!X8aq)&T@&32b zOH_>Nlih{OH>+Ocy+`{@rNqzO8I=E`pVD|Xes0l=$FLm)p$k(lhT)ldk$9=V1*Kh6 zFFuThZ1mz&xR#AxdNAlCNb9Emei_HM zVG#(UMGK#)a-O~rT5Oolq&AxK$Rm$`_H5Z`E+xLUPHnVmek_6kcMCIO9mbCqK9gN- zUEMYsVi<QW#za|C9gl62z;ee|aoem$9DxN;do#)~{4HgT{>c^g{SgeI)gf z$b00))%KD0Wi#2l9|_|sI;Y1zZdP+Xy?*p3b-aA>jd#C!l$kxIF5tcZpSM}OS1 zAr6-=EM^YfG>+Ny2R#qG1^*hn4zI`SoAzZt+U>(}0l9aR@7P}z!goW#B-Tj2%h~hY zCGTd8ep%X=o3A-L8FjdKG&swIX=?`K4$PlC#JIzO=8ikq<+Fkp6JEQwUiqx#I|1?p z!Q{nB(47r0K8^p{@Z!tBv*AUK^<~40GvT~g2qv^f@uJ2ZH0}_l7cPTlw_y?RL~->v zi(!4U`?4^|%GTK0#T~w7QNPE)bF;=Bc<)wmhlJPfQN9X@98Ti^=}c^~F+uRxLW8C) z7KWGcuP2uwUP^YbmUd0~-@I{$?7(`&9lm8z!`Bi#H=FDlBIUVi|EK=ALpB#H?hs>6 ziMKp~SHu75zIJIxacQ*O>v?4bpYI2S*7F5@p?=7|d+7@uY;IqO&tatt6F%P_pF==& zQW^*N`9&8#EC~MEBaP~~L>Qi_3yEjr3o*xlaw94(@hos`e4$r?w}7R~U--Pdz8ROG z4(`Ko0eN0CF7Y%@)Q(GJ^Ks%5>Ie`eR zl@`~47OiT!lopj1*MJr)=LUpxS8GltrA4L1HK0YSx+bMXrNuR%MXQ<~rA4L1HK0YS zx)!BHrNuR%MV)s^=aY5A)QnMk(|~(X>k?LzST_4hqi7Mi7Q>qNbNBI+b9*0klomm4 zUf@$+-D&+q@m z_q^FLdhjyB#+OXtT(j00^4_CsE2gJTpHBApl6(#U`qP9o7Jh1}t$2tB1K^QCb!|l$ zo>^N#yj0+N(ym!&cnl5M)K<*lS~j&6F9Oe|wjzgicL(lIp4Y6cn8t}(wG{y#w8|ka z4B3w2LqrLqESc13p~p*!|JPj;qdHKfksUqfWME+OPOC zWZd=3@4xrMmFLMA!t*yPZ}Q%4coV}QC3+mBLVyN^N76V(5)j@z6~N)9M;_I@8HQ)_ zCh=0dkPp(X$(u81$c8tc!*y(U^EKev@FvHBvEj{m;6?DJRZexiyy+}{?Y55Y1553X zI(N1I?UU}z7!ym*WapK(!7W$(nKJrcz382B`d_-}9qYmS2-BOSi)Q6b-n$KNVyGnL zO}s0RaT!{OH?4BaM+)|O^RQ=(SLn^Ve|&wb^D$@fjoaSZvAO%ZH=M5VrMAZoE^Tg~ zSn4{pqx;CxmX5Yh%-(P|Z@%{WkFIaU{BIfX>FCU%&n$Jcfr}sCJKlBGx%>Ap;?hsA zWyVLwi3LsT&V+OGQ=6`E-${X^@gEQGz3(sm(B$p0@)vfTr?9<$`yJ=EJhS-=o4(lj zY{wt9f2r+XcE9---}>gCf8+9Y=it^)FYkM9Ty|hk)qK zG!Br5MPI)x2>x35+Z?ka4A0cp#5)$arnI{U$AV);{|F7)=<814+30K9$Ts@=GVpBl z_4~k!(APSjj^=K;lnzo^mpsCNUuTu;U#N2|i{iVN2A#W{#em(Is>g23;k`Ahj^Mr9 z=!n^=fkf*FK8JwF>NF0JrbS0g3xdDqIfAJp!thKTLA(?%;DfYl>WF3?%Ob#+R&@^} zBldFxAC0gZX*HgB=in{dyC;@zIR(4%e>k$VbI*OSA&)F=@~p?s+SX(0W3V7gupjrF zh5h(nucgL+V`cl%#f!2Z=kblJ?8kq#Y$YDtI zu4yMegob*76E)`93~+38!3)4!z!Ej)SqAO)0Z%}l*VF|ioT#M>z<>ETxs>(tANs}@ zox3()``RsSSC6%m_sD}D2ln70!s7e<_RY$Fymu@9OZXfl%74}RZx#4&I8Od(VbI=B zd&Lt574dyf|9u_YSKKVz7d7YB&L-wP-n$j=C43$dK8JwlpfnEf6HAQbh#>fD@AFs3 zNW$O$VT6+b3? zE)qV6fbc~c2S93New-8pf6a3Q(-xg{k1qcRp2?5IOD&^?@*{0M8-AR}wQTtD72w(M zV-fAz@Z%itYV%_*n~gF5gT^H^E2H#iaXSqkI%Tn_G_GbWXCV(|J%gUJ5Nt69eH$O>AuMWOV>UWoRP6Q4j=S=KLK7n z$azSPH1|9td=4vJnDBW>sDA`RC#7)!V!ok%P_1@(ET{`-a1%DV@Hza?Mi;&YJR4nj z1nt`B!g=6@=)yvrxPIaecNb9TZ2bJ@P9<;5Uw9h|(jY7iogZd|yQoB2^oxAI$ zi|2N;M(ZOt{@sptzjBiM)%u~wy^Qy>3#(@Jk9hCVI$<{P^^-x_7p4=A1-=obR zCpj`?J;ujF?e1Hvh}WY|a)>Fv)=EdBNGcJ}-~H=ORVrCY`(mbwp2EZu%^ z*MYkZxRsJ^Zm#=|s!GX&_pnlOA2Z#5Dw*y(j7rHJhnx%uwpy|JzMf3xatKD&+XPI}Gc(|8U6 z;nOq@fb`3{`xQa(*E~lsb$1w^DIbV8$qV=(?V7s#XK1JwI8przy}+~4-9_Ln;CfO0 z3s-<=BOf}!s}b@+YbLd3(xq~c)cV#;J~(PMS63mo8Znhk*XYMRzyGC+Zd3){T)Xeh zalZ%eBFvxb!?|YF3A}e3oiLs7Iw(GefXL=F4v>aB{1aiZ5>qFH;h8$28Dc8I_riBU zFmvB6Vk&D`Bl-2){$__%NZ#3l3dtj=kh~8Sl1C~kBt5IKYJ82#5nk>oSm$Of&EtoA1_;N1n~h{z<B=Il%SS zCcBl%ue>+^sZHMr)dEGnpOAl-mP?>)<#zG z-VwaJ6c&Ln-aBf^d#7+A8{S*H+Q@u9R(^1d@uPl%cLJ!eIcF|xzO(n*d$;|=*8NKd z_rJ6CBL_OJp6*0t@@qaXz9!X?Gq2UEkIcB2^nSQKy1nOo$209;XgkvFjuAS#^?mi7;K-rDvnZMSvoY`eYf*V^uE-{svh zkOB}q*6G~188`)-D|nVRSkQCeen-W)DW0Xae1(p(H202mz{}{xCa=opv*O!?*H8w( zneb2Ae@3xcOV|&Byj3%%8HUF;0=ykI)X+LFq#tn8dOMaf^|x1TC{3-b1tM0p7cn9!PjSC7(k;gW9Oxrl;PH0wM6m z>Nx>v*VKKJXs8!RQ9cm!6>WT=mw~r{CCUe4A8#M<1mt;5A7}kDk8aAd6_8 zv-Py0nsS%t5#7u_d41mb5Bs|=F6@8rJKl_x)jFdm@GKj@W~7w(n#w}pdx*SF;~42t z^u(zE4mX8XO&=)?FBA9=|4+OWH++zG_h3I5E2A8?(G$<%e>QsJHQ?Fk3HB@R_V0}= zd0tab%;Q8YJrUqdyPC=&dz4p8L-|6Ui^=!;s`!p&1IfMNm2)&y88HSg^ zpXEQi4)Idl@Il%&`Ew3`>IF`e9k&1+8~(fmJmN;#ag3eV@aK8pMewIxy=C5hY~0Ie z6HvjQPCvM^*6anoQYq28!^S=%K7qq|INye zymuRZOnQwapF=?SB8>z5?81+eg5a+`lBo8p!tgTqpZtfHAYKZKfV6A!V+nt<;m3Jg z$c7(Z0iF#%7SXN^KT=*q@S|OgW!}EVa*x+RQNfR>vFvjC{_?ibrOx&-nK{VIi|?we zrra|Aan@4qnF0U)z05kx9-)2*NMjUxpcY0x!kTWrJ`m)e(qc#dG|iZHwkaOFSzAMsM$ z@Il%&b;Wx6Y<+TbSj)YeF%=u1&5l3qYn!ilH&bCFR>xG}y%o)viZ}Z>$FK6dH;s2D zeNI@7cUJdBFy3jyoAbbnvg2%cQ~SlVUyS;x7t3n*i|xw}4aLb*E!3GW;l=iPu6=FW z{-x1fi|@^!n^^k6gI>?rO}}T1vq1LXS;OM&{W#aG{yp#A#%4=;og<$^Ky0Tp4$w3Z zo9$si@Yg&?Fm1LlJkw?)UWym+LE1HKwn;QZUWxMWp9YSNfB!P@7O-^rOBgS%LcT;H z8z)b7I_Hz+2CJCtUsYF*gJMSHB`;D%PPCw^uXme|lWu}IxJj0LUqW5v0hJ(#L zPXnLBiZ2shBe`CB(}pikfd+f=o}={Uv%s;@o38?I0ZWwLJdAexfF~d_#f)`4jT5!} zseReuY^$5nIhc=O(`u|kV;!^`sfSiS)-jxq73)}S|H_Sdxc=3H z>R+9F>O{$}5AK_D9(m;P&z>!JDwZ(LOtNdY==%tWpOeM`+Aiu}d2c4njtlFvg02`| zr})S9o4J+ZAGPZ#gYl2Oc;t-`|KM}j`B}=JlmSBHr1%mR8$YXg;~&F?Sn-cl=_}ZL z&DqJg$GxKx^QblMOpq7vz;`&rn8$(Uj(PAotawptE33wZI%>&_lVD)lno%*2Q|{>)hNHJY_>mSS6ivHsI<5Sv}jdJsI;iGxCXRnRX3-!sI<5Sv}jc`rnIQE zxCXSSbxc~v1n=96qj{yL?(Uk+=@IZqSc&yDi@U&8%2xzvV{T7A=0tb#ZHvq0~M}f&t#d{~@uy70o0s75^G#27Xz2QAP7y$2c zSC8ishG*6@5ib?Ep0sO@=TbyNHZ>Fv<61W3Mmz_+1uRkHM%;mR`vUhT&ufkwaTF(N zjvFzM$;9!^>gKh@OKr+);I)L0ous^0U3D+oZe(UQ76RNXlys;k8^G z-?~umoWr{=Eq;BIH~LWz^l{j@ojlj9b|mlJ%8pF<7)N{#0kP-OI6&J;?8u@Z_-nDN z%y9w3@Ju_BcquFb((WD{2+m(OhK6kH$VvRq#*U;7X=6vG(5{Ug`4I3z?8v;v4>W!N za&!4e*6R{K7|0B3{2=(|Dc3qG=8j$dO8inhFA_=iH@k8O?C$#DR&qb#;}xl$)et*t zMB@kRz-zO~9(zc6tr5JI&8}tq;A@LlHq{zuC}=VYY87)NO`Rxyfzpo zexSLWn#)NGn!fw0kJ&nq&BgJp>y2eyT6EeqZj89`+3C{*_@3G)TIns?_KDiYvKrAR z`f+?W0s626vrjZUmX$4!ddy+Fv-vC|3KR+~p6iKn zrCDt(-n*5Jb#^xKycUd*$aWgfNBWYuad7;694^Pg%(!tFUMBD#{-1a$ZulVWnsMVI zZi2ceY7EC?z_E!NKMOpYxbaT3Yr|_tfmb_joQ;?3GhjbQC+C_5ROI?NyE-;|y)-N5 z`*h=v&B}AUcRQXdC7$PkzNXNA8qdd1D?C@kb`ZSJUY+w(3?gA$@JyZ~UJ8qVv}^Jl z=WMazxk+5ehUds{HawR?yEZ&`40yG9ZXhEWb2j=-eH-;{$OEMH)%R@%VvTE1udQ`y zQEe^wHB@cBj6L`ZkU8Z3f+Fv5;e=y;Xl5TT1(F&}pM}Y*ljs+4k8KA%AUR zT8-$l>GRwf_ZPR}g1v7un2ps(S~stKT5Cq8w2rM6 zc`Y9+zq-ztowI9x@#`I0$A-Aw^l7bQtKzpJtg@7AnR!1Fn>YJLZDV$mxXfzzjoR3e z;W4|x;W#b_1NCRrpJ|*wlZ%-Tlkr`j$?kIpkBqmq zEnB2*PJe}c`l5HLBG>=YyIZtBlyNMiplKbOQx(gy^=WKlS&iruwaN1jk7eaz<-*jP zTkUkVd~P*(P3zbgFEH(_jbF#+Rfbx}>gvt)+||*kb!={aHF!?z*lO`y5eHK|;X_zo zP4m{V<;%UDP;Db1Ze6JpXXtCZ8{ev1K9q>-BBswQiKY%@lbx$>ZUOjl=tt?KHM2Q)IjVtsCXr ziBmV4k2jufy}r%v_D-#1EBiKy=Q*uotJZHR2pk*z7GB4eAJH*7bUby+Y3eQl*TD>p z680yt&{pQsINxR{*8IKo+FF>8ZBq075lGfLwyHR?ZJ$jM%tBu>YCNGT>;@; z`#QFvSo0It&ugD9DzAapw2rM6c`erb%Z03rED#;D`-;c-75NCou9oi~olSZTo5Tz# zzhyg(ZGO)6jvw5Eo3PPojTqz8MyDOY{nZ|Ca46Q?()H@J_VFuQ9*E#I#$=myd{5rH zMQnUF>Gf+#j*B<3{TORJUF{RqK2hp9>Xp?W+jDqr=a$yE0mmDJFQa+>8PGFrHi3;F zHyDmNw{)GpOpp39Nv~ZK|Ajmt+i7f*FVvUeTUnM7W_&K(ml!~CAlBewuWI6Jdv#NIEHmz>5}$?24yw%*ZTB>4#&)csk?qn`$6f?X#E<= z{{#2W*vkG!^o7<}zcw5z2d3_M58vIPeW5PD>AZ)n$!~>tc|LXKd3KCDyR?SQ&GUqg z(;Bu~JXgfQ6i@gdaSU_3!RD=DD-6b&lSlh&w7;ft{WXProUt$Kx3{*af8*I(QxtDW zuB%CMU;TReH#Rx`;Wcc9Vd;gjsb8))FUHY68`xP|!$w(S_K!Bh_#8I8b`-(E+Bs;2 zH62SgYP><}@Mg_F*KYNtVF(T z^qTrK>eG<-8k2)IG7xKAjymUsdP8&2n1fc*+O=vMYvbpjjpWvHT<165)!H?e*R*!6 z%AaWgUK@%tu5-P$YlkE1X{f(9xIa_U+O=w(W*awX-rBX1Ladm0o%W+-doq{sCZNq} ze|me*HYb={*aEd{C9Pen=Cuv4(*`rK=F8T&fyNCQ7B|4u?HV@-X4x_x+VHv8N?Nmie?0-oIu`n*Qd3&Qb`S*5%sD6mDHTAJcFo*Q+x(tMTq{wvYl9h` zOImB!TnZN+;5ukkm#{yHrQu_E4rb!zztlND!5i;tZl~KfqqS?G?ho$M*vkII)vgU@ zW97iqn@jzM)~tt$7xwoi0D^E++ovO{yJ z2eY|2bMI(BjrP;fw{J*(=U{dyR?eCFHHgzlq{Wk8A7I`!$bOx7jc?D4Y1#JCucu#Q zliMF!vo@G5#F>|--kP;8?W>`kHAPy}I-2G2`uIMY!OpVbwQxIYAl~@7b?P=}ch~ss z5q?cesP0&YvRJua-4e(Eezh6I6T_S+9@plF#T^=Squ0gR)*HT8uSj znflS{M>o!o&JSvhpvpy&hq7KLxtNcWr&I4(442;hv~#ZirHkiME7yo~%%x@>Gn@Br zF$d7})alcSu3OS^ud3@PQgH10$gn=p&m(*Yi;VHb{qQ=9{BW$X=?5jU5IvsbE8fj) z%JBxAey7{H#hG6`(A|FJ(9dtq%pAJZ*53Jti|>DTXG9&-PW-!Bd5`yQ#d`^#7lO|r zKs$tx#==i5basRX10b|$jyV^GXV&KuFBQ0+w7Un#ZoyLY&mBcWtXJQHg*aSTbM;9q zxVIUsTsVban=$9U0=xw*yapFukJo3L@~qf&_MqK9ZulV2Yx3SCPSl*|ZZJO*r*5RM zD!ljPb*Bj4+jRJ%x8+>y!TpDgU;nE(*Q~t9d$;1f*<|ZI<-JDm-cUA9TylB#*J!=> zJx>r+=sjn5=EC{KS)_^CG*?>gW9Oxt+(H!g2?4sJcfRkQLapT~+vOUdR@>LdZ`3ql$TNkMeRB({U# zkxBKKtdl_`Yztl{uuYUnES_z}z2&i&P5t;3E_0B5WIbZLu)!;9^(?VbOCKO0ggl4 zta6|CZYB3IbWxJWQc3dI4n+{Jjofdbe5o{Vx7ZJWK|F?5A(HothO zO?eH2gv~0iWgwSC=2OnvjuFeFk(I%l5dh*GVTbqsaQ`t-97$I3q`lr!z4ZLF7S+E_RH`!C)^FKcytE9ld7 z<9#%%?B~5($$rc;0n|kMHNkH}pPG=y!cQyltRl99;C=S$cvdlpgl)kyZ7t%Zun0)I zW<2XKE@0!=OyWW|@vH^laiPxR!ghImv%e>Wc5TM2I|jVke$8;KJe$IRWaUKj+{|ibJntXQz4e|b>;>ac7*zg_W%?ntf_^uD_+VI`OzzgBKm^nqO!grgM z@7($Hrl-!LgB75Bx2*g4K3ah9h9xqGGNi~lq{5Ir-+dRn4ye#~ULWf&w~w{sYI^g| zarUQ@3*G+KY%Lv_axdfk?83_LTRrUdt&VOz(9C_Sd>%W!h|X0&lKHcbH|T@tr!@9S z2BH^_34*`&NTgaXhT)ldk$AblHKkosFV3MM8@>1(u4SVaUjv?vUZg&@(TnGS7orzO z;^h8m|El({k_SlZrf+l^$F^Y+5Z?O`4hVnp+*K^K`&SED3`bjrsG8M!^S9Wq%>oxPSHX+vgX1H-AX`ec%g~l;0p(`-|P@(D%a%yO!_!nbjJ*YS~|e zK1g8^2=lXTW&b2DWaDSk$F}jaQ?Q}>H_O9iee?V5aN+t)gcYuWJK^T4yw zb^Uli8@>zgYaJPg6H~6g&u4!RYw9u=Dy!<==%}o!GkG!i4f^qJ4th0p`!_;O9iPXF zKNDV4$LA0bK1t&Mc~JQCVL|ZMJV!A3GYrqRH;s1!2;)V~>t||YU*e{ATCu1QiQS0a&)US9i zvLYv^*tK%458rRI`a!&RD?2OUb#+4HBzf6RW1F8-_^iN_0q{O`HJ^pynS4gPRN#8j zuE}TjpdreEC_C#IaBS?XXMwkXrORK~F0XIqGwejWeK;;4&uhjX=%?K;NLUNrzQK`L z^Gz1Ak|`I>XD@h-RPb5*_?3hT*R-zg1NW^KL02}sMjy$B*Pa8O z4X@pSc5Qf#zE4eF%Vl&vP4#I&ZOihPB63}Pnp`GkUX5hEMa%t{_)uofbGO#jmHip5 zt8)n?gI|wS++C-LRm$6Rf5U7oTc2hUSFw@*l>IjHKZTpM$zu-f>%o*{;-xUDAv&L- zKAxLE|Efe0dhm>4eLOtZto9b~-OAoNoBWzOK8t|Rei{eJBjVo_1;JnQ9Knnu6y2lC zKZ4hSJQp*Es6L+S=s_iGr&m#@JeT}>I_0_Qn8GUPxsf>Y*VNy)+V1zQc3$lq-#MP{ zj9*XZ_p2Ukp?bPmef$wb>z_E` z>>d5g{d=e8=FXfves=D}EUsn^9|b1$6zf?C?B5Lf+hID9F|{Cwt}}IF7@nyUiMN`4 ztIy$jHg@Q1z_YPK>#nEEWixT|{4~c~bG*rWy;#in^JN^{hDAVl&x}7`1;Raogtg%9 z%Vo=>huHZ<_2s|OCvvoJb!s^lF`f82AJUybm<|{d1b;2`W$J)1JW~e{FBQ0^w7Un# z$OA?HoNfMF3HUZT;LE_X(E)vUK$|+B(EPVtHr_bF17gud$NygRUcS-q)7$wW?f0S0 zm3V$*AC`d7eHsV&StSk;l;yD;~ymZ1|0~nGL_O z@5hGULTf8>*&*pUwb65GbE(Zm9_Yo=0Gq22EBCn^wT_nkmpwsHA^VHl@7rEndgH^+ zU0oOFKYZ*uGn*5 z4>)t+f8O79@yq)Q7k7=n{-aD+Z;g5G?g-pBpLPHCp7R~gw127X({FOiD-6HuWOo!!6Lh5Ec6TBe(?u>Y2` z-gy@4n_IrN<-pR>4(AiIH=MTX*Lufq54Bx`dU6PjjMH{K)D7cxbn6lR@&iqsm^yya zY1_q{7{2>{XLI+K`)_IgaObUUztVPF$IiCf+kUO>&h}m2Z2~C(!DF4yjhlf}ptayx z(jGf=mZ1Yjwk_{s%fuHd@{l^v6GPe|7N5n6R})^VSMVOq{gtOpV~@`$yh>gOg1jY@ zSHtj3UL_un2}rvng&?oaqanWUC_PCYwBgmafVY4p%6?^x(1uqRfEU86vBoXd*oMY7 z$OEMH)sJlq#G5C4^?WHm%AvlL^VrF!PDq}2-<?5<%=Tu61Jzr23imXn9 zRw4e%I^r0%gTQkHQ%8j1Q6I>E_&?(Dn1Hlv>WC)xrQ*#YzAAhP8*WTv9HeI}+if=4 zb+*cv)%vpj7{_3|`Niw3|MOxTEnojvn$r5e7Oejp)Oo_iE{v6Ay1F@~Vqc+%?!Mn>$M)3X)*z-{|Ab`cr7Xo5PzKG3Rw@JJd5NCFb$4vR~e z`YjC4u>j`hgvj~Lo-eE!T*W^or$$MdVChrk1#S8c#?V5V=s3q@B<2p8a@p<6c=*51t zYr}h!z^l!Bxr}H!o7~yLuvFPc+p6C~n}7%Wl{5~J6huEhEC~MEBa><# z4Z|~elz6$oHKkpXM`;_{=tuIM4Ub*|o(+#uHrVj!v%m}C(SbNQjM@jReZb@a()#N6 z0q1g}0j%`J>iJQAltcX}3qLCHbx?hvO#zYDX&itEEbECd|H!oE!tgTw^`xC<@S|+% zpytE%M7*(-SBE#R-^^)@gY;}?!zF*NP36sMy?GcsS0`_lvuJJfrrL07!%;6b$c7t< zlmD%>sI=HPTFhtT%+aN^sI=HXS{#g1yREdSwAese%xlc=?&Bxt_C6YK&^*m&TK$+` zKGry|Di>8QHc&3cnnzh_QE9Ppv^W%Neqp6WrNsu)VyroLl@^s28%T>fzpU0`xZSSo z&n0jz^&s3YVVT6z_*#siSbd@@7ga7cP%dg8pvpx^Jx?CWdY$B=_5ms_CWID;voiC5 z=0?PsAVy=|s~_tg9@PG5?ROE~EbH~r(Zl7+aFvTH7uT562bMn5;oQ~!w-eXTIWvbQmM--c z7u&Bo{Xf4pbEs{w{mPT>ai{;6->)?X2y1Hv2C&hrwe7t3=$ebuCr_VF_B@=mYFE>E zHpa}QW|np1L6Eq*Sql}0XVyXyFBP~T`Ga8A%&zB{n7h4Oa)0G{ZRZyV@a17Uz7&lT zUDsY~yqDC^ZXVbT&iwqM@FwN}nQ?hD<5ckG;eWu;RflYNljDLnD{tD3X@2@7XO8E% z4oRIOw-BH~;gK|sksgINPX%zeDYR(pX#~7GfoPeI|^>zd-{gc@psoeY;W(U-+%juCO-#dJHPAx?Y-wa zpXvAlX5RX(?l=G39a3iN5r1oJ>v;JXaGO;x^Eqv7W{xzIWZvg<2nY|RaR4f(te0O9 z1b@wQ1XC}+;2vH65j;~b6Yt0}nmc|dclTgnKSU7=f%ai9)?2Xf-ndYwei938h8e6} z_z8Y(^fKp1wb9Ej1J6b;zYV+yz5I|3?`vE|<0_oO;6MB$@lxFILE7De{h*%M2>#nz@aETUJJ54r>1%`JOV3L~#51G*+sflW zojy6Myje95LJRTcm)#$(I@WXF(q{N_n>=5xb2GfM>s!U2n>oa>Kqr(O+*}wgc^IM+T{DnzPq2&Uc+ z!!z|Z@i<1DfV6As?dxcWHgA-F*8@Bo|Lz{(E#P`lao4wiXXD?o&?3sevylzz->H8` z9w4o+wtu%TSIEX0-=Z*JKL_!P;1fVaoYCq3?nNinmMZSA9$UJ{MfZNV-K?^o_iiKm zIR#3RV|&5xAu>3PXX9rT*By0W*@h*L(B9dAqIo z4V~P|Z_B*LH(A7z!XmH%`7IY`j78ON9wn>_zoFw=`K{&nZ75FNPGP{lzu+ZL*@oDY zQ}493t!z`$UT9XElJ{<9Q=-E-$vnsB5D;CH#sPj>u_?y{!C!lyz1pS>!^`;Blgkh< zB|BJ4yQWRav88!`QSpQlaBOVKF9UA@OO#F7hj#mbCm_#j+LXs|BE+VQHE);36EvPc z9w4o+emr3$v$pYs3y3E;?Z`G-F;B1?&)TfApZ9Jh`_T!UWZAFrglc}PKb|l$u(t68 zm)|;--%g)Ai;i98w^s9SMh4@>6YBGCI_^X+Z5tNnrHi*C^NBJvEEk^oyjgV|@7+qr zm6FYKd=3HeGtxLfn_m4J@6GUC5bXV%k$jw(g8Db=-!#gQmBtf4KR5gN#s6vlFaA2pKKp0jzh>1Hy!U8bF`f8& z<9jFseF)PPGlJl+MRuCGHDP!e{7?SFOAs%`4IiXkGZr?7KlK79Di*c?9Gh6!CEyV^ zDi(GW?b_tloCjX5SXh8RwcZ%-o6zapxany6h;FH^VJ*vwjQT+RD0;N2bZ-rnl-M%d$-XM zNv}2La|np6PU8SSzr^6D1;Jl?q*0w?6ozN|Zp2Fkt|{&A!LeZ8`YAMI zSAn;HrORK~F0XIqbuhQdCa&@{@b1U|1+eQvfG;1k<4gN~FX~M|1z&2dF==(P`z`r; zY~w1kQ#uZS$(yI}{!&;3!gzB7#8uX?*4WWnV<9Mi?TImOXD#D8^JvmWZ=>rx(fKNT z4gulOG!F2+ir&5;2>x2$x!E5QhG)tK;54y{&!c+IJpiLtX~2Yzy$8@Sd5+ zaTPehzD>c~mm7&ScR?X%Uu*oT*GPp8>Ga=nt)sggV~gI*pg+9*4;OFV^*;K`nN1bd zKYk~kp;`Sn-n)%HNP7Ko3eO=BrVkzx1b;2GX6l15JX0SKFBQ0^v}^itti|XBUR3}1 z9B^#>xEF!9fF;V0%c0#q;0eg{nmjm-6Se#}@ZiYW=I3j@|J-9|rXHP}K6zH_kE{B; ziy-8b5Hr?c{MNMf{`pKcE5-g;YrVhsvFph(Vf@ufziIt(EArdGTIT03k7uLx$F7dk z`r|5|8-u(`d1BA~4byQ=TYsF-FSRq3tRwki9sA7hRx@64pn&6X%*Ww!nM0vb_>si_GT`5P6)&0e)hMH6IZKf9-w# z>OSHyJTtaHyj0+t((WD{3-%EoMME~Rg;V&SO>E&Sz_W=h>_NMIf%}u^HDe2tI8igU zkk1s>HnyO($mQ6=Y_jVjdjfPNbf3mC(wOjDF@VEOp+7U07lvo@8}U+D1f*S)-_WJ!j_RUBUrSU_&^tcw}2(8f0ef2Zr};Xy_-Dw6i(FgfdV{fS$}Mw z<4`MqJ(wq3&Rx%RTz%y|XX5AI4$hR-izEN|ov6HrjXw|hY~pK=b3%Mr3xA}sO%P>5XFNv4pg?x~9O}=dU{PhR5_IUXlCv9AS*^^p(TwQ;73Lh*b9}Vj; z-kgCDu+f>%;TkqNbIr#Ec<^4!+GG1MbqZc5L`58fa~*e%f8(~F?r_piaGvANiKRb( zdUUDNm>+AVYk7XGo^fx6tV?HQcC4TJvtw~4bc{K%+^Mq0wgR_V?PflwjoqB|8f5152?#HyaRBUB*3T~qg1_cDf~lXw z@J#(oyd&-vydP=T)X(3ulmS1(Wo%?XAFgL(H(vmrjoths;6>QYT7#@L$S#qCRMw>r zIq1XL)J)V{gB*;jlzq5f_2EvG{G5uuIp>i_g0Xk_a8t>yWl|rmI^KEMQb$DAAj5~V z<4gPgt}7HaT7wMxMJx;VePBOs4KjSVg!5+5_Liqj<8es>5?`Uu6$Fnws_nNhJkx$7 zUMg@wY1g#hHi8dl!<(x!-|^RP`u9JK zC{cYPJ;1Z^?bdw0;|H|{*-_ulC35o2`s4>^2jk?b7Y6P7%ozg#RKyyc{;q2s+m~yQ zZ}$IVxdOQd$YK5Cci>#J#`$>fHo73`^~Zb;0g=gR9N=dbU2s$o{Iy2{)w&=I&(sCP zO9iee?V7saAvDwryeM5T0~{M&@B;7_uypwg+vWAmoRtjP?Za^ad0w-Byo3|A;(Yt^ z*?g@0{M8r(pr_1#ov*w%|Ec%UFRo(%uqJsn@ioaQAvCOo7t+`!-3bpq6u{x8(4=XP zh2doa|Kb0Mm*R#G(yqya$IuXYB#H;;fMdghF9Oeo2XkoGh6kBL6T*YTYn!L9V*q%0 z`rtRMNv_HnE`sh;SOmiOt%>vWN3wBh(sWK_AqB{Ip$6|zFdj+SYh`C@O>z~_jp5y; zyjSY}%3C&d9Aox2Imo=^nVI*Vh-y6sQ=R_|EHW!J7!m>JW{Zi z|A%YVcUGDTEy?tWo8+RO8dg#=BOPf*Uv8AK!6SFs*&dzJE z|L8iZJkDV}=)Y`Zg~!3AqbDYoF5P;|6{+dyxk8*LT^#4`u8Z?~{_fkUaUOFmyTK=~ z&$s{Y`@1gwFZ-8p{2zW;of~uy4OSn#+@M>}Z+fQl3mso<|5Dq(?0)l`ZfVDXtrN?e zsQ2)Wj-ueBS#3hQoS;(T>!j!9<6#}*-;)YIcBMiO z-cB&rBPbK*ac=+iNSSbWBgh0kYqXzON_>qrpF==+GmQh}1Buau@w&={NSReF3p)T0eL0Bp`CEyMo=cS<-H?6 z`A%y5y$BoO_d!FgA`keiHu50pb>UCrIRwJw!7GB`uSI8?@*oT^ga65YcnRVi<%SQ^ zu4yCu9sbk{oG2TC7q_tym;<(e>qXfJmw;zuBm4|_5jKKdUHGtlu4b`@JZK-^I)3+$ zuXp|5JAQY+)A!qu1q1ExZP~xnx%I%(rk+2$(YE918%~E?OAx3G|Lvuo4oHIE`}jC3 z!+#GLKfRV2AMrhe*KXYWRM*8n!|x{7W^huF5TlR~F6MjR|8ayY_+7l`v7l}68L{%k*C><5@Dg*-!k@&DhH& zJz=H?dltU#d*5IBVGp<_EVfPBsvXNZxb>*GvZGte{awxMzw%ja?1QAw!>#h5q4GfI z;a2|@l4AY*SLCCQ#Ho#_cYHIa|1>nkhp#!iySJn7q+E@=wf(?S@1yPQ&Rty>7vGyd z_wKiQ$E7mY)G6E-$YG;dW1PHq8y%7K+IT*PK$s6XEeQTvENe5y8HQ)ZIEj}ETvOWJ zgJZ$@v(|Hr>b}7J$@7{%WZ3v-`|^X?Sal*p_BP{N-py3x$p-kcr-Cm#!IuZxJAJ`Ja*+I?k|6kNk5sDr2*dD9{Yku9^1;-f)K9&@jmj5z9ym6Agx><*0+ud+ z;q&tPW}PK#dHZl&K%UpspU>e$tv*8N&wRW(6Z>)GU-oXMLVvcocJ0d-+fq)dxIcRS z?_2R;&B}MYcPqY2c&$C3Lx6NhNMqsW6}~&ng8}e9eKp^O;hB6#yj0+N(yqyON6?TB z-%aCMHhf3^wBfscv}?n64+AfR?}oM3MCbn|iGxI3;Cem!=Ai=$35;#14^>W@pbwSo z8sJ(sQX2G3nid^F85{(mdyQ>`>4;n=R&1lrxhlQb#)lYltQp&AL(I|n#LwJ_BfTib z7lVCR+!vreZ&tgF_ikmk%_f^C`5XdbKbbsP5(Ix8#*<-qY(xITOAs%`4IiXk({7u_ zpL&547!I zAiQVlk*h!m@|56}P5X!J>id-zl@`~47Om>al@^s2*MJtS>Y0@ml@`~47OiS&l@^s2 z*MJtamQ!1$>voHgy^*7ga8boc{CWID;)OS%@Ob9I&)OS%@Oa?6uWz=_3T1)~hmUAN>9Dm?}y-)7T=CcEt z;o%I6z4IAbk^}AlMA=McD2FNAvYC+q&+VSo#Quu@lQ7=zuJ9o%H2Bp)rsq081=S!ruTKu*4Fzv=VR-A-MQ#EfAA^C znZIb(2L#ZB%h=Bv`~Sk&zYqIth3}+RZBbvzdE}9)6H~`eKJwV3Ps}`iqGI<{VE2i$r6a+6t3|(ySp9d4z4jrMT%>DG=8Uc6yI>(U5o^`Vz}bWiBo&4 zx?6d$bmI8g#~*p@%+wPnoV}x;xqt7}+}xRy$Is54n8g*X;lBeW-wp4X!0!^QcVN7V z@KG$m@y5Dv-zgkp%@6-iJZ^u?-xn&F!F~{kOSlUQ@uTo~Kk^@JI=o&#H++!$%V0lv zfBm>WzJInsijw;q#Wvb3-&UOQT;9fi*#;M0kJsn6JOehJmvFQHnj1dIy_D~Q zf`ql;1>}!aE`Ous&mULFAC9iy`#R@-bLG!Jom2Vae>>7Zg5=M%${&xHgeS|4?td@g zGnGG)^2e%vBb&|n14>2PKbNWN0`<|fe+a#Q>RCYB{@3sP*xBvbLOlUn=s#A-B97`$ zi-^C@#sA}7XWnrxVHktIkCaJA&{mRdq9X3k1EErHufx?~a*q0@+9skN7obeym~jH! z|D^0-&Hdjr_J0feY?bdQ%0?PkwwFqE+Dn|`&ef%~m$qY@_7d$P+Dm<0!(O7k??$m^ zlI^Af?vd|KfOZGLw412+`8+(&_bqmbX*Zq6xgZEdm~tx&&$OF}$94tSE+K=3HcSx< zVG{R8`r!SoWH-Hx^R~6&*MZA6xUgMbpW7m%vFW^p2mCkO@IjvUL)Z`E&EWnX5G1Sx zFJL!W)%w70@&|T^mRk#G6JYpl6W9OX0Z(qF{!flm3Ar@d`+Aozw+dfPjZa+vzeXv| zJRi=R1<&)}R`%VBXe`NcYS}-Kx6jwZ??j4OhFWrJ*YatX4zk96nD15uUX)ylBa2Q| z`)-_K&!v0HBG+ewEF#ZP7VY60vM9+ih&*4!A|O0&%Ag+5a|%dNGH6aNS8zQW8T1zL-o_FogE-!$jqi33?k_?HX^ofW?1JJv`Ukm` zp@gkTER45s3Dbv{ac)({r+9GOs>W;e;s{Tb&|$q@~?btQx}HenYxg8 zHo9;F#4)Yv`Wh2QcW;lkfmO2$g!f zHuib5#t|s5s7p1D;MpAFGoSYK&aB&vyoG~hIfwG9cHD%F< zxken}POcG0;C*Wx0WSey%Ah&#aQRoL!jwV8vynj?A&y`pgS4(l>xyXmP!5`L^~*R` zPaI)ierO<0El0g^gaY!RHn~|)(_ifzchddkjHoY;dfSYq7tsHAGgEjyHC}M@q0W8E z)Pw9p5@6rV==R<}>^$G`jOIgm{Zy2#d@rjRM>ty}kia<|B_FC;bs^uA0Qrny#?)=| zp-y>!FaL^;Gj(AYo~a9ox2JqH&j;de1`B0D5es2G;|P=P9e6+TydT1@_$WLRmJbE_ zlZ#Wo(>VF_KZeVnn<{_2uWM(E9|7{3$sc4ysr*^ywJ^D&@~3v69^_9xPR-V8#4!th z>RCX``B0`U^e3UR$jgU%+s%jS0iOlucL~}=hjA|HHc=7x=z(YrZ_g$^P;VUb7@A_M zd{0p}(g)3ls%bAFBZ@XgFpl|a+(+!-<6PsTeu8Tl^|xZ3)I4(9Oni3&UH*n?H`(Sx z&C7-SwNQj9x5DsDyNP&v{A+O~cAaTAt!ErFD68dpO}i;99}047I8J?EHZyEp$MTfd zp&gMA1rIHYY^StW$KvHfU95;`I_cimO&LX+79b5JHGV1g$aO7wL| z2#;L`;swQ(WYS^05RDgjR6!f+H-$j3=Ke7(q!qrWTK0NSMy+nVV9M2{8ZYqPzu2|& z_zpo3J~nOm`5+Ru1<$nMiMJt%yPV^Y{q)LgRgi2kcv2Y;ZL1i+wSWe-{$5uJ@r***Vg+u z-#fFKj$yB>yeD~1=bVB&@)I(hE^&;5>&W|^Y56a8GbT9&o z$fmbflubv`-bRii?BWacf%KP^9jv+kFO2>Buuq=gdx?k})GM3Zv7s2_VXVN-DS&M1 z=RRZ;c`E6$iE&N7Cjs&{!IVwxr%K^C&-2}e$);yxIfYY z?{6j9bOGmWWYgaP?`7a#88RXKK`-=D@TGTsGD>rJj#`EQSSxuX% zDm$w5n426W{@gCKM}IEEHEbs8|D@YYyhpw#0opn}lC5%w{@|b3u@= zZOWxEJkw?(o{h~^#QpUGH_B#u1voY~)7!w~5@j=8!UNjaOh<8l5jK;K38iB~f#N*= z0=bl-gsn*|jn0h<*za~@LNy?^umFv?99y7%G-C@KBdYMa7h$0NP7D6YB8Kd~6czWR zoKyQ9F9ASVxrX+;J6@F9?`prh#D^cT3(UMJo7jTQma?D<5Tt|DDF8sh5J$2q_W8;&w6Cjn4N4|&Dg^8u#vWv`(J8VOcGIGt`ua`s2^Jx zg=O2sK}$V&lvZT zTxqiHWh~pc;X|9hHtqMTIKG^_vux+@%MTag)Bt9)8O)wXh@OApc`sN}5r4np=22}P z-{EFX&2y}%UC!>z_((aEYRi4H$DD;L?ub!WFk;k|*PXYSt1z>oy-uBjSiuWiQM!|=?QJMnB{?m65aWkpoX{YBu|#N59NytlDL#oRC80VjbcAkS;c zBIZ#%AV^pX-oAVx6RQTa&b~n2!WBP5`>f z3hN7mTpEa18(Lo+f#0@%x%9T=Ppz0crE-aH+XL!Mz7I-2t{X0wkUiCdc2q9mB>>KQ ztMadCA=6$8!!zwA;_WG4&C8A8ZUzf&nIaa#dgdrhx_99H$n%=^(h72EFjnp7D%8Mi zH*%*~BbU@u-{cKQ3wGNCzp^drE*E-l1H7(_LqGuVI&(b##vuKFvrtajwNtB zjpYc!H1@U_5d;}e3Q+`!C9D|N9K(yyID$tF!8iinOXK4RQ{_0qPPEsIV`=a`33U1! zW*kBLfosPR>hA|08Hf|t)ch#Tk0Os!&aHla)JQH)OskOd)1xf%qh9lZB<1|5ZruHW zMdz;0YtV7;{Fj+ai!+D*d*{Q~|7pjq7u!D;&(Jlj!@?082z zDxy2Izd9=N(UvU{!53*N`X6n(ov!9(kefsptc=H;} zop@@_*;|^L6E-<>;?&;KiQ{J<=S815;p`p#%>8?(=H||vJbrfW#H@E`cE8jKym!X4 z2<(I6a|p=Org4CHlDl_I5d1aI5q=#D`}d>pGQg4lVACDPHpLAeq+OCiu&?W3{E2+B z1q*Swu)R-WL7OvJxxic_o7|w6fVY5!*WkkI@%kno7SQf)92by#H|^6?IB~xqVJ&$3 z@*_iW;(4pdhx0Y~kjGk`52uw6-M(a@QIakBI>ikiHXt7s;>52CIe(Zl3w_A`CqRWh zEG|0z9oL-Q9q+t7Gjr&G^AS%Q?v^7f@n8xUYgS#zd$-YrvkB)xK8JwtLK+A7sYS;< zBnbZ6BZF#P7>1YeuP2uwUP^YbmUc~Dcnl3uS4HWxUJeM^^UH@i~YE0v+^SE-G&!S3Fk#V zhk)=z8VC5vg%=+d1b^+3Lp3jk;hDThyj0+t(yqyilW53>7oWzpYg1XR)Rs81}$Bk7~YD4eX z%Dl*VKbqAp<-ObRqQ)w!d2!>%DzX`kRcNdNA|e5?itIqVSVevPNF8@pW>r*XRIIEI zHok3!q>6;cu2UphA0&pH#y(?h61xuTA2M?)!tl&E#m2YIvblJ1iq+ylFQa0a2cu&Y zt-ymxk5Qz2{^Lq{(0dv6_vL1XV#O#1{pn9E`f@LL9TF9Nxs}-z;J|Vw#mYL6<9Ri! zPsDqV_K9XsCp|uKhevYmZy5g_4d8IoBZ2Dv+b}#+2NEyE3;7`Jn*FyAp`l*jMCDS< z0LP~P_66WAU|~)n7q-jm--1Q-JvN;T+O_GwEdj4~|82GqFFvtaI?&6bSk{5uUzrD6 zK?f#1E|DV9`5?TI#y-faOqXHyrP`sPJUF6p35`pTt;k0NuGc4rVjvqUE-_?Z?{UR@ zIKv)0eZ%RzU-o7Psdi(i)#AFo)iT)PaJ#|P0*rmZ#uI;1TXWve|092;BhHQ?FU zYDdtnjjc8hyxO+fz+kL+#VYgWyz-`nA5}V?^f-p{X0;!+3cQ(*700NvPSWY8-b7`{ zu5aDeJ654FcgeApau53;vzj%Y!F!L6XOt2j&){J zT^k$rJn%wn*n-A7G}Zx9E7Lvce|=&dgPAz74jpGj29Q|Y@ghhI0zwCA93WkE_$P9L z;IDa(V8)cg@F>f1tr_=E_#vK+Tr2@^63b?Pp&p>zHTz*MbuZ<6T6LTu~~V% zgk=)T8rX{?aeSA0#{=tF9+$8862}8;|M1WLV4|G8;~wk5bGPoeeA81&&mr%__Yt6s zB&4yBhQ-g)cr)LMis(e@-KPf;6?e-R$k=2+wfx2`&rj3 zA1URLxBDwHU=Q{f+b_CD;mbi0G2S1QEBG{UZ2A*k2A)knYyIQ$<%Tp?p|J{*vDi{v zuTQKZSBMv@Sfv`Hj2o%wEJrEa{pwtD>IZ=qs4+@>oFXM318b4XX>5~zB~GEXnfH?H zZL@qPUYugJc+ibf1bC49%7aOdQKUTba(|Tvy_b=L0J4cug!@PNfmkt$)v9&RAVNV7 z^r92kTbch_pw>O{@rht=a2Wp`4e%&8sUHbuPE;6P2DtJc{*QPmZulVWnm*A(_){-% zqI{wm;Mn*?F92@=OH}S@2JPDLUwEy1J{K=Ov06INt#uFRK&^HE?Ck7R(&G{-(4>Iy zLK+7^hH8iUFNW`e5W^15Yg|I(5~LZS9j@0WE|DLO6_*&Y*9UKT4_C9+owY(=+p&LX zv|Z}m4>(?>`@1XF2=(DTZIl`zK1+1$x|H}>1)oD8Oh+^#ry?VbVlC~Ob{caQZ0xjW zaSaMkD+VT8O&VUF_i3<1SBP+);IG#$g z_U~Gb1(Wz#hW77P^J4w|yF-JqVj05&DGw&Q&mBB6-qt4CmUei5*%qfd{+@TLrtP}b zt#cRabz* zAP5DS@y0MbwjuxFb%bm__Ruk zN{bDo#eq0JozkMxVgqS$P<+f*uHPfiHET?n z_Z}UuI(wP}jNb~}b_`^&lWRJyduKoQ#N5n>uK4VJMq+ec5UKS$8a5+coq9+ZQ@ls(QcpI9M*F0W^NA0I<6hB8XlI}l^83|=CcEt;o%Gi zRLy5-nGCoI5ZO#-h{G2vp9uwcFTDe!e(<~Vz4MF}pP?gF`D~e1`6gR{&*J4bs6HcE zl;H#M84A*s&svSo3R#(*#!jD!_KWT#eZf<%m3^csCmmH=!EvFQ)pq2)Tj?}(b|#tE z*zYGG8a#~y{G?(#2FGY6uJ^gCZO1S?({?0YiWl-h+BI#*A{w%>9UsPZY;4EpfM;Vn z-hp=e7ab3vrQw>JCn!|+J6 zxYmqZhIlr#SOVT87RnJWh~`d@)7~Clly`lE%!BEP%9tw?6k%Uyj&KMn;`2J z@M8+`=2}rdhGbEO58%g4b8@jH+g4)N@F8W})IVYIHdFtE;bm~`7UQ!KsXS7BM%$yK zVy=ZsYT$XHJdf2r5T9whz|GBUEj}B`#Od=aWHnx}60cdt3#LzNyr7ELHh#QdWI$%# zv(af9FVJ{F9ocRS}|TQ zqWJ}D9xo_qyr5dAZTxsaHmmssI(`AQy5z8N9h5#L>`!88cs;^!b}&wUfyS;hcGbAp zRW=`|4_;|eX|aK{IIQCUs*Z*VPJ)geiPM*>a#7`C6HKRbJNnv+>6uPxi)w8uAoe0X3uUZ1DxwbiKg)-D=I1s1ba~1rV zqQ(x+&T8zS74uyNbK;?_Nlik}%JvoGkIE4KG;EAD z9g8hwoZI2Sp*Vfkb=M>)pUoycW+1#pUXyL*GrRGmL+2tH9xTM^kFVEuL~uaIZl8ti zs4;`8x`d4%3(x5sm?e!FP=Bp|%pf-qFW*40qw@`FjotpO#g_MDN=c6wh)t#T72kjd zbozo>e|8X}q91F1PW=FvtzX%QL8t&$`A{pJ}|HCHZW4EprUI#x-7m z+_{p*3#xgo1>yxGnq#2x0(v6rA1}yfIwn$IvIKH!GyvYE_K4n(W8 zsI=HPS{y3Rh)Z&eqQ!c1$u70EdTjXg$`hFZq}L~-g|V-&*_t;g!5al#y!k_EaF*%Aoi45 z^HU5WVO#Jrfo-A`v81pFNV|J*;1(=J|HK$Bz_|MsEX3i$TJ}$3fgLx4l?#*jz1!P# zf2CcngX8xuV4n-G!G+i3_1R|7E==K%HhS$L;N6e^3P`*AhKFL+B52G&V+LWgcp1dC zO$ZEYp)u2!xr%elBM=b0eTY>_hM2|-$mbmu?{oQ$dT(x}F>CmZY-IlQl*SA)cvnJ$ ze6t(hml-ZwO>4qu8Z$UKt9;giz6=UI$zVQ2#=!HU{i1!D%bvih@MZ3Qzw`BpU(Wxx ziKTa*o>+Qoc4FzxnFC9|-S#{0cm7!||7ItJoey_ny?=Y>m)efJxt)ia)z{&3*yz1d z!uc`9kKhA!IU$XOpIz+#hj=gm9!WTk>Fb2ynR<_S^lJp9UDMYop&|MrQNGSRaBO^? zSAe&GCCb++qFozbXAXF^eVt*QA3|$EL21kO9(g9{cbBj~iKX%L<_yQm8>x2;fQjn} zLPW&4HvZVtr%#?mC#jAbxJ>^b^%fWpcQ{sFjPe?74AK6i5bkewbw1@K<%Ermbrv0^ z%4@C0Ys)>KbbBIwo^qB@w9iv(i~|QVDzIN5Y%E+-akKg|ymu=;Lq}z?J{-f6WlX>*J03Aop&@%ER-13WM>+IFRa%Xg+(vyP1mE zg5!=ly>cIEOW2R-Buz4}(T5fYMezI96XDX<;bdSOE4h<(l?YyV_TnMJLfRU*tSUtL(L@0Ao%MrUnUIC^ks;b!XhB;nth<_neW*rH;1)6uc_C<^F2ofBobf~pHp8( zeHrpVV|g|^)F0x9r)ni!GiLVpY7*=)Mfb;L#>ajYTA$DM+)57~eM@C}B!t0D3 zXszgDXQm!y>|k1JMd1@QW9-0&-$G*tg^Z3zs`=Ay^hx4QT(3+1bRjdimazl)Ga5U9 z+)sMFsQNPv@Mj8{e7x8}o&HSA*NeiRnbNv!)4tm9{!GCgs*~L^E=1=}OHWR8U+4>- z!mh~a{QTmTEe~|9oOeKZ+N}B0y!Yt*Y4|b;=QY)74bf?ZII#om2i1PihV_FMvhi|Y zvh~S*tp)XBSXv8O9mCr2x%?z17I&tQpsXMnvYeC&U(6d?#TE%NEpwkL*V&NJ$(6~Y4;syh2 zI$o~R^0lC_ue27lO6G5T`)XidE%P~@mahe+ACv6bG|F@V*-qmCyVb>Wc#%i;h`vd%@wV+jct%%o~@?Np~D}26TYC#JFdF=ze`}oPZ zy^lK1-r3JRF*kJ_>$x-DdRn&TPCPZ|>@7{rsV~z&UuHPocpK7-^TBdov=)^8GP7C> z3dwHfnKeTU%O;QiC=9TgwV;K85#gS-=mXVSP>_JZ>GLJP^|@>)mqRR zI;|OEbT&FIJa#ZRD4b)Z)3g@U^=a#m9n5MiXbpZV;#dlcKoVmIHvAS|3p%J{;%Y6Z zOWqRa<$8T;K?jG{GIpS~puRsdmFyZdt($2?-OOMiUhF`uvgkNnt?{Qhid1XQ?*V@% z;d~~x4V8gxr?E|a(7}TM`X52yIf6OoKp37GqucoYOfC~EZcwK`bD-;MTYATDACDTd zjs1zuS`TX17YctS;ryoK;#TXm6a-3r{!DH_G?h*KK=V4aFSK!ep}BZ@Fj@}^J3}lF z*Q~&P-1!P;b#73+I@8W-hQ81~?~}W~Vpp0uXW@OJxmY8^`KQctr=nmHaac5FElq2Yfhay?MFxJLET(Btp{yIot7_ikH!r& zhnh|ZeUSC(2hGPE6Sq$Ls^#lJVP9!IXbaj``FyOt8J!!{jm^kUFgC}iUGx~8^kcLh z)Qrt-d_N{X9A~Tztq1iuY^7MZZ6B!CgI4=8MZDgW_ln(L>2cUN^`OhWn(E7_FGC_< zKVN1jnp@$R z*K+atX6lR4X+3C3>p^Siv}TAM*yyzIKG30|So6cxnLn*_gUZ~XC9Mao!EZ$zOJNa6 zV(h?%-@@xbhjd(Atp|0 z{!GI8Ol%wK0NGCa`k;dc0rWqDKwUx5deE>j+lB{Y#SI1|Lm@hM`X%q>SIiCi7h6V` zj&|79gl@-oYu1`j-g|WZ0eqT-^IR{P$A>VU8xsV79maEEc&2V6UMg@+Y1ixzJ&cBU ze_OB+hYQDM_#_s{gBh$`DB<^Rf14}0KdyuMbYI5)0v29_3$MrP--1Qt3pSlT{L#jz zIR?Di<0KB}BU%)xJy-(ktakFz<(U9Kq}Z9fLte`!1>vbP_l=eV_}#;}X>ennJrazD#&t z=g5Hef$AKgAhmKo3Vn-Ue|!o1lUO$U3weOFZuZAt#h~{QCbull=V8%;;{NIN{d2+vR)@zEU53Iv?w$v>-C|#m33SfpP}0_5o@ipvcGdiRlasYF(h}XrVz_uM;iiHP)@PC^RVRb)v=LShaJ5 zQUMe_2FL{_t2<74oHdSZb!qWHSNoNT>*t)ALzmjxH-CNc{qOEXg-;IB97T` z=ESMJr4z@`KK=-<`osxm@91al-#axocjn~rvvVhAaW!lBC@}f?SXV&EVc|Uq&}Jm0 zu@Fzj{yV~h0q{tmdTh}!ybS&;|KVkbm*R#G((WGYv&Nz5A7>2>>mH(Nd`rN5ex8?9fZ>tCIIZXFa zA2h4(OSJ70@svwP2I<_aBOtn zG_GZ%`<@5h|KHx%z(-Y`dEYxT$xJ?&jEXiW=p;cM62VCb5L&kkNx0xw!H-(I>Lwu> zm`H$_4-0PlnhGlJYKzv^5A3eC?!KtB1`2((i*HcTYSnh);=ZVLm))%m1owRt#gbB& zdH?@=&zaoZWSB`KkdS+RzjL4aob%lC{hV{2=X~5$#=ZdJO=aw>2HntO-^|kC>_01; zmHOQCHN*)sfcHY%Ui`x4p2gik$JO1=Y!_ysu^>2be&a&^K}acV?p4%7@B6e#N#>(0 z|FO!GOnZtvSvT5wl6jFv@%U$xf{?DYfk0NeWKe&&4c%wesoeh#ux zrXwn3Bh{9TOu7l&s%6VYL6iZy&A7P&Z~i#e|GyRMSTJ^V6Q#l7?6D~u;eSsmva>sO zIg`so*(md|I{#wYQ=EU{hON=fbIgl0avqci2l9xVe}yE0fb^rW{%a_tyY@dMot5WE z=kF(r|KrHYbE*FKq#9wRGXLV-i`FA-qA|~pgr_q9O8DQCxutO~;uI{|{HttE>iUSi zMxhRniIjri_R4J^e&J@%85L>K;Ld)T=%9O_yQ2GAHMkSU7$;aN2xDKg-17lZfF^)wA8+r%U-`lbBpr|dFJG--i0Tz|cpnX>56lwfX$>JOCRXnVv5t$dqnYn0ze^+Ae;yoI zy>c#9DG3BLs(!G3ArW0rgeQX`onIn=GF~g+@qb)QUo!nd9cWU~FFXjkRP+n{_i-wG zcO&SA)-TMOW#3n3>le`6bUu>s%^9A4VPs=K+csxrc8B7i9@-uQ^nI!PrI9@b zn0SHwFb>9m;q40_p}gb7+Nh&>h+lRRP}mXd>zg6E_0p8`A;75 zhbcvT-W9^T+0c)Ma}%y(%K2Fc?`9+Etn;oAi2No(8Sh1KGoQs6yYkNLVVzg*|GQsu zd1sGNr~~93W979_Qwp#jRdsgeX~CU53q>x}S7M6?pNle=|5TLwd}H19QhnXEJgZ_X zue&losq!ZmUPm*3GB46dKFNavn}OuJ>m`AJMiUv#pNZ(K{7Je}Q(K zvf=E(88QFi+}_|*vxE1=Wy=Bw94Gu|pPNNpTjye@KL5=b)*Z=Z@s*_HvQj(de=q}N zCHvfLi&9m!d{t|eX?-YCZ=ahTg7+4|%?~S0qOp(rKvR)}A_yoIIq1Zlo1IfKtUFsq zcy3n7Yujd@n@xE>YM+}0zgWk^YPk7frAfq-kra8d4FRRXlkK3}2upn@Z6bLvgm_cg z6V5&BL+d8yl**MaTQ@PBON&0=JBm=naU<7D^WcJNi|gIYIx-T|kH)GOPegYSXraSv z)IY+5bg8t(I?z?arVE>>E$)W@1XyWg`mFm?J3(-XBm$Il7tftDdoCNHFiFo4jqpw( z>Lv!Cnzd!4=19GLZWis*Iu?ur*=X*t_NvDJl$l&MdfZ_00kY99=iqfBvmS!|%vjX} zGVLkq0l8#5s@H^=7ir{s9voPua!sgA5(sEi_u#Q95uKISNar_&DdXiBW?r)mAtE2# z+_0pf<$UQcV9jIQ^}tgZ>o$OHBW$vHS1#gBW!^d(G1FVe_%p9cq4tK>KH{E4(il@I2(M08eu zBb}cC2_xgR@>?Y$N`>EUL^!GN+r6Mmh2JJ4-cjDY*Ew0HU+a=>SdkxlJgC!5J zt$+S&uw}D`bw9}nYYeNesq9f5Cu=~X{v2#B+MhJCPtJn_y1DpR zaD^lgkbX2)y+9&5>sUZKKLZd(#(NQP^W5uXuED0VAEyolkzg#CGpse(5$;j7&%q8@ z`?1f#f{&~`7lNA~R+>aSH+J`^mdzd3+K@xS^b)@{IBZNA@@17+UH;g^Iau+HoqL`027UMWA_~F+|uFb_H12)t!p3; z93Nf7++qE1c%*m!m`}lGBTwV{JRasqr{e59h%Fqg!0R5RwD}(vQZfUkK^0 z{SQeu{$!oG!`tIM!gW-|b?kK=*6UbZ*J0XIT-RykLh3}&kJkIOB!7`Zc7KB*wSVexB7H-v+N=`N8X{@La-sB*Akfrj2^Zc+Qq@Z25-c z$#Icy&=zNzgzaQ)am43&y#41{ljMcdp)1K1Yt9kUFWo2HZk#nFtIG`(x z&%G8&0s-kqW1V{?qO;DuNatq&!pL~7b1%+qQki>25Kbz4Y90pNMp%!qiFhx7cvIO^ zQw_Qy*HOWH@!vS4u%~9kXIZo5er@d9ZrjwM-wuJwHRqcPk9&_Ebx!yj@Is{Kv!_5yXO``E|%${W}4i?WeZR|_NleS*M)=MOk zjdp`cCP+pBgb1XYl+UuFEylb26CoQxFJYWz)ny~qmW`TfYFiB1s0KARn%9MLMcX2f zeR3Y&+2-WB5M>#&k?ql{n@B`wou7>Z*{FEVaMp$5r-PF3eQP%gf57>=3g{+`KfvyC zF6v1BFW7OS7i_LUqaDq>XX^zAuMd3=dck7zCE&^CVIy6Wt?<0$_Gy#sHCbc48};W~ zvrPk8qVXH)Ho#n7YpUxvAQRM zX-{!a#Hc^#YU>>a^WQ~iD%7(KpWS?^dM^VouXXH8x{LlE`YqNdMm8CZp zWuH`d?ijMqO!KAQNyj|tMdCMEUt)rI9_HRp&5f&$$){ zXU176g*7f)=V0p`$OFeo=P+~DuyhV1lzY5F?s3?1&wzhBU=B9g&%D}l&vB7^W)5pF z_z2}5`@gTIJGChH)Qs+RR(s87Fwgl@)HNJS?wNZ6bq!AY>}yTSviQCt`|K;`a^q0f zP#V9k!IpWN*RE`-S*pxvZfP=LM836z*R&`z>S|hSnddmlJf$<`m2D}s#j;s)VJP`p z&u)xOFay?ll!D8=IDLSfZpI&7-%u;Mm(;$bDn*`-wnF^bH9z^i2;Ac^R@Z)*_LTHt zb))}0Y=E^ZjMPiz0cW+#y#Tz!-E52|G59=eB0B5XKsvuEKpC%9AI7y6>ImGhq@m?m zR_k3P--O$ASZQSX2<1PN=(h!SBW$wsu$SP&RQBMsfG)w>Yw4_E+>1~aUnok>kH0fA zXXVH2;C67N%NY&sG&}D*XBw!b^o;-vnJM{CXqeO@&_{1YIJ2EgO!`aOC{z>E~BtkGOI^VC5Tb z@T>DBx6Q99^6RMof9z0vlP7r6=2sMiC<{XCnW|&(>#SfgCc45TUFRL)eE0MCcWeOp z8>{0d)1D$fj{5Vq%!@RM#?M6aSnf^mz)HSNL}wj8N#}=^M#gI$KgaNVcUFlMDZ!J; z_|abfwRIun0nQaa_kSuC2WOQI=Ps0y&*i-RbGZSsm(YsXbGa19j#2-wS$i%wm|s5! z*=yG9;jCSaoL^14k^!=ptt&x)JPcjQs6W$d^Xu{9SM#Oj$>w@x@yjog>o#A5eg?*> z+w^d)!F0IJ;gC})SvmK%p;AIgRJ_HYDplV z(JTh*FB8#OZENR0@s@|uIHI@EZXjr>Y;I$p-A zo`Y#mQO_~z|ED`qRtTWfH{{_R%__cryvRhuSNhSgeX>8LRy_yl{IJrR_N_X(!Ld)1&zzp4kts7Wc-!h|C!8v?eH*ivQ17)T1S~2@P zgxwY~9&?^?lJrz%vxlLlvd3t9j6R-YbeUYPw);i9Up%?};@sdc_C?wKqTMeZ$9{3{ z%wgO=VYfxQEgsLdIBOVsSGz6RZSi=v#kgAEo-f+-#gjZ=9L~N!yI-{X#pBm6;-~V% zI5TgzMY}B?&$c+z)^*$KE@Es3IElJ$T>fM07wxtqJAC0B`N&Vy> z{-o?w{^Tk9`N1s5?#kr{vz@ySC; zdV=p~kf&Ra7#RNNop)~c8}3Z)H%=w3AHkawH*_$Mq+)(}9w-k`8XsSbN~%?+wkTCq z%U88lHPqGLx^i`0RV3Wd7;b_i@Vfe$AmzX0Gm(Jdoabu_H_RCH8#y}Gg_pK2ufm@g zSB8}t^RK>gMomjgQ~lD`mT)tZm8v-pgv=k$jMMPU4)ZDv<#L*HU|Dt{Segg%kq3~L z-;<8-=L=kxd>wGJAuUZ2Ea{WcF+K7dyebTDsB=Y3vpIc_;Um@$<6y1I^v%aR;%o%a z4exJA)HA(@VH760ZO`yi;GK&hoP^4 zazm_!B|rPuXl%lc^L!>#A8B0Zscu|||C&a=j(1=6Rlt-ED{m8*hIyAb-_1D7hF1Es zjM%nL_Ps1;APxOSmbT%-e!*;bR`)D8kcvL!d$w!Yj)>0!F53d}O5m(x=9Re8x~it3 ze)+0!-SlOxt7@BZGDYtpYQpH#t6H1FHFc%v8wC1|ruvq!38#0N#k*`!zcCeY@mz3# z5OqtwAYLYLriu6>fe-6w%;(t0u!Hph*3{KCFPqsvVMsP#m=)iUp1kkKHWCx>J3J_zlg-nzoCtLu z76njyf)0TV)vnEHLN)0o4^I}KY}e-Tiv+Tst?fDy9os9yYUH;xq)Vk8)`6}XmV8K? zs2%QxUnZ0IM^;EFVN*gwZrf&&C5#qyTj!F zW;)gSL!$srR5R3N1lF~AoM(MYBile897u;gOgD-8xzW@ga(*BU(@taU58r~@Q2pWZ z@HlUWMgiFEP;WIx+n2mRr{VO6BWZ^X~?5$h@98`x#RLk908UIZJf-zESt+!`-y~{> z4XbNfn(LdF2_0h6b~slq+$LX7@fl1py4O>d#S7pBwM1i|0gL8T)FDntp)GbEt1Y&! zinqq`*%n0soS@ctDv!@ODYV6ZPS6&y%vv|z*O^%WC#V^o(&O_;2Jcf)b$I^*r}UzY(DkYnOOiQsu`Zr{ozQ~_m+ppc{?-;z;1_PZa0$ta3t-p zVZ66PqX6u7c#_*8mRZO5{7@9YiE4ESiuTHK*Dy}6~Pc7?pO#qg^VepR|3zMBZk`&Ae>?_U{B_p6w5EZ_5xL{_g8 zmWKDln2l_Q)^pd1=z{oIe#3A`=jV$sGG5+S!S%$DaK8c{@&1!!_p4kFnpEz!*Z{hX zu*vRM$wj;+pp!|v zcsj0Lpd3QA_T1ez>G^W)a_x+Yo1%mW?Vcwi<=q}f#yJ(;8P3ysy*Y@n;Hvi*cmH78 zrQLUbeR20gg$QYRdUr;;yF1f;UANmgB|52BbzRo0q^52j^m2h+1|T;S=rW&uJjt$*9QNh!K1nltT7zdfxtH)qoOjC0ld z-r{>4_iWqJo9Wu!>rZ2hTY3w#-N@4gM_eCYcqIF?!iw_lY)59LucB>RTKfz8d%k-q za=8e(J*{_A&abo=wWr@#dncv8+UxgBJCc4h^N6SKH|G_ijK9+D@fMf;C~!pmcp75PuLvFbEX3Fu_pUDAv?o4T z-5m|C?%owN!l^?!%yg>7%;9&skotQ9J*vmk?Q&#vr#YLuR`*PB!F5fAR&(|nA;gh> z;Su%IClJ>p&4ZN9st6#y1>G(uLMT@9ZtGHZtZR2@%Kb`#b5ZQ@ua7$0Z|ZaXN$JpA zAN-UDvNVTAzg=-ZKRlh<%b%>zS6t^6Dm_Z*~&(N7jA(quw*szYX2s ze5v!b6y41X*T}s|R!5-~W^Iz#w z@?Y*^+>C?fb_3|V%-1gnJS1RDbY4>5BJYl%9xw)@Dvob@vnLGb+pb05T<)E^KI2Z$ zUGBTnH>BO;`WyW=!ppp6j-O_FrCdJ5Gk!M}znhG3=X+h>QRjPo3%#zmAMaAL z`bk~nz3{8VcM^{RXJ07sJr;bg1^=xD-)F&pC-4(H=E_k68G+%LYIIo!&R&vr!oHH_ z=D=G%-oJ`>mJ@N_nbrW@FslB&xRVY}s$OTeSm-xc=vlV%d-+DlyBisPze!Ur7l;Hp zEyv3#BPGj*3@scEn<@HH##PgxN8eI^tC?u9tDb`XPl=j|^tyN85CrR#@LvFz;bOjj z6;Pi~VKB}`xo|$Ugb+CEjd+8=Sr5cH?$iHXfj=zp#{|Av;9CU#oWOSq{565UDe%1l z|E<9H3;ZL2A8UR$^gW%c>uOr?Z;#LMF1?}d>)emBkcMrOhVxtVoXdsDmS4D$M@i>_ z<-LZ)C3jDjFL0xwA59S~>7{ofx*%xyjZBgsAB2EQ!!T$rft6tsuLj*Az6c}pQ3l+c zkEzJVYrAUsX4~rfH=ygG{DBm@`Y>0-Aj87+__a=8j%vg5r$)rE*0_ zMUPTZ0GnG$8LsAMxZ!uP+8g`gM%?k+sVNt_4`#Sr2luqp`94%`ndHHpzyBHg(Smha zTCYb5R%S$Fhu@FAyggtWn{a1|R9u0Q^f7hd7 zd=I#z4p`UaN+7!T5X{Im5JV>O| z8S(9S&+XFE_iS=2y^EBLcX%gqLFDW1jCamB_WMF`>2OAzTb-4;C^4lY17$?mxWlDQ&^-GJ8w%=|*5ql0n(BXe zp(o(!oYvq+xrAfsniBYbsF9;Fci>N*L2X(??C^iY0#oRsbU;>En5Hf6QL=yXY16ly zTf9@gpym8JXScLJ*q@`k)0f@$PG9cE^>}w|+1;n?%G+1au=r3<(+b3R+h>RDavk z)3l)W@WKt7AZJ{9hgMrxtQG0$*|pHE^*vAe+n!>Yj>dk`>&cninb*KNoETFs_H<-i z;MQ_GGA~d9ozWk!(0Y6-Ln%Zks=r9vwNTlbabcM@0cpfc`|e-#x^w=}S*GP7FW-zg z^%N)_p@znVi+f_1^z3+J#UILyH4x8(3v>bH;|VZV<&FduIr7wP+E*59lZBh8+G zOY?O49tk2nZyr?wA4fC%YukHXhyc%xrC)Tob1w20JG>|s-2TCe7pw26nWRmrQ}Tm5 z|Ei01P*MMCB&+U!Kkuy1)L0*?=0GjD(WX5CXXiAHxh{+`=SKPGi}F|VV~4-2yT24E z-0Iu@<_aZ0yUw?BW*26=9jxDVku$ccsMB23wriSu@4xL=dz_whk4MRRKBv(6t^@5r zg;fsTp_E6!JDbj~=66bgZ^!y}=ax)Od2kY9KN@pB>}vPDaLh0sK`4$4gks#~YlPw2 zQrYL4t~{8j8R0M#rNb!ae_rvEPjkL?M%|fHzOcouc@vcM^}9~rmz{Uk=9`g@cVflb zS(~3*xaN7+rn8=|*E}evG?soeBajxo;1QO17HZ)4(Tu5Qpr}s|^mv@g_xAKD8=vo0a+ID=+8h@zh;9eIz0c9+Dt)E_l2T?)UQm0q zGIsdJ*c}T>_fEsN*Ho@6f3QRGtNz8^i#(nlhbN;)g|wI9d9GK@`C_#ApPxfaXLlAv z&~IM$PY8QiXK<_Xs8ZMv{e>RW#x@Lw@3~4ddsQb>xU(y$r9H)(S+h06pP@^TivKrV zd-_~$p3+}*ISWpAq&@JHzRAH&T^`}ja2-)45bD{Ev~KDmp4+*3>mJ;!{>bFT-ETL& z8%^uIUR7th?pJztwE4m1zx!|3Gpc6vmP%lGr>FGxt_jHBJAMAP*x`dm+ZKG<`OM9a zm4DpHRvP;(C(og`bp>s;P*d_^hyQfc?f!=R=b<$G)#EcwP%dLz?Ts*x@JiR4DmIIx>1yw+CM+fsdk{3vPsL?)YE-g1%`2 zV*Ali*QUVIR}N&9ru&<_n6lS9UHRytJU`BT6WGG{;Rrf)H=J;o+1r;yuj^;7Coy%&YpMZ+GknM zvBUL8y&}(d9Sv${UzUSZd>eT->V&1z@|mmDt!=55r8w`<1(|9g^lJ#cP@9kNuEsZMUHWiQ@V(!w1^55nQSja0qkYd$ z({{JJrlsqAeq~XbGedC}RYe{CO16)0D@A|o^c5c7TNL?iy3+fHw)`!AO?^PUK+jph z<`wFr=|`Nsr?`o0B@`X%++1t)yNdt4F12WJ_vzY0+pdkK6}{b=e$b5; z?9X{?Z_bR+$D7)o)0B%tJs-3^y&`AE)3u?GceOpIw>gK=$HvpKqf@vLD*^$s}LVqe%JL?y5aZH`DAo z_^P^j#p12FMf~6|m9rzRnd{2u_qmYET&+LNZCxKv@)gee!#AJJnKADVYo9HQbhp1wD>uOLv$drIeExP^C+Gq2(xJsTDrTEuf1?WYJ zs?)?s{ZQ9)y}q2nNX5HR_vT)oCreM8>L~AVn9^4mQ8!)XK7UWn4A^#MJ2oeRCV{ z$*2Ej0jd8d-i}9m`_pYbfIq!uTiZ@d=;^)-@R@mKZGKFSiI)PBZjHe26>y_~j|upi zfcpf@#zdRn2LPY(ZfkoCu>Dz2TO;PrbZ-%Gjey?-+%nJEmJL6%o`<+Jr{jh42MzOG z4O`(2tjip%`B~vrUf%u6tG|5h^KJ#;@y6_d`N9L7vU#a`` zr%(E^J@C5aw@Ll3;Gljq>!_u(rFkDfl^S!x?yp$s)J=>I- zo^9*w0rZ#Z^nSR}u+23A4#<0jH|lEgPAtTx{ES=yBz)ProzmF4x`84SH>Cc3ht6%`MMzlIqwtB83AI)QsF}t}S)R_sKI@k5PI29DC z$xz>CUb7^ZQubw-tY_-?%x3VvRMK^QU_VW|u6sBW4%M*yel}n$EO}7s4>#i7FsdFu zc~atw@$y4h@~EUQizmaNCqEiS)%AG`fL|}@n*o0aoIJ_ze*pLtaMlg+cEFziXImxy z65v+g-?!s-8iO*sAUH-$(42TVB7xS@X3Y@8@XuCLt! zdX^vcqZb2j6?i^y4ft9UeiLwM{CH_K;XdH&EckaV_|q2rWeeVA!KpKphT%`K-~|?Z zmIc2A_zSQyf0yI^Mc8VD#r!VEdmhS@{6PHMz-Ixk6!`anuQmB^2Yw%L0G<97yxb3* z{RqFO?)Znm*|!n@FW~=f!v7oiG$e+78T}{1Pa5WLnhEy<|Dpx|iUqF&{w>rG`yz(d zV)AEr?6;*M-rv>@o!Kue{%>1w{1YXv1k<(L&EbY+(2Z8DUbd_`+%mIRfik-}T+>t= zsakO9wN))#kr!%dg(3PU5DJX(9{ygu&-|57gvkoyG~nDRhiH$ zp+{9^Rq^bqmep0LL}R5vq(p}MwJWc@K0&zjs!(c{u15M~E%w*o%J9nC#t*w$$sz$(0US5_+u|h~=wrb1VLxWlb&Is#Z5uT^(+TG_C$dJl=}c zD;pcaEua?xSB8n2VioS!U42az5*eo>j@lm>PdPT1v^3S!%II5-Rw_1_fVOr`jow(R zR@SuCMufxC@bY>z?uKy9s@6u~R$J51fQA!Z(-^L8F*QF%yJR(~Ooeex&8^`oqqv85 zx73hMj}|dRC_}UpNo{Tm%0~1PjtlX>FhUIM4--zqTplnJ9UI4M2jC@ySY!whVxDsy zU?vp!HxtfKlr@AGE6QDjK}Fe1SfVK1gfk(BpwG%I#qZbz{5c`qZ$uwNx|<1svri-b zFNBvU%DL!2Gx1}eMl1(r&Qp~42tx=5`hG&l=eoNe{bJ^PtU&=f$`$43#L=<8M_7z8 z9K#{gcQfGvMfnaP()n{jO;KJF(2s=$<|jx9y6XrR;yVFvC0vB^B1HcGkr46xLb$(2 z2>Sg3K8*aIi}*JnKg&3Qf+R$uIDLfJmzDUnXEkKqN(XUn1c3 z0#*wc5wKCfH3GH?xIw^;0zNF@;{t9LuwB6C1l%RyYXU|Eq+I7XU(BhHuc-nL5CUiV z=zpWYBLZ&_IOmV_e_Y^ z{TB)U27xyUe1pL675I|^-z@N50^cq0sKECKe4oI7CveJzjPH=ZeMkfGiG;9zfln29 zNZ^$MuM>Dg;ExOZNrATuoO2h3w@cu=1XP(1M!e{>sQDn1N@EDIDt!VzvG~={&H=u8xBRbyI2ziw=y7#=3@@ zh%N|PeuE;^O(HsUSEOsa!$imSD&v#+_!8XET__<~nu~H3Wgj5(f$mM8&oUohftBCl zRmldyXEG7MWq6n2-5g%_Btu`s@EDFPmmBboGHC?RjRyinDr>T3pxcN*vhfwVDm^?O zAmfx}j92Bg(-q|tlY>mVbxn3B1gsVOKp08afZt{618<7=dzJ)CgSg%aCi$A|Mi#7T zO*Vri(_5z}^D;ZP@!^pMc#8`yy;7?7zeIGOm3H1NJo7JlJB``LI{P*1+BZ z`)%0!VV{8A3i~2#C+xq&>S45hrhXgte%L2qw=&$v;Rbs@>=UrM+eezRWBLJQ$@BxU z^PtCdPCt;XsQQY@2YsP^r?>OF<4W@k^{h$adU_zu{K=?2p=&`iGwWI=$@aqv9?GPm zOBoo(K#aN*@(^9Ys=6%3=48g{4z|+`Wi?CzlsprTDS|T1gfGQAX=q4)8{k|WGw{E| z`+O7Lf%i*I_Lxm70XpKBlElLR7J|F;PUWV}PjZ2GrDxSKzz7?`B^Cv=z6)74gyE$$(uvVjf* zM6!4&+Cbq>eqxobgk&}-PLpJW^rs>WnuRG#U(2w>rqj~L0eb&?5(qzDhd>e9a*`N8#=b`34Tz8O0j`7yHPXHZI07SAMl4HDe z?z7Jn7Q>Wi5#BjBki&H%x}ZVR2%sC%q1fU^hDT_cn&=4Ux^B2LjZ7c;(mH4G!Q(8` zhcZ0toM8z93E_KbBwb_E^yb#aM(8S1+s8GtxGd#4!zISNF@E-j`?wsp-S&LNZ9m@X z%qx$mU-E6QXgVV@af;e>wxhDzQSIBA>&3sDBkC6&aB)->E*b+}ZAYT6tiS zmW|yh+&7XY_Imep>3c9L(y-Hm>#BFQbM^dJv3Bg=PhEI5jlOq%ol-ENH#=jJ zb~pFvY@8r=48*oMH@W6ir(e+)r(&+1ah^c(OOX->5oKWkzC%d)={wlgHp!B@a_OrmZqDs$a&h14VQMG_6JG+u8n-t$KabI*B z*7jqEzZRS7a8+#oR9XBqVwkG_Xj?zc6P*(eDT{NlCr0(OcD-D&_|WZ3ojq>n+4GeG z)$IVbsH6N)TY3K%^A0V2_O7m116M_V8Td=2pwGFhs6P5ypf&nB_9xtiy#=wu=f)gP zduJCr9iOwJ>|$YEu)h7KQk{3`KYp67hw#i%v=|3y zoW2ruW<|H7PTPQ<8Wuc`24tx zX{g3o#C6j}#=5EWW1L(oDmTs}U=`G*ht2Pp4t8toqiL9)m*7zDoxI+CXZl@fce^$? z@6lI>gON<{WUdW!ic7;Z7XrrDxhuW?#aPv*u7!qqVb_E;;B^Qg?#{e%ZftdDUfBm* z-I;f@`}~VQB<9%pcpWY4nJj;zSNWvyS*Z<@2xV?*`61_M5c+SG*0ip7u2p z1;?`G7W{tz|2iz|nRD##S^R%&!G8vP3hID$P5M^>F9puJCH?`RG>q>M>{sE>I;Q_b z6iGdB)*gzpFQ@6-fj-_j%Oy}VRF+0=OOJ>xrUe(;v*tEJ4 z3o}9~{?&@|s%1^9S7NmU#~{`W)U4~8_MsL;xO~DXnFu7VSr@Uz)#E0-UrR4OTGmv< z1p+~WsIGsOD|r^c6dLiX!wuzFOA@Oe zCeLe;Q|YOpY%_DPmP?4rcvIjX5uSnm3FS`zvj~Bg6M}A;fYcEa?-P*oB+{Qt2>K8q z{J$yS!velZ2)c=EBcS^-Atp+?E`1W#9f^z1$*gncJdcwvwh5_oCiDxOeH3xMuYyjE z-9RBGZb9K*Dsc99qzehi{)p#B7$tR&q$f^#;#UZKiNJ3Zc(uSc2>f1wZx;9#f$tLd zZh`L=_-_T?BXIHs?c9D$-OwzVEU^Y>-@gVW9Y;&Ea*KS>EJX-x4Fd>76U?) z(v5X~pNNii#&1}BG^7(vNXKRR*mr_1uG`!VxY8BZD^Qm3|@6wZkzR?_jNja!L;p z&ou*S)WagF71+CiXwCFnw=ry6YY6M4#zA;`sQ?3gZiZ1E)nj?}h?d(Iwc49}G!6}%du|Rd+nx&It z)6VFORG+bC$>dm3QR^2vA&+c1SdG&DQl7S=HFh|JU9-;0q8bO%Tr`Dq>^EW#P11Ko z)h&5&o32wGto{$gbF4D~X4x^vB0Dzjz+2~ zlZ}1UZ^neg66lVqTKdz(z7tb*S>VlB<|g$~e~+p>T8_Pmt+yC-t`Xer)oj zpGHft_nqxI}KD))~1K}W+pKm~;~#P@Ap`Ri91n~`tQ zFn`Mi(qQ-NO_>NdOUez*yCIM0dtI?F)7WPz`*W6wRbB}&a2S@;zXF=lQ0Wa_riYK+ zj)(<*7lGg;$_K2&exvIBHIl9PVN;P0WH}jOq$||D<-xL!`8~5o`GECGyd3a;Sk@yG|SfR_SiJrQ3IxD~jRKOO-7mI-HgJ75i?>SNH)C5rFOW+-`N zi;2L8_m?gBdltOcf*-cv)Qw8R@Xod1Gk_m}Wjmp~QDO1t9uaByz1&|`Yuww?6t1bO zYHbKFEiNgeq@m-@0$++*H};)j^B6aV)m7bE)6g0=NCr4neWSi5Qbp<^Je9_pCIr*a zTvt;SL2Tis`21dM`0AGi7G6C-xG_!j&2oUrd4RCdAC6ftF!oFhxgiYlkN76O0m+0L zV$<^4+N#EIQ}b#ZEw67`TXm~NXc{E{3@OnV=dUv%4@^aU5ME1&iyK}d#6??zPFxtRaA5rY0MLeY6}-p~0KA?ucqUW9%VWMgNaLieD6Wdeo-WFP9l zgWt#H2H>Rvze4yg5qO=zBLaU|;ExG>r@(g!e4oI7CvdV7r8 zm&PStta3vTmBe!6{21Ab&yTI^0_J@L42rZgMX;=ADOMz+W8Lx_nWRK?^9;JU+(5cT z;#&YceS}uIq0N*JOuggzu*waUNNA-@yeT}Z+z>^08{yA#Vg6WtgjTs>13XfZ8=hkT z$P33Lu#6s_50F!FS$23;oW=|I4a)c4;X#M8G7M z8!j;#(SY?0&fXh$L=Px+u8Xi9u{WrnXYSj2AmW^&RF`PE+7r)ne(A(p;|q^Zat4X5 z+4`T8ot1Uv1)+*QSN4Gj>6B^R`srwcQlFFJOf~MfiIqM7ctqLidx2-wUXMLqZJgOw zI(*w*k$cM>Z=>U?-d$Z8d9b{!qrCc@t&Ygw;O3#1vATkl6d0BvlTLV}fZr65^vKZrSLHX1W2){BUGNe^7kskkMAQ}b8x@jYfBA3@ zVm3qRO#Nm8NazK?sR?D-4E~-R({Fgjfc=0pZ2xm40!aMJ7JPvPza02YuqeLs*&>ug92BZG_0;wRtgYa*^EuTVzaUwmj&f=Y*got z^>8ybq*nT%>^l^`+G}JhW zAxLqc17dsPIK*&?2Lv7xc%{JgI)FdhBk9M=IQ2M^Dve9LSjVXlI!U%2WG~LoEH~>o zwMTp}fo#!5a3HX5Kh#;FHE7ldU$$i9K$p~(&!r?_8qE!?HSC%UnYQ&FUE Kg(L!$bpIb->T1gX literal 0 HcmV?d00001 diff --git a/lib/arm-missing.c b/lib/arm-missing.c new file mode 100644 index 0000000..93f3ef8 --- /dev/null +++ b/lib/arm-missing.c @@ -0,0 +1,16 @@ + +void abort (void) { + while(1); +} + +void *memcpy(void *dst, const void *src, unsigned int len) +{ + const char *s = src; + char *d = dst; + + while (len--) + *d++ = *s++; + + return dst; +} + diff --git a/lib/avr51.S b/lib/avr51.S new file mode 120000 index 0000000..79240b8 --- /dev/null +++ b/lib/avr51.S @@ -0,0 +1 @@ +avr5.S \ No newline at end of file diff --git a/lib/convert/itoa.rob b/lib/convert/itoa.rob index 6ea4a9a..6d63373 100644 --- a/lib/convert/itoa.rob +++ b/lib/convert/itoa.rob @@ -7,10 +7,10 @@ use math.abs; const itoa_chars = "0123456789abcdef"; -void itoa(int16 value, int8 base, char[] result) { +uint16 itoa(int16 value, int8 base, char[] result) { if base < 2 or base > 16 { result[0] = 0; - return; + return 0; } negative = value < 0; @@ -34,6 +34,7 @@ void itoa(int16 value, int8 base, char[] result) { } result[i] = 0; + ret = i; // reverse result j = 0; @@ -45,4 +46,6 @@ void itoa(int16 value, int8 base, char[] result) { j++; i--; } + + return ret; } diff --git a/lib/stm32f1.rob b/lib/stm32f1.rob index 710a90f..e72dafc 100644 --- a/lib/stm32f1.rob +++ b/lib/stm32f1.rob @@ -161,7 +161,7 @@ void __isr_reset() { __do_copy_data(); __system_clock_config(); - main(); + ret = main(); __error_handler(); } diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 0f6150b..05fa252 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -51,6 +51,8 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 if mcu.startswith("stm32f1"): ldflags.append("-Tstm32f1.ld") + ldflags.append(join(stdlib_folder, "arm-eabi-libgcc.a")) + ldflags.append(join(stdlib_folder, "cortex-m3-arm-missing.o")) auxsources += Glob(join(stdlib_folder, "stm32f1.rob")) elif mcu == "atmega328p": ldflags.append("-Tatmega328p.ld") diff --git a/test/atmega1284p/run_avr b/test/atmega1284p/run_avr deleted file mode 120000 index 1dc1d13..0000000 --- a/test/atmega1284p/run_avr +++ /dev/null @@ -1 +0,0 @@ -../../platformio/toolchain-robcmp/bin/run_avr \ No newline at end of file diff --git a/test/debug/platformio.ini b/test/debug/platformio.ini index 26e80a0..f39b390 100644 --- a/test/debug/platformio.ini +++ b/test/debug/platformio.ini @@ -14,4 +14,17 @@ debug_tool = robcmp-ssd1306 [env:native] board = native build_type = debug -upload_protocol = none \ No newline at end of file +upload_protocol = none + +[stm32] +platform = robcmp +board = stm32f1 +upload_protocol = stlink +#board_hardware_spec = specs/stm32.spec + +[env:stm32-release] +extends = stm32 + +[env:stm32-debug] +extends = stm32 +build_type = debug \ No newline at end of file diff --git a/test/stm32f1/Makefile b/test/stm32f1/Makefile index 6045c5b..53c5eb4 100644 --- a/test/stm32f1/Makefile +++ b/test/stm32f1/Makefile @@ -18,7 +18,7 @@ LD_FLAGS+=--gc-sections LD_FLAGS+=--lto=thin DEPENDS=${ROBCMP} Makefile -LINK_DEPENDS=out/stm32f1.o +LINK_DEPENDS=out/stm32f1.o ../../lib/cortex-m3-arm-missing.o ../../lib/arm-eabi-libgcc.a all: out test From 752a9117adfbbc174894160e53732bc91e19d4e6 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 4 Dec 2024 16:32:47 -0300 Subject: [PATCH 096/117] Add stm32f1 test sample with uart. --- test/stm32f1/coseno.rob | 94 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 test/stm32f1/coseno.rob diff --git a/test/stm32f1/coseno.rob b/test/stm32f1/coseno.rob new file mode 100644 index 0000000..ba7bbca --- /dev/null +++ b/test/stm32f1/coseno.rob @@ -0,0 +1,94 @@ + +use intfs.ports; +use arch.stm32.stm32f1; +use convert.itoa; + +use math.abs; +use math.fconsts; +use math.trigonometric; + +precision_digits=1E6; + +values={ + 1.000000,0.999962,0.999848,0.999657,0.999391,0.999048,0.998630,0.998135,0.997564,0.996917,0.996195,0.995396,0.994522,0.993572,0.992546,0.991445,0.990268,0.989016,0.987688,0.986286, + 0.984808,0.983255,0.981627,0.979925,0.978148,0.976296,0.974370,0.972370,0.970296,0.968148,0.965926,0.963630,0.961262,0.958820,0.956305,0.953717,0.951057,0.948324,0.945519,0.942641, + 0.939693,0.936672,0.933580,0.930418,0.927184,0.923880,0.920505,0.917060,0.913545,0.909961,0.906308,0.902585,0.898794,0.894934,0.891007,0.887011,0.882948,0.878817,0.874620,0.870356, + 0.866025,0.861629,0.857167,0.852640,0.848048,0.843391,0.838671,0.833886,0.829038,0.824126,0.819152,0.814116,0.809017,0.803857,0.798636,0.793353,0.788011,0.782608,0.777146,0.771625, + 0.766044,0.760406,0.754710,0.748956,0.743145,0.737277,0.731354,0.725374,0.719340,0.713250,0.707107,0.700909,0.694658,0.688355,0.681998,0.675590,0.669131,0.662620,0.656059,0.649448, + 0.642788,0.636078,0.629320,0.622515,0.615662,0.608761,0.601815,0.594823,0.587785,0.580703,0.573576,0.566406,0.559193,0.551937,0.544639,0.537300,0.529919,0.522498,0.515038,0.507538, + 0.500000,0.492424,0.484810,0.477159,0.469472,0.461749,0.453991,0.446198,0.438371,0.430511,0.422618,0.414693,0.406737,0.398749,0.390731,0.382683,0.374607,0.366501,0.358368,0.350207, + 0.342020,0.333807,0.325568,0.317305,0.309017,0.300706,0.292372,0.284015,0.275637,0.267238,0.258819,0.250380,0.241922,0.233445,0.224951,0.216440,0.207912,0.199368,0.190809,0.182236, + 0.173648,0.165048,0.156434,0.147809,0.139173,0.130526,0.121869,0.113203,0.104528,0.095846,0.087156,0.078459,0.069757,0.061049,0.052336,0.043619,0.034899,0.026177,0.017452,0.008727, + -0.000000,-0.008727,-0.017452,-0.026177,-0.034899,-0.043619,-0.052336,-0.061049,-0.069756,-0.078459,-0.087156,-0.095846,-0.104529,-0.113203,-0.121869,-0.130526,-0.139173,-0.147809,-0.156434,-0.165048, + -0.173648,-0.182235,-0.190809,-0.199368,-0.207912,-0.216440,-0.224951,-0.233445,-0.241922,-0.250380,-0.258819,-0.267238,-0.275637,-0.284015,-0.292372,-0.300706,-0.309017,-0.317305,-0.325568,-0.333807, + -0.342020,-0.350207,-0.358368,-0.366501,-0.374607,-0.382683,-0.390731,-0.398749,-0.406737,-0.414693,-0.422618,-0.430511,-0.438371,-0.446198,-0.453991,-0.461749,-0.469472,-0.477159,-0.484810,-0.492424, + -0.500000,-0.507538,-0.515038,-0.522498,-0.529919,-0.537300,-0.544639,-0.551937,-0.559193,-0.566406,-0.573576,-0.580703,-0.587785,-0.594823,-0.601815,-0.608761,-0.615661,-0.622515,-0.629320,-0.636078, + -0.642788,-0.649448,-0.656059,-0.662620,-0.669131,-0.675590,-0.681998,-0.688354,-0.694658,-0.700909,-0.707107,-0.713250,-0.719340,-0.725374,-0.731354,-0.737277,-0.743145,-0.748956,-0.754710,-0.760406, + -0.766044,-0.771625,-0.777146,-0.782608,-0.788011,-0.793353,-0.798635,-0.803857,-0.809017,-0.814116,-0.819152,-0.824126,-0.829038,-0.833886,-0.838671,-0.843391,-0.848048,-0.852640,-0.857167,-0.861629, + -0.866025,-0.870356,-0.874620,-0.878817,-0.882948,-0.887011,-0.891006,-0.894934,-0.898794,-0.902585,-0.906308,-0.909961,-0.913545,-0.917060,-0.920505,-0.923880,-0.927184,-0.930418,-0.933580,-0.936672, + -0.939693,-0.942642,-0.945519,-0.948324,-0.951056,-0.953717,-0.956305,-0.958820,-0.961262,-0.963630,-0.965926,-0.968148,-0.970296,-0.972370,-0.974370,-0.976296,-0.978148,-0.979925,-0.981627,-0.983255, + -0.984808,-0.986286,-0.987688,-0.989016,-0.990268,-0.991445,-0.992546,-0.993572,-0.994522,-0.995396,-0.996195,-0.996917,-0.997564,-0.998135,-0.998630,-0.999048,-0.999391,-0.999657,-0.999848,-0.999962, + -1.000000,-0.999962,-0.999848,-0.999657,-0.999391,-0.999048,-0.998630,-0.998135,-0.997564,-0.996917,-0.996195,-0.995396,-0.994522,-0.993572,-0.992546,-0.991445,-0.990268,-0.989016,-0.987688,-0.986286, + -0.984808,-0.983255,-0.981627,-0.979925,-0.978148,-0.976296,-0.974370,-0.972370,-0.970296,-0.968148,-0.965926,-0.963630,-0.961262,-0.958820,-0.956305,-0.953717,-0.951057,-0.948324,-0.945519,-0.942641, + -0.939693 + }; + + +int16 run_test(stm32f1 mmcu) { + + degress=float(0.0); + value=int32(0); + result=int32(0); + i = int32(0); + while degress <= 200.0 { + value=int32(values[i]*precision_digits); + result=int32(Cos((float(degress) * FM_PI) / 180.0,18)*precision_digits); + if (abs32(value-result)>10) { + if i!=0 { + return int16(i); + } else { + return 1; + } + } + i=i+1; + degress+=0.5; + } + return 0; +} + +int16 main() { + mmcu = stm32f1(); + serial = mmcu.uart2; + serial.setup(9600); + serial.enable(); + + //led = mmcu.c13; + //led.mode(port_mode.output); + + loop { + start = mmcu.millis(); + + ret = run_test(mmcu); + + // millis is counting downwards, thus start - current + time = start - mmcu.millis(); + + timestr = {'0': 10}; + chars = itoa(time, 10, timestr); + + if ret != 0 { + serial.write_array("FAIL"); + } else { + timestr[chars] = ' '; + timestr[chars+1] = 'm'; + timestr[chars+2] = 's'; + timestr[chars+3] = ' '; + serial.write_array(timestr); + } + serial.write('\r'); + serial.write('\n'); + + } + return 0; +} + From 1d239105bba136e825f7c33dd79e4250ff670bdc Mon Sep 17 00:00:00 2001 From: Vitor Almeida Subhi Date: Mon, 7 Apr 2025 21:58:58 -0300 Subject: [PATCH 097/117] fix(CMAKE): add support to monolithic library systems, such as Arch --- CMakeLists.txt | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f97c7b..23c7d65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,12 +63,19 @@ add_flex_bison_dependency(lexer scanner_main) add_flex_bison_dependency(lexer scanner_use) add_dependencies(robcmp parsers) -llvm_map_components_to_libnames(llvm_libs support core irreader passes - armasmparser armcodegen - avrasmparser avrcodegen - x86asmparser x86codegen) - -target_link_libraries(robcmp ${llvm_libs}) +find_library(LLVM_MONOLITHIC_LIBRARY LLVM HINTS ${LLVM_LIBRARY_DIRS}) + +if (LLVM_MONOLITHIC_LIBRARY) + message(STATUS "LLVM is using monolithic libLLVM.so") + target_link_libraries(robcmp LLVM) +else() + llvm_map_components_to_libnames(llvm_libs support core irreader passes + armasmparser armcodegen + avrasmparser avrcodegen + x86asmparser x86codegen) + + target_link_libraries(robcmp ${llvm_libs}) +endif() set_target_properties(robcmp PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" From 98ab7b89399fdc721ef57677927fabc9bf608276 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 27 Apr 2025 20:30:41 -0300 Subject: [PATCH 098/117] Add support to recursive field access: read, write and method call. --- .gitignore | 2 ++ platformio/examples/blink/platformio.ini | 3 +- platformio/examples/blink/specs/avr.spec | 4 +-- platformio/examples/blink/specs/stm32.spec | 4 +-- platformio/examples/blink/src/main.rob | 9 ++--- src/FunctionCall.cpp | 9 +---- src/FunctionDecl.cpp | 1 + src/Identifier.cpp | 4 ++- src/Identifier.h | 3 +- src/Load.cpp | 40 ++++++++++++++++++---- src/Load.h | 2 ++ src/LoadArray.cpp | 10 ++---- src/Scalar.cpp | 8 ++--- src/UpdateArray.cpp | 7 +++- src/Variable.h | 9 +++++ test/atmega328p/Makefile | 2 ++ test/atmega328p/bssinjcheck.rob | 10 ++---- test/general/intfinternal.rob | 9 +++-- test/general/typesetrecursive.rob | 39 +++++++++++++++++++++ 19 files changed, 119 insertions(+), 56 deletions(-) create mode 100644 test/general/typesetrecursive.rob diff --git a/.gitignore b/.gitignore index 268d16a..294aae5 100644 --- a/.gitignore +++ b/.gitignore @@ -66,6 +66,8 @@ build test/general/out test/general/temp.spec test/atmega328p/out +test/atmega1284p/out +test/stm32f1/out platformio/toolchain-robcmp/bin platformio/toolchain-robcmp/lib platformio/avr-gdb-build diff --git a/platformio/examples/blink/platformio.ini b/platformio/examples/blink/platformio.ini index e1b1e3e..bc99b87 100644 --- a/platformio/examples/blink/platformio.ini +++ b/platformio/examples/blink/platformio.ini @@ -4,6 +4,7 @@ platform = robcmp board = atmega328p upload_protocol = serial board_hardware_spec = specs/avr.spec +debug_tool = robcmp-led [env:avr-release] extends = avr @@ -12,8 +13,6 @@ build_type = release [env:avr-debug] extends = avr build_type = debug -debug_tool = robcmp-led - [stm32] diff --git a/platformio/examples/blink/specs/avr.spec b/platformio/examples/blink/specs/avr.spec index 8e55299..6d156a9 100644 --- a/platformio/examples/blink/specs/avr.spec +++ b/platformio/examples/blink/specs/avr.spec @@ -1,5 +1,5 @@ use arch.avr.avr5mcu; -bind avr5mcu to globals.mmcu singleton; -bind avr5mcu.b5 to globals.led singleton; +bind avr5mcu to mmcu singleton; +bind avr5mcu.b5 to led singleton; diff --git a/platformio/examples/blink/specs/stm32.spec b/platformio/examples/blink/specs/stm32.spec index b562d3d..5303022 100644 --- a/platformio/examples/blink/specs/stm32.spec +++ b/platformio/examples/blink/specs/stm32.spec @@ -1,5 +1,5 @@ use arch.stm32.stm32f1; -bind stm32f1 to globals.mmcu singleton; -bind stm32f1.c13 to globals.led singleton; +bind stm32f1 to mmcu singleton; +bind stm32f1.c13 to led singleton; diff --git a/platformio/examples/blink/src/main.rob b/platformio/examples/blink/src/main.rob index 3da34be..2a8df7e 100644 --- a/platformio/examples/blink/src/main.rob +++ b/platformio/examples/blink/src/main.rob @@ -5,15 +5,10 @@ use intfs.ports; -type globals { - mmcu = mcu(); - led = digitalport(); -} +mmcu = mcu(); +led = digitalport(); int16 main() { - gg = globals(); - mmcu = gg.mmcu; - led = gg.led; led.mode(port_mode.output); diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index e4c7870..0985fa6 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -78,13 +78,8 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock if (ident.isComplex()) { Identifier istem = ident.getStem(); stemSymbol = istem.getSymbol(getScope()); - stem = stemSymbol->getLLVMValue(func); stemdt = stemSymbol->getDataType(); - - // TODO: When accessing a.x.func(), need to load a and gep x - //Load loadstem(ident.getStem()); - //loadstem.setParent(this->parent); - //stem = loadstem.generate(func, block, allocblock); + stem = Load::getRecursiveField(istem, getScope(), func); } vector args; @@ -155,8 +150,6 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock // this parameter if (stemSymbol) { - if (stemSymbol->isPointerToPointer()) - stem = Builder->CreateLoad(stem->getType()->getPointerTo(), stem, "defer"); args.push_back(stem); dataTypes.push_back(stemSymbol->getDataType()); } else if (fsymbol->getThisArgDt() != BuildTypes::undefinedType) { diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index 7feaa43..eac0b86 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -64,6 +64,7 @@ void FunctionBase::addPseudoParameters() { //TODO: There is something better than fix this to Int32? Fix here and in FunctionCall::generate string spname = p->getName() + "." + s; Variable *sp = new Variable(spname, tint32u, p->getLoc()); + sp->setPseudoVar(true); this->parameters->append(sp); // add a pseudo symbol to resolve to pname.s diff --git a/src/Identifier.cpp b/src/Identifier.cpp index 05fc6e9..1531fab 100644 --- a/src/Identifier.cpp +++ b/src/Identifier.cpp @@ -1,7 +1,7 @@ #include "Identifier.h" -Node* Identifier::getSymbol(Node *scope, bool validate) { +Node* Identifier::getSymbol(Node *scope, bool validate, list *symbols) { if (scope == NULL) assert(scope && "scope can't be null!"); @@ -16,6 +16,8 @@ Node* Identifier::getSymbol(Node *scope, bool validate) { if (result) { while (!ss.eof() && result != NULL) { getline(ss, ci, '.'); + if (symbols) + symbols->push_back(result); result = result->findMember(ci); } } diff --git a/src/Identifier.h b/src/Identifier.h index 68889f2..43fe4c0 100644 --- a/src/Identifier.h +++ b/src/Identifier.h @@ -1,6 +1,7 @@ #pragma once +#include #include "Node.h" class Identifier: public SourceLocation { @@ -14,7 +15,7 @@ class Identifier: public SourceLocation { complex = ident.find('.') != string::npos; } - Node* getSymbol(Node *scope, bool validate = true); + Node* getSymbol(Node *scope, bool validate = true, list *symbols = nullptr); string const getFullName() const { return ident; diff --git a/src/Load.cpp b/src/Load.cpp index 5556e6a..3dd7263 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -78,8 +78,11 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl if (bs > 0) v = Builder->CreateLShr(v, ConstantInt::get(req_eq_ty, bs)); return Builder->CreateTrunc(v, buildTypes->llvmType(symbol->getDataType())); - } else { + } else if (symbol->isPseudoVar()) { alloc = symbol->getLLVMValue(stem, func); + } else { + // not pointer and isComplex: two or more recursive levels: a.x.y + alloc = getRecursiveField(ident, getScope(), func); } if (stem->hasQualifier(qvolatile)) @@ -90,11 +93,6 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl // this is needed by injection if (leftValue) leftValue->setScope(stem, true); - - // TODO: When accessing a.x.func(), need to load a and gep x - //Load loadstem(ident.getStem()); - //loadstem.setParent(this->parent); - //stem = loadstem.generate(func, block, allocblock); } else { alloc = symbol->getLLVMValue(func); } @@ -127,3 +125,33 @@ bool Load::isConstExpr() { void Load::setLeftValue(Variable *symbol) { leftValue = symbol; } + +Value* Load::getRecursiveField(Identifier &ident, Node *scope, FunctionImpl *func) { + list symbols; + Node *last = ident.getSymbol(scope, false, &symbols); + symbols.push_back(last); + + Node *first = symbols.front(); + symbols.pop_front(); + Value *alloc = first->getLLVMValue(func); + Type *udt = buildTypes->llvmType(first->getDataType()); + if (first->isPointerToPointer()) { + alloc = Builder->CreateLoad(udt->getPointerTo(), alloc, "deref"); + } + + for(auto &x : symbols) { + Variable *var = dynamic_cast(x); + if (var) { + int gepidx = var->getGEPIndex(); + if (var->isPointerToPointer()) { + alloc = Builder->CreateLoad(udt->getPointerTo(), alloc, "deref"); + } + alloc = Builder->CreateStructGEP(udt, alloc, gepidx, x->getName()); + udt = buildTypes->llvmType(var->getDataType()); + } else { + yyerrorcpp(x->getName() + " is not a variable.", &ident); + break; + } + } + return alloc; +} \ No newline at end of file diff --git a/src/Load.h b/src/Load.h index c86907e..281baef 100644 --- a/src/Load.h +++ b/src/Load.h @@ -34,6 +34,8 @@ class Load: public Node { } Node* getIdentSymbol(bool showError = true); + + static Value* getRecursiveField(Identifier &ident, Node *scope, FunctionImpl *func); friend class SymbolizeTree; }; diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index 05738d1..e731efc 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -3,6 +3,7 @@ #include "LoadArray.h" #include "BuildTypes.h" #include "FunctionImpl.h" +#include "Load.h" LoadArray::LoadArray(const string &i, Node *pos, location_t loc): BaseArrayOper(i, pos, NULL, loc) { addChild(pos); @@ -42,15 +43,10 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al if (ident.isComplex()) { Identifier istem = ident.getStem(); Node *stem = istem.getSymbol(getScope()); - alloc = symbol->getLLVMValue(stem); + alloc = Load::getRecursiveField(ident, getScope(), func); if (stem->hasQualifier(qvolatile)) symbol->setQualifier(qvolatile); - - // TODO: When accessing a.x.func(), need to load a and gep x - //Load loadstem(ident.getStem()); - //loadstem.setParent(this->parent); - //stem = loadstem.generate(func, block, allocblock); } else { alloc = symbol->getLLVMValue(func); } @@ -68,7 +64,7 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al return NULL; } - if (symbol->isPointerToPointer()) { + if (!ident.isComplex() && symbol->isPointerToPointer()) { Type *ty = buildTypes->llvmType(symbol->getDataType())->getPointerTo(); alloc = Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); } diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 9c4e1a3..00f442d 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -4,6 +4,7 @@ #include "BackLLVM.h" #include "HeaderGlobals.h" #include "Pointer.h" +#include "Load.h" Scalar::Scalar(Identifier ident, Node *e) : Variable(ident.getFullName(), ident.getLoc()) { @@ -33,16 +34,11 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc if (reg && buildTypes->isComplex(reg->getDataType())) { alloc = reg->getLLVMValue(NULL); } else { - alloc = symbol->getLLVMValue(stem); + alloc = Load::getRecursiveField(ident, getScope(), func); } if (stem->hasQualifier(qvolatile)) symbol->setQualifier(qvolatile); - - // TODO: When accessing a.x.func(), need to load a and gep x - //Load loadstem(ident.getStem()); - //loadstem.setParent(this->parent); - //stem = loadstem.generate(func, block, allocblock); } // set the allocated left value to: diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index 286ef5d..6302dae 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -2,6 +2,7 @@ #include "UpdateArray.h" #include "FunctionImpl.h" #include "HeaderGlobals.h" +#include "Load.h" UpdateArray::UpdateArray(const string &i, Node *pos, Node *expr, location_t loc): BaseArrayOper(i, pos, NULL, loc) { @@ -31,7 +32,11 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * } Builder->SetInsertPoint(block); - Value *sym = symbol->getLLVMValue(func); + Value *sym = NULL; + if (ident.isComplex()) + sym = Load::getRecursiveField(ident, getScope(), func); + else + sym = symbol->getLLVMValue(func); // sym type can be GlobalVariable or AllocInst Type *ty = NULL; diff --git a/src/Variable.h b/src/Variable.h index 06fee4b..13f0034 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -12,6 +12,7 @@ class Variable: public NamedNode { Identifier ident; int gepIndex = -1; enum PointerMode pointer = pm_unknown; + bool pseudoVar = false; public: Variable(const string &name, location_t loc): NamedNode(name, loc), ident(name, loc) {} @@ -51,4 +52,12 @@ class Variable: public NamedNode { Identifier& getIdent() { return ident; } + + void setPseudoVar(bool value) { + pseudoVar = value; + } + + bool isPseudoVar() { + return pseudoVar; + } }; diff --git a/test/atmega328p/Makefile b/test/atmega328p/Makefile index f171d3d..0776f91 100644 --- a/test/atmega328p/Makefile +++ b/test/atmega328p/Makefile @@ -41,7 +41,9 @@ out/%.ll : %.rob ${DEPENDS} @-./runtest.sh $< $(patsubst %.rob,out/%,$<) out/% : out/%.o ${LINK_DEPENDS} + # exchange here if ld.lld show relocation errors ld.lld ${LD_FLAGS} $^ -o $@ + #avr-ld ${LD_FLAGS} $^ -o $@ test: ${ALL_TT} diff --git a/test/atmega328p/bssinjcheck.rob b/test/atmega328p/bssinjcheck.rob index 22927f4..121f40e 100644 --- a/test/atmega328p/bssinjcheck.rob +++ b/test/atmega328p/bssinjcheck.rob @@ -18,16 +18,10 @@ type container implements intf { uint8 cols() { return buff.cols; } } -type globals { - c = intf(); -} - -bind container to globals.c singleton; +c = intf(); +bind container to c singleton; int8 main() { - a = globals(); - c = a.c; - row = 0u; while row < c.rows() { col = 0u; diff --git a/test/general/intfinternal.rob b/test/general/intfinternal.rob index 815c444..637050f 100644 --- a/test/general/intfinternal.rob +++ b/test/general/intfinternal.rob @@ -22,16 +22,15 @@ type mcu { int16 main() { m = mcu(); - spi = m.spi; - if spi.speed != 0 or spi.lastb != 0 { + if m.spi.speed != 0 or m.spi.lastb != 0 { return 1; } - spi.setup(1000); - spi.write(8); + m.spi.setup(1000); + m.spi.write(8); - if spi.speed != 1000 or spi.lastb != 8 { + if m.spi.speed != 1000 or m.spi.lastb != 8 { return 1; } diff --git a/test/general/typesetrecursive.rob b/test/general/typesetrecursive.rob new file mode 100644 index 0000000..d37ade8 --- /dev/null +++ b/test/general/typesetrecursive.rob @@ -0,0 +1,39 @@ + +type t0 { + a = 0; + int8 callf(int8 x) { + return x+1; + } +} + +type t1 { + c = {0:2}; + m = {{0:2}:2}; + b = t0(); +} + +type t2 { + d = {0:2}; + e = t1(); + + void sett2(t2 tt) { + tt.d[0] = 1; + tt.e.c[0] = 1; + tt.e.m[0][1] = 1; + } +} + +int16 main() { + x = t2(); + x.e.b.a = 0 + x.e.b.callf(-1); + x.sett2(x); + + x.e.c[1] = 1; + x.e.m[1][1] = 1; + + if x.e.b.a == 0 and x.d[0] == 1 and x.e.c[0] == 1 and x.e.c[0] == 1 and + x.e.m[0][1] == 1 and x.e.m[1][1] == 1 { + return 0; + } + return 1; +} From bcca9cc15345d40f96910102ddd4f17480f4bf5b Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 3 May 2025 13:25:12 -0300 Subject: [PATCH 099/117] Improves code generation removing unneeded nested type parent field --- src/BackLLVM.cpp | 7 ++ src/BackLLVM.h | 1 + src/BuildTypes.h | 5 + src/Node.cpp | 9 ++ src/Node.h | 1 + src/PassStripUnusedFields.h | 181 ++++++++++++++++++++++++++++++++++++ src/Program.cpp | 5 +- src/Scalar.h | 11 +++ src/UndefInit.h | 21 +++++ src/UserType.cpp | 35 +++++-- src/Variable.cpp | 9 +- 11 files changed, 272 insertions(+), 13 deletions(-) create mode 100644 src/PassStripUnusedFields.h create mode 100644 src/UndefInit.h diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index 7f4007b..a318135 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -27,6 +27,7 @@ #include #include "BackLLVM.h" +#include "PassStripUnusedFields.h" using namespace llvm; @@ -46,6 +47,7 @@ unsigned int dataAddrSpace = 0; // Injections map injections; +set unusedParents; enum SupportedTargets currentTargetId; extern char *build_outputfilename; @@ -203,6 +205,11 @@ int print_llvm_ir(char opt_level) { UpgradeDebugInfo(*mainmodule); + // Run passes that need unoptimized code + auto modulePassManagerUnopt = ModulePassManager(); + modulePassManagerUnopt.addPass(StripUnusedParentFieldsPass()); + modulePassManagerUnopt.run(*mainmodule, moduleAnalysisManager); + ModulePassManager modulePassManager; if (ol == OptimizationLevel::O0) modulePassManager = passBuilder.buildO0DefaultPipeline(ol); diff --git a/src/BackLLVM.h b/src/BackLLVM.h index 610b1a3..82e8ea5 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -46,3 +46,4 @@ const TargetInfo& currentTarget(); class Variable; extern map injections; +extern set unusedParents; diff --git a/src/BuildTypes.h b/src/BuildTypes.h index beba83c..b546d50 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -100,7 +100,12 @@ class BuildTypes { } void updateName(DataType tid, const string& name) { + namedTypes.erase(tinfo[tid].name); tinfo[tid].name = name; + namedTypes[name] = tid; + StructType *st = dyn_cast(llvmType(tid)); + if (st) + st->setName(name); } const unsigned bitWidth(DataType tid) { diff --git a/src/Node.cpp b/src/Node.cpp index b197563..5ba6023 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -58,6 +58,15 @@ void Node::addChild(Node *n, bool prepend) { node_children.push_back(n); } +void Node::removeChild(Node *n) { + NamedNode *nn = dynamic_cast(n); + if (nn) + symbols.erase(nn->getName()); + auto it = find(node_children.begin(), node_children.end(), n); + if (*it) + node_children.erase(it); +} + void Node::addSymbol(NamedNode *nm) { addSymbol(nm->getName(), nm); } diff --git a/src/Node.h b/src/Node.h index 8aff1eb..985a5df 100644 --- a/src/Node.h +++ b/src/Node.h @@ -56,6 +56,7 @@ class Node : public SourceLocation { virtual Node* findMember(const string& name); void addChild(Node *n, bool prepend = false); + void removeChild(Node *n); virtual map const& getSymbols(); diff --git a/src/PassStripUnusedFields.h b/src/PassStripUnusedFields.h new file mode 100644 index 0000000..b504573 --- /dev/null +++ b/src/PassStripUnusedFields.h @@ -0,0 +1,181 @@ +#pragma once + +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Type.h" + +#include "BackLLVM.h" + +using namespace llvm; +using namespace std; + + +struct StripUnusedParentFieldsPass : PassInfoMixin { + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { + map modifiedTypes; + + for(auto& structName : unusedParents) { + StructType *oldTy = StructType::getTypeByName(M.getContext(), structName); + + if (!oldTy || oldTy->isOpaque() || oldTy->getNumElements() == 0) + continue; + + oldTy->setName(oldTy->getName().str() + ".discard"); + + // Prepare new element list without parent (last field) + ArrayRef elements = oldTy->elements(); + std::vector newElements(elements.begin(), elements.end() - 1); + + // Create the new StructType + StructType *newTy = StructType::create(oldTy->getContext(), newElements, + structName, oldTy->isPacked()); + + modifiedTypes[oldTy] = newTy; + } + + // identify structs that depends on the old type + for (StructType *S : M.getIdentifiedStructTypes()) { + if (S->isOpaque()) + continue; + + bool changed = false; + vector newElements; + for(int i = 0; i < S->getNumElements(); i++) { + auto element = modifiedTypes.find(S->getElementType(i)); + if (element != modifiedTypes.end()) { + newElements.push_back(element->second); + changed = true; + } else { + newElements.push_back(S->getElementType(i)); + } + } + + // change old structure name and create a new one + if (changed) { + string name = S->getName().str(); + S->setName(S->getName().str() + ".discard"); + StructType *newTy = StructType::create(S->getContext(), newElements, + name, S->isPacked()); + modifiedTypes[S] = newTy; + } + } + + for(auto& [oldty, newty] : modifiedTypes) { + replaceGlobals(M, oldty, newty); + replaceGEP(M, oldty, newty); + } + + return PreservedAnalyses::all(); + } + + void replaceGlobals(Module &M, Type *oldty, Type *newty) { + + // Find globals of the old type + std::vector toReplace; + for (GlobalVariable &GV : M.globals()) { + if (GV.getValueType() == oldty) { + toReplace.push_back(&GV); + } + } + + for (GlobalVariable *GV : toReplace) { + auto *newGV = new GlobalVariable(M, newty, GV->isConstant(), GV->getLinkage(), + GV->getInitializer(), GV->getName(), nullptr, GV->getThreadLocalMode(), GV->getAddressSpace() + ); + GV->replaceAllUsesWith(newGV); + GV->eraseFromParent(); + } + } + + void replaceGEP(Module &M, Type *oldty, Type *newty) { + std::vector toReplace; + //std::vector toReplaceStore; + std::vector toReplaceReturn; + + // Collect all GEPs using oldty + for (Function &F : M) { + for (BasicBlock &BB : F) { + for (Instruction &I : BB) { + if (auto *GEP = dyn_cast(&I)) { + if (GEP->getSourceElementType() == oldty) { + toReplace.push_back(GEP); + } + } /*else if (auto *Store = dyn_cast(&I)) { + auto *val = Store->getPointerOperand(); + if (isa(val)) { + auto *GEP = cast(val); + if (GEP->getSourceElementType() == oldty) { + GEP->print(errs()); + errs() << "\n"; + Store->print(errs()); + errs() << "\n"; + //toReplaceStore.push_back(Store); + } + } + }*/ + else if (auto *Return = dyn_cast(&I)) { + auto *val = Return->getReturnValue(); + if (!val) continue; + if (auto *CE = dyn_cast(val)) { + if (CE->getOpcode() == Instruction::GetElementPtr) { + const auto *GO = cast(CE); + if (GO->getSourceElementType() == oldty) { + toReplaceReturn.push_back(Return); + } + } + } + } + } + } + } + + auto createNewGEP = [](IRBuilder<> &B, Type *newty, GetElementPtrInst *GEP) { + Value *ptr = GEP->getPointerOperand(); + SmallVector indices(GEP->idx_begin(), GEP->idx_end()); + Value *newGEP = B.CreateGEP(newty, ptr, indices); + newGEP->setName(GEP->getName()); + return newGEP; + }; + + for (GetElementPtrInst *GEP : toReplace) { + IRBuilder<> B(GEP); + if (GEP->getSourceElementType() == nullptr) + continue; + auto *newGEP = createNewGEP(B, newty, GEP); + GEP->replaceAllUsesWith(newGEP); + GEP->eraseFromParent(); + } + + /*for (StoreInst *Store : toReplaceStore) { + IRBuilder<> B(Store); + auto *val = Store->getPointerOperand(); + auto *GEP = cast(val); + auto *newGEP = createNewGEP(B, newty, GEP); + + auto *newStore = B.CreateStore(Store->getValueOperand(), newGEP, Store->isVolatile()); + Store->replaceAllUsesWith(newStore); + Store->eraseFromParent(); + }*/ + + for (ReturnInst *Return : toReplaceReturn) { + IRBuilder<> B(Return); + + auto *val = Return->getReturnValue(); + auto *CE = dyn_cast(val); + const auto *GO = cast(CE); + + Value *ptr = CE->getOperand(0); + SmallVector indices(GO->idx_begin(), GO->idx_end()); + Value *newGEP = B.CreateGEP(newty, ptr, indices); + newGEP->setName(GO->getName()); + + auto *newReturn = B.CreateRet(newGEP); + Return->replaceAllUsesWith(newReturn); + Return->eraseFromParent(); + } + } +}; diff --git a/src/Program.cpp b/src/Program.cpp index 6c0660e..fc96946 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -5,7 +5,7 @@ #include "PropagateTypes.h" #include "PrintAstVisitor.h" #include "BackLLVM.h" -#include "ZeroInit.h" +#include "UndefInit.h" #include "Return.h" #include "Load.h" #include "BuildTypes.h" @@ -121,7 +121,7 @@ void Program::generateInjectionSetup(SourceLocation *sl) { Node *var = findSymbol(globalVarName); if (!var) { // alloc the global var - ZeroInit *nc = new ZeroInit(injectType->getDataType(), loc); + UndefInit *nc = new UndefInit(injectType->getDataType(), loc); Scalar *svar = new Scalar(globalVarName, nc); svar->setScope(this); addSymbol(svar); @@ -251,6 +251,7 @@ void Program::generate() { // create a function named :global_init to init global vars by calling their constructors global_init = Function::Create(global_init_type, Function::ExternalLinkage, codeAddrSpace, "__globals_init", mainmodule); + global_init->addFnAttr(Attribute::AlwaysInline); global_init->setCallingConv(CallingConv::C); // clear debug information as we will move instructions to __globals_init diff --git a/src/Scalar.h b/src/Scalar.h index 898cdd8..dc5649b 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -5,6 +5,9 @@ #include "Visitor.h" class Scalar: public Variable { +private: + bool used = false; + public: Scalar(const string& ident, Node *e); @@ -31,5 +34,13 @@ class Scalar: public Variable { return v.visit(*this); } + void setUsed(bool value) { + used = value; + } + + bool isUsed() { + return used; + } + friend class SymbolizeTree; }; diff --git a/src/UndefInit.h b/src/UndefInit.h new file mode 100644 index 0000000..ce07549 --- /dev/null +++ b/src/UndefInit.h @@ -0,0 +1,21 @@ + +#pragma once + +#include "BuildTypes.h" +#include "HeaderGlobals.h" +#include "Node.h" + +class UndefInit: public Node { +public: + UndefInit(DataType dt, location_t loc): Node(loc) { + this->dt = dt; + } + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + return UndefValue::get(buildTypes->llvmType(dt)); + } + + virtual bool isConstExpr() override { + return true; + } +}; diff --git a/src/UserType.cpp b/src/UserType.cpp index a20fd0c..19f5195 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -124,7 +124,7 @@ bool UserType::createDataType() { } bitWidth = startBit; - StructType *uttype = StructType::create(global_context, ArrayRef(elements), getName()); + StructType *uttype = StructType::create(global_context, ArrayRef(elements), getTypeName()); dt = buildTypes->addDataType(this, uttype, bitWidth); if (parent) buildTypes->setInternal(dt, true); @@ -192,6 +192,28 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all } } + // generate functions + for(auto & [key, stmt] : getSymbols()) { + if (FunctionImpl *f = dynamic_cast(stmt)) { + f->generate(func, block, allocblock); + } + } + + // check if parent was not used and remove it + bool parentUsed = true; + if (parent) { + NamedNode *sparent = symbols["parent"]; + Scalar *parentscalar = dynamic_cast(sparent); + parentUsed = parentscalar && parentscalar->isUsed(); + if (!parentUsed && parentscalar) { + auto parentf = find(fields.begin(), fields.end(), parentscalar); + if (*parentf) + fields.erase(parentf); + removeChild(parentscalar); + unusedParents.insert(getTypeName()); + } + } + // generate init function/constructor FunctionParams *fp = new FunctionParams(); FunctionBase *finit; @@ -203,7 +225,9 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all } finit->addThisArgument(dt); if (parent) { - finit->addParentArgument(parent->getDataType()); + if (parentUsed) { + finit->addParentArgument(parent->getDataType()); + } // nested user types can be inlined in the parent init finit->getAttributes()->addAttribute(fa_inline); } @@ -212,13 +236,6 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all finit->setConstructor(true); finit->generate(func, block, allocblock); - // generate functions - for(auto & [key, stmt] : getSymbols()) { - if (FunctionImpl *f = dynamic_cast(stmt)) { - f->generate(func, block, allocblock); - } - } - addChild(finit); addSymbol(finit); return NULL; diff --git a/src/Variable.cpp b/src/Variable.cpp index 8c82824..5c85736 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -1,6 +1,7 @@ #include "Variable.h" #include "FunctionImpl.h" +#include "Scalar.h" Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { int gepidx = getGEPIndex(); @@ -26,7 +27,10 @@ Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { // Thus, we access parent in _this and gep the field DataType parentDt = this->getScope()->getDataType(); Type *parentTy = buildTypes->llvmType(parentDt); - int idxParentInThis = static_cast(symbols["parent"])->getGEPIndex(); + NamedNode *parent = symbols["parent"]; + Scalar *parentscalar = dynamic_cast(parent); + parentscalar->setUsed(true); + int idxParentInThis = static_cast(parent)->getGEPIndex(); Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, idxParentInThis, "gepthis"); Value *parentptr = Builder->CreateLoad(parentTy->getPointerTo(), parentAlloc, "derefparent"); return Builder->CreateStructGEP(parentTy, parentptr, gepidx, "gep" + getName()); @@ -37,7 +41,8 @@ Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { Node *nestedType = stem->getScope(); auto nestedSymbols = nestedType->getSymbols(); Node *parentField = nestedSymbols.find("parent")->second; - Variable *parentFieldVar = static_cast(parentField); + Scalar *parentFieldVar = dynamic_cast(parentField); + parentFieldVar->setUsed(true); assert(parentField && "Parent field must exists and have a gepIndex!"); int idxParentInThis = parentFieldVar->getGEPIndex(); Type *parentTy = buildTypes->llvmType(parentFieldVar->getDataType()); From 963043ec3f8d32cb1bebc86653a0d3d608b9a983 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 3 May 2025 17:23:11 -0300 Subject: [PATCH 100/117] Move semantic related files to a specific folder in src. --- CMakeLists.txt | 1 + src/Array.cpp | 4 ++-- src/BackLLVM.cpp | 2 +- src/BinaryOp.h | 2 +- src/BitCast.h | 2 +- src/CmpOp.h | 2 +- src/Enum.h | 2 +- src/FunctionCall.cpp | 4 ++-- src/FunctionImpl.cpp | 2 +- src/Header.h | 2 +- src/If.cpp | 2 +- src/Load.h | 2 +- src/Matrix.cpp | 2 +- src/MemCopy.h | 2 +- src/Node.cpp | 2 +- src/Program.cpp | 10 ++++++---- src/Return.h | 2 +- src/Scalar.h | 2 +- src/UpdateArray.h | 2 +- src/UserType.cpp | 4 ++-- src/{ => passes}/PassStripUnusedFields.h | 0 src/{ => semantic}/PrintAstVisitor.cpp | 0 src/{ => semantic}/PrintAstVisitor.h | 0 src/{ => semantic}/PropagateTypes.cpp | 0 src/{ => semantic}/PropagateTypes.h | 2 +- src/{ => semantic}/RecursiveVisitor.cpp | 0 src/{ => semantic}/RecursiveVisitor.h | 0 src/{ => semantic}/Semantic.cpp | 0 src/{ => semantic}/Semantic.h | 0 src/{ => semantic}/SymbolizeTree.h | 2 +- src/{ => semantic}/Visitor.h | 0 31 files changed, 30 insertions(+), 27 deletions(-) rename src/{ => passes}/PassStripUnusedFields.h (100%) rename src/{ => semantic}/PrintAstVisitor.cpp (100%) rename src/{ => semantic}/PrintAstVisitor.h (100%) rename src/{ => semantic}/PropagateTypes.cpp (100%) rename src/{ => semantic}/PropagateTypes.h (99%) rename src/{ => semantic}/RecursiveVisitor.cpp (100%) rename src/{ => semantic}/RecursiveVisitor.h (100%) rename src/{ => semantic}/Semantic.cpp (100%) rename src/{ => semantic}/Semantic.h (100%) rename src/{ => semantic}/SymbolizeTree.h (98%) rename src/{ => semantic}/Visitor.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 23c7d65..b7d0622 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ add_definitions(${LLVM_DEFINITIONS_LIST}) file(GLOB robcmp_SRC CONFIGURE_DEPENDS "src/*.cpp" + "src/**/*.cpp" ) flex_target(lexer "${CMAKE_CURRENT_SOURCE_DIR}/src/Language.l" "${CMAKE_BINARY_DIR}/Language_l.cpp") diff --git a/src/Array.cpp b/src/Array.cpp index 699d261..399dbfa 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -1,11 +1,11 @@ #include "Array.h" #include "ArrayElements.h" #include "BackLLVM.h" -#include "Visitor.h" #include "FunctionImpl.h" #include "NamedConst.h" #include "BinaryOp.h" -#include "PropagateTypes.h" +#include "semantic/PropagateTypes.h" +#include "semantic/Visitor.h" Array::Array(const string& n, ArrayElements *aes, location_t loc) : Variable(n, loc), elements(aes) { NamedConst *nc = new NamedConst("size", getNodeForUIntConst(aes->getArraySize(), loc)); diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index a318135..f557522 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -27,7 +27,7 @@ #include #include "BackLLVM.h" -#include "PassStripUnusedFields.h" +#include "passes/PassStripUnusedFields.h" using namespace llvm; diff --git a/src/BinaryOp.h b/src/BinaryOp.h index 068679a..ad89640 100644 --- a/src/BinaryOp.h +++ b/src/BinaryOp.h @@ -2,7 +2,7 @@ #pragma once #include "Node.h" -#include "Visitor.h" +#include "semantic/Visitor.h" class BinaryOp: public Node { private: diff --git a/src/BitCast.h b/src/BitCast.h index bd79566..bf3a891 100644 --- a/src/BitCast.h +++ b/src/BitCast.h @@ -1,7 +1,7 @@ #pragma once #include "Node.h" -#include "Visitor.h" +#include "semantic/Visitor.h" class BitCast: public Node { private: diff --git a/src/CmpOp.h b/src/CmpOp.h index 16a7ce8..23e52ef 100644 --- a/src/CmpOp.h +++ b/src/CmpOp.h @@ -1,7 +1,7 @@ #pragma oncd #include "Node.h" -#include "Visitor.h" +#include "semantic/Visitor.h" class CmpOp: public Node { private: diff --git a/src/Enum.h b/src/Enum.h index 423b22b..d3d54be 100644 --- a/src/Enum.h +++ b/src/Enum.h @@ -2,7 +2,7 @@ #pragma once #include "Node.h" -#include "Visitor.h" +#include "semantic/Visitor.h" class Enum : public NamedNode { private: diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 0985fa6..82fcc1e 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -3,13 +3,13 @@ #include "FunctionDecl.h" #include "FunctionImpl.h" #include "HeaderGlobals.h" -#include "PropagateTypes.h" #include "Load.h" -#include "Visitor.h" #include "BackLLVM.h" #include "UserType.h" #include "Program.h" #include "Interface.h" +#include "semantic/PropagateTypes.h" +#include "semantic/Visitor.h" extern Program *program; diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index 7bcc8ca..ef790c9 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -1,6 +1,6 @@ #include "FunctionImpl.h" -#include "Visitor.h" #include "BackLLVM.h" +#include "semantic/Visitor.h" FunctionImpl::FunctionImpl(DataType dt, string name, FunctionParams *fp, vector &&stmts, location_t loc, location_t ef, bool constructor) : diff --git a/src/Header.h b/src/Header.h index 751916a..0a09466 100644 --- a/src/Header.h +++ b/src/Header.h @@ -36,7 +36,7 @@ #include "Program.h" #include "Return.h" #include "Scalar.h" -#include "Semantic.h" +#include "semantic/Semantic.h" #include "StringConst.h" #include "UpdateArray.h" #include "UpdateMatrix.h" diff --git a/src/If.cpp b/src/If.cpp index 3f6101b..110bd5f 100644 --- a/src/If.cpp +++ b/src/If.cpp @@ -1,7 +1,7 @@ #include "If.h" #include "FunctionImpl.h" -#include "Visitor.h" +#include "semantic/Visitor.h" If::If(Node *e, vector &&tst, location_t loc): Node(loc), expr(e) { addChild(expr); diff --git a/src/Load.h b/src/Load.h index 281baef..7d77b2e 100644 --- a/src/Load.h +++ b/src/Load.h @@ -2,7 +2,7 @@ #include "Node.h" #include "Identifier.h" -#include "Visitor.h" +#include "semantic/Visitor.h" class Load: public Node { private: diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 3cf471e..14b746c 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -1,9 +1,9 @@ #include "Matrix.h" #include "Array.h" -#include "Visitor.h" #include "BackLLVM.h" #include "FunctionImpl.h" #include "NamedConst.h" +#include "semantic/Visitor.h" Matrix::Matrix(const char *n, MatrixElements *me, location_t loc) : Variable(n, loc), melements(me) { NamedConst *rows = new NamedConst("rows", getNodeForUIntConst(me->getRowCount(), this->getLoc())); diff --git a/src/MemCopy.h b/src/MemCopy.h index d41c461..ad1dde1 100644 --- a/src/MemCopy.h +++ b/src/MemCopy.h @@ -3,7 +3,7 @@ #include "Node.h" #include "Variable.h" -#include "Visitor.h" +#include "semantic/Visitor.h" class MemCopy: public Node { private: diff --git a/src/Node.cpp b/src/Node.cpp index 5ba6023..c3f8011 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -4,7 +4,7 @@ #include "Int16.h" #include "Int32.h" #include "Int64.h" -#include "Visitor.h" +#include "semantic/Visitor.h" Node::~Node() {} diff --git a/src/Program.cpp b/src/Program.cpp index fc96946..690326a 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -1,16 +1,18 @@ + +#include #include "Program.h" #include "FunctionImpl.h" #include "HeaderGlobals.h" -#include "SymbolizeTree.h" -#include "PropagateTypes.h" -#include "PrintAstVisitor.h" #include "BackLLVM.h" #include "UndefInit.h" #include "Return.h" #include "Load.h" #include "BuildTypes.h" #include "ConstructorCall.h" -#include +#include "semantic/PrintAstVisitor.h" +#include "semantic/PropagateTypes.h" +#include "semantic/SymbolizeTree.h" +#include "semantic/IdentifyVirtualDispatch.h" Program::Program() : Node({0,0,0,0}) { mainmodule = new Module(this->getFile(), global_context); diff --git a/src/Return.h b/src/Return.h index 294b075..7490b77 100644 --- a/src/Return.h +++ b/src/Return.h @@ -2,7 +2,7 @@ #pragma once #include "Node.h" -#include "Visitor.h" +#include "semantic/Visitor.h" class Return: public Node { public: diff --git a/src/Scalar.h b/src/Scalar.h index dc5649b..fbe4635 100644 --- a/src/Scalar.h +++ b/src/Scalar.h @@ -2,7 +2,7 @@ #pragma once #include "Variable.h" -#include "Visitor.h" +#include "semantic/Visitor.h" class Scalar: public Variable { private: diff --git a/src/UpdateArray.h b/src/UpdateArray.h index 12b902d..21c18cc 100644 --- a/src/UpdateArray.h +++ b/src/UpdateArray.h @@ -3,7 +3,7 @@ #include "Node.h" #include "LoadArray.h" -#include "Visitor.h" +#include "semantic/Visitor.h" class UpdateArray: public BaseArrayOper { protected: diff --git a/src/UserType.cpp b/src/UserType.cpp index 19f5195..836574f 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -9,14 +9,14 @@ #include "FunctionParams.h" #include "ConstructorCall.h" #include "Variable.h" -#include "Visitor.h" #include "Enum.h" #include "Load.h" #include "BackLLVM.h" #include "Int8.h" #include "Scalar.h" #include "Program.h" -#include "PropagateTypes.h" +#include "semantic/PropagateTypes.h" +#include "semantic/Visitor.h" class ParentScalar: public Scalar { public: diff --git a/src/PassStripUnusedFields.h b/src/passes/PassStripUnusedFields.h similarity index 100% rename from src/PassStripUnusedFields.h rename to src/passes/PassStripUnusedFields.h diff --git a/src/PrintAstVisitor.cpp b/src/semantic/PrintAstVisitor.cpp similarity index 100% rename from src/PrintAstVisitor.cpp rename to src/semantic/PrintAstVisitor.cpp diff --git a/src/PrintAstVisitor.h b/src/semantic/PrintAstVisitor.h similarity index 100% rename from src/PrintAstVisitor.h rename to src/semantic/PrintAstVisitor.h diff --git a/src/PropagateTypes.cpp b/src/semantic/PropagateTypes.cpp similarity index 100% rename from src/PropagateTypes.cpp rename to src/semantic/PropagateTypes.cpp diff --git a/src/PropagateTypes.h b/src/semantic/PropagateTypes.h similarity index 99% rename from src/PropagateTypes.h rename to src/semantic/PropagateTypes.h index 0063f78..27ad9ac 100644 --- a/src/PropagateTypes.h +++ b/src/semantic/PropagateTypes.h @@ -2,7 +2,6 @@ #pragma once #include "Node.h" -#include "Visitor.h" #include "UserType.h" #include "Matrix.h" #include "Array.h" @@ -16,6 +15,7 @@ #include "Load.h" #include "MemCopy.h" #include "BitCast.h" +#include "semantic/Visitor.h" class CoercionBase: public Node { protected: diff --git a/src/RecursiveVisitor.cpp b/src/semantic/RecursiveVisitor.cpp similarity index 100% rename from src/RecursiveVisitor.cpp rename to src/semantic/RecursiveVisitor.cpp diff --git a/src/RecursiveVisitor.h b/src/semantic/RecursiveVisitor.h similarity index 100% rename from src/RecursiveVisitor.h rename to src/semantic/RecursiveVisitor.h diff --git a/src/Semantic.cpp b/src/semantic/Semantic.cpp similarity index 100% rename from src/Semantic.cpp rename to src/semantic/Semantic.cpp diff --git a/src/Semantic.h b/src/semantic/Semantic.h similarity index 100% rename from src/Semantic.h rename to src/semantic/Semantic.h diff --git a/src/SymbolizeTree.h b/src/semantic/SymbolizeTree.h similarity index 98% rename from src/SymbolizeTree.h rename to src/semantic/SymbolizeTree.h index ade24c7..08fd8a4 100644 --- a/src/SymbolizeTree.h +++ b/src/semantic/SymbolizeTree.h @@ -2,7 +2,6 @@ #pragma once #include "Node.h" -#include "Visitor.h" #include "UserType.h" #include "Matrix.h" #include "Array.h" @@ -10,6 +9,7 @@ #include "FunctionImpl.h" #include "Scalar.h" #include "Enum.h" +#include "semantic/Visitor.h" class SymbolizeTree: public Visitor { public: diff --git a/src/Visitor.h b/src/semantic/Visitor.h similarity index 100% rename from src/Visitor.h rename to src/semantic/Visitor.h From 84933bc9a026b4ca07ecb061d73c68fc5a4e0734 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 3 May 2025 17:36:25 -0300 Subject: [PATCH 101/117] Conditionally add typeid fields to types that really need it, improving on code size. --- src/Dispatch.cpp | 11 +++ src/Dispatch.h | 7 ++ src/FunctionCall.h | 4 ++ src/Program.cpp | 7 +- src/UserType.cpp | 91 ++++++++++++++---------- src/UserType.h | 15 ++-- src/semantic/IdentifyVirtualDispatch.cpp | 44 ++++++++++++ src/semantic/IdentifyVirtualDispatch.h | 13 ++++ src/semantic/PropagateTypes.cpp | 20 +++--- 9 files changed, 156 insertions(+), 56 deletions(-) create mode 100644 src/semantic/IdentifyVirtualDispatch.cpp create mode 100644 src/semantic/IdentifyVirtualDispatch.h diff --git a/src/Dispatch.cpp b/src/Dispatch.cpp index 36cb4f2..893e4c9 100644 --- a/src/Dispatch.cpp +++ b/src/Dispatch.cpp @@ -7,10 +7,21 @@ #include "Scanner.h" void Dispatch::addDataTypeImplementation(DataType base, DataType impl) { + //errs() << "addDataTypeImplementation: " << buildTypes->name(base) << " -> " << buildTypes->name(impl) << "\n"; set& impls = dispatchHash[base]; impls.insert(impl); } +int Dispatch::getImplementationCount(DataType intf) { + if (dispatchHash.find(intf) != dispatchHash.end()) + return dispatchHash[intf].size(); + return 0; +} + +void Dispatch::addIntfInvocation(DataType intf) { + intfsInvoked.insert(intf); +} + void Dispatch::generateDispatchFunctions(Node *scope) { /* for each base type, generates a function: diff --git a/src/Dispatch.h b/src/Dispatch.h index 29804bd..5d8cdc5 100644 --- a/src/Dispatch.h +++ b/src/Dispatch.h @@ -10,9 +10,16 @@ class Dispatch { protected: map> dispatchHash; + set intfsInvoked; public: void addDataTypeImplementation(DataType base, DataType impl); + void addIntfInvocation(DataType intf); void generateDispatchFunctions(Node *scope); void notifyInterface(DataType intf); + int getImplementationCount(DataType intf); + + bool isIntfInvoked(DataType intf) { + return (intfsInvoked.find(intf) != intfsInvoked.end()); + } }; diff --git a/src/FunctionCall.h b/src/FunctionCall.h index 040c8a3..bce1e1d 100644 --- a/src/FunctionCall.h +++ b/src/FunctionCall.h @@ -37,4 +37,8 @@ class FunctionCall: public Node { const string getName() const override { return ident.getFullName(); } + + Identifier& getIdent() { + return ident; + } }; diff --git a/src/Program.cpp b/src/Program.cpp index 690326a..503aeff 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -210,11 +210,14 @@ void Program::doSemanticAnalysis() { SymbolizeTree st; st.visit(*this); + IdentifyVirtualDispatch ivd; + ivd.visit(*this); + PropagateTypes pt; pt.visit(*this); - + buildTypes->generateDebugInfoForTypes(); - + /*std::fstream fs; fs.open("ast", std::fstream::out); PrintAstVisitor(fs).visit(*this); diff --git a/src/UserType.cpp b/src/UserType.cpp index 836574f..02cef05 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -45,58 +45,75 @@ void UserType::setNestedParent() { } } +void UserType::createTempDataType() { + if (dt == BuildTypes::undefinedType) { + // create an undefined type to use in recursive subtypes + dt = buildTypes->getType(getTypeName(), true); + } +} + bool UserType::createDataType() { - - if (dt != BuildTypes::undefinedType) + + if (buildTypes->isDefined(dt)) return true; - - // create an undefined type to use in recursive subtypes - dt = buildTypes->getType(getTypeName(), true); - std::vector elements; int idx = 0; unsigned startBit = 0; + std::vector elements; // if needed, add typeid as the first field UInt8 *typeId = NULL; if (implements.size() > 0) { - typeId = new UInt8(0, getLoc()); // zero is changed below - Scalar *sc = new Scalar("typeid", typeId); - sc->setScope(this); - addChild(sc, true); - addSymbol(sc); + // the typeid field is needed if any implemented interface is unbound + // (not injected) and at least one of its methods was invoked + bool intfInvoked = false; + for(auto &intf : implements) { + DataType dt = buildTypes->getType(intf); + intfInvoked |= program->getDispatcher()->isIntfInvoked(dt); + } + + if (intfInvoked) { + typeId = new UInt8(0, getLoc()); // zero is changed below + Scalar *sc = new Scalar("typeid", typeId); + sc->setScope(this); + addChild(sc, true); + addSymbol(sc); + } } + // Process nested types + // They can add child to this instance, so we first identify nested UserTypes + vector nested; for(auto child : this->children()) { - Variable *v = NULL; - - if (UserType *ut = dynamic_cast(child)) { - // internal user type: - // add a var in the internal type to store a reference to his parent - ParentScalar *s = new ParentScalar(dt, ut->getLoc()); - s->setScope(ut); - ut->addChild(s); - ut->addSymbol(s); - ut->createDataType(); - - // create a new var in the parent to store the intf implementation - ConstructorCall *cc = new ConstructorCall(ut->getTypeName(), ut->getLoc()); - v = new Scalar(ut->getName(), cc); - v->dt = ut->getDataType(); - cc->setScope(v); - v->setScope(this); - addChild(v); - - // replace the v->getName() symbol with its var and - symbols[v->getName()] = v; + if (UserType *ut = dynamic_cast(child)) + nested.push_back(ut); + } + for(auto ut : nested) { + // internal user type: + // add a var in the internal type to store a reference to his parent + ParentScalar *s = new ParentScalar(dt, ut->getLoc()); + s->setScope(ut); + ut->addChild(s); + ut->addSymbol(s); + ut->createDataType(); - // add the nested type to the program root - program->addSymbol(ut->getTypeName(), ut); + // create a new var in the parent to store the intf implementation + ConstructorCall *cc = new ConstructorCall(ut->getTypeName(), ut->getLoc()); + Variable *v = new Scalar(ut->getName(), cc); + v->dt = ut->getDataType(); + cc->setScope(v); + v->setScope(this); + addChild(v); + + // replace the v->getName() symbol with its var and + symbols[v->getName()] = v; - } else { - v = dynamic_cast(child); - } + // add the nested type to the program root + program->addSymbol(ut->getTypeName(), ut); + } + for(auto child : this->children()) { + Variable *v = dynamic_cast(child); if (v && !v->isConstExpr()) { if (PropagateTypes::isUndefined(v, false)) { return false; diff --git a/src/UserType.h b/src/UserType.h index c9b1e49..798fd14 100644 --- a/src/UserType.h +++ b/src/UserType.h @@ -15,17 +15,20 @@ class UserType: public NamedNode { bool createDataType(); void setNestedParent(); + void createTempDataType(); public: UserType(const string name, vector &&stmts, location_t loc): NamedNode(name, std::move(stmts), loc) { setNestedParent(); + createTempDataType(); } UserType(const string name, vector &&stmts, vector &&implements, location_t loc): NamedNode(name, std::move(stmts), loc), implements(std::move(implements)) { setNestedParent(); + createTempDataType(); } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; @@ -58,13 +61,9 @@ class UserType: public NamedNode { return std::find(implements.begin(), implements.end(), intf) != implements.end(); } - DataType getDataType() override { - if (parent) { - // forces the definition of the parent first, as it adds the - // parent field on subtypes and also create them - parent->getDataType(); - } else - createDataType(); - return dt; + const vector& implementedIntfs() { + return implements; } + + friend class PropagateTypes; }; diff --git a/src/semantic/IdentifyVirtualDispatch.cpp b/src/semantic/IdentifyVirtualDispatch.cpp new file mode 100644 index 0000000..8a84890 --- /dev/null +++ b/src/semantic/IdentifyVirtualDispatch.cpp @@ -0,0 +1,44 @@ + +#include "IdentifyVirtualDispatch.h" +#include "FunctionCall.h" +#include "Program.h" +#include "UserType.h" +#include "BackLLVM.h" + +void IdentifyVirtualDispatch::propagateChildren(Node& n) { + for (auto* child : n.children()) { + child->accept(*this); + } +} + +Node* IdentifyVirtualDispatch::visit(Node& n) { + propagateChildren(n); + return NULL; +} + +Node* IdentifyVirtualDispatch::visit(FunctionCall& n) { + auto& ident = n.getIdent(); + + if (ident.isComplex()) { + // get the symbol containing the function being called + Identifier stem = ident.getStem(); + Node *stemSymbol = stem.getSymbol(n.getScope()); + + // identify if exists an injection for the symbol + auto ij = injections.find(stem.getFullName()); + Node *ijsymbol = NULL; + if (ij != injections.end()) + ijsymbol = Identifier(ij->first, program->getLoc()).getSymbol(program); + + // if no injection exists with that name, or the names refer to distinct symbols, + // then there's a call to a method of an unbound interface + if (ij == injections.end() || ijsymbol != stemSymbol) { + DataType dt = stemSymbol->getDataType(); + if (buildTypes->isInterface(dt)) { + //errs() << "Identified a call to " << ident.getFullName() << "\n"; + program->getDispatcher()->addIntfInvocation(dt); + } + } + } + return NULL; +} diff --git a/src/semantic/IdentifyVirtualDispatch.h b/src/semantic/IdentifyVirtualDispatch.h new file mode 100644 index 0000000..d829732 --- /dev/null +++ b/src/semantic/IdentifyVirtualDispatch.h @@ -0,0 +1,13 @@ + +#pragma once +#include "Visitor.h" + +class IdentifyVirtualDispatch: public Visitor { + protected: + + public: + IdentifyVirtualDispatch() {} + void propagateChildren(Node& n); + virtual Node* visit(Node& n) override; + virtual Node* visit(FunctionCall& n) override; +}; diff --git a/src/semantic/PropagateTypes.cpp b/src/semantic/PropagateTypes.cpp index e72de0c..639bab8 100644 --- a/src/semantic/PropagateTypes.cpp +++ b/src/semantic/PropagateTypes.cpp @@ -435,7 +435,16 @@ Node* PropagateTypes::visit(UserType& n) { } } } - n.dt = n.getDataType(); + + Node *firstDecl = n.getScope()->findSymbol(n.getTypeName()); + DataType sameNameDt = buildTypes->getType(n.getTypeName()); + if (!n.getParent() && sameNameDt != BuildTypes::undefinedType && buildTypes->isDefined(sameNameDt)) { + yyerrorcpp(string_format("The name %s is already used to define a type.", n.getName().c_str()), &n); + if (firstDecl) + yywarncpp(string_format("The type %s was defined here.", n.getName().c_str()), firstDecl); + } + + n.createDataType(); propagateChildren(n); return NULL; } @@ -461,14 +470,7 @@ Node* PropagateTypes::visit(Variable& n) { } Node *firstDecl = n.getScope()->findSymbol(n.getName()); - DataType sameNameDt = buildTypes->getType(n.getName()); - - if (sameNameDt != BuildTypes::undefinedType) { - yyerrorcpp(string_format("The name %s is already used to define a type.", n.getName().c_str()), &n); - if (firstDecl) - yywarncpp(string_format("The type %s was defined here.", n.getName().c_str()), firstDecl); - - } else if (firstDecl && firstDecl != &n) { + if (firstDecl && firstDecl != &n) { DataType ndt = n.getDataType(); destDt = firstDecl->getDataType(); if (ndt != BuildTypes::undefinedType && From 6a03d18ec2d5d3a8b13e764ba001b059a7c75a47 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Tue, 20 May 2025 15:23:31 -0300 Subject: [PATCH 102/117] Fixes global string var access --- src/BinaryOp.cpp | 11 +++++- src/StringConst.cpp | 67 +++++++++++++++++++--------------- test/general/global-string.rob | 19 ++++++++++ 3 files changed, 66 insertions(+), 31 deletions(-) create mode 100644 test/general/global-string.rob diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index 2326a60..008cbee 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -18,7 +18,16 @@ Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, // left Value *lhs = lhsn()->generate(func, block, allocblock); - BasicBlock *newlblock = dyn_cast(lhs)->getParent(); + auto lhsi = dyn_cast(lhs); + BasicBlock *newlblock; + if (lhsi) + newlblock = lhsi->getParent(); + else { + // if lhsi is null, lhs has no parent (e.g. a global variable/constant). + // use block as newlbblock + newlblock = block; + } + Type *lhsty = lhs->getType(); BasicBlock *fullev = BasicBlock::Create(global_context, "fullev", func->getLLVMFunction()); BasicBlock *phiblock = BasicBlock::Create(global_context, "phiblock", func->getLLVMFunction()); diff --git a/src/StringConst.cpp b/src/StringConst.cpp index a340711..8f02596 100644 --- a/src/StringConst.cpp +++ b/src/StringConst.cpp @@ -16,37 +16,44 @@ Value* StringConst::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * if (value) return value; - Constant *constant = ConstantDataArray::getString(global_context, str, false); - auto *gv = new GlobalVariable( - *mainmodule, constant->getType(), true, GlobalValue::PrivateLinkage, - constant, name); - gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); - gv->setAlignment(Align(1)); - - // const a = "abcdef" or a call to func("abc") - if (!leftValue || leftValue->hasQualifier(qconst)) { - Constant *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); - Constant *indices[] = {zero, zero}; - value = ConstantExpr::getInBoundsGetElementPtr(gv->getValueType(), gv, indices); - } else { - // a = "abcdef", alloc array and copy string const to it - Type* I = buildTypes->llvmType(tchar); - auto arrayType = ArrayType::get(I, str.size()); - - // alloc array - Builder->SetInsertPoint(allocblock); - auto alloc = Builder->CreateAlloca(arrayType, dataAddrSpace, 0, leftValue->getName()); - if (debug_info) { - RobDbgInfo.emitLocation(this); - RobDbgInfo.declareVar(leftValue, alloc, allocblock); + bool globalIsConstant = (allocblock != global_alloc); + if (globalIsConstant) { + // put the string content in a global + Constant *constant = ConstantDataArray::getString(global_context, str, false); + auto *gv = new GlobalVariable( + *mainmodule, constant->getType(), globalIsConstant, GlobalValue::PrivateLinkage, + constant, name); + gv->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); + + if (!leftValue || leftValue->hasQualifier(qconst)) { + // const a = "abcdef" or a call to func("abc") + // returns a pointer to the global constant gv + Constant *zero = ConstantInt::get(Type::getInt32Ty(global_context), 0); + Constant *indices[] = {zero, zero}; + value = ConstantExpr::getInBoundsGetElementPtr(gv->getValueType(), gv, indices); + } else { + // an initialized local string variable, e.g.: + // a = "abcdef", alloc array and copy string const to it + Type* I = buildTypes->llvmType(tchar); + auto arrayType = ArrayType::get(I, str.size()); + + // alloc array + Builder->SetInsertPoint(allocblock); + auto alloc = Builder->CreateAlloca(arrayType, dataAddrSpace, 0, leftValue->getName()); + if (debug_info) { + RobDbgInfo.emitLocation(this); + RobDbgInfo.declareVar(leftValue, alloc, allocblock); + } + leftValue->setAlloca(alloc); + + // copy string to the new array + Builder->SetInsertPoint(block); + Builder->CreateMemCpy(alloc, Align(1), gv, Align(1), str.size()); + value = alloc; } - leftValue->setAlloca(alloc); - - // copy string to the new array - Builder->SetInsertPoint(block); - Builder->CreateMemCpy(alloc, Align(1), gv, Align(1), str.size()); - value = alloc; - + } else { + value = Builder->CreateGlobalStringPtr(str, name, 0, mainmodule, false); + leftValue->setAlloca(value); } return value; diff --git a/test/general/global-string.rob b/test/general/global-string.rob new file mode 100644 index 0000000..9fd573d --- /dev/null +++ b/test/general/global-string.rob @@ -0,0 +1,19 @@ + +a = "-10"; + +bool test() { + return a[0] == '-'; +} + +bool test2(char[] b) { + return b[1] == '1'; +} + +int16 main() { + if a.size == 3 and test() and test2(a) and a[2] == '0' { + return 0; + } else { + return 1; + } +} + From 6375accf644a8a12cc697af5024554ef9675d875 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 1 Jun 2025 22:43:02 -0300 Subject: [PATCH 103/117] Reorder IdentifyVirtualDispatch to run after PropagateTypes. Fix error in atmega328p tests. --- src/Program.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Program.cpp b/src/Program.cpp index 503aeff..81ba8f9 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -210,12 +210,12 @@ void Program::doSemanticAnalysis() { SymbolizeTree st; st.visit(*this); - IdentifyVirtualDispatch ivd; - ivd.visit(*this); - PropagateTypes pt; pt.visit(*this); + IdentifyVirtualDispatch ivd; + ivd.visit(*this); + buildTypes->generateDebugInfoForTypes(); /*std::fstream fs; From 9c885223585449953ecdad65aa37b7f8828387e9 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Fri, 6 Jun 2025 17:20:34 -0300 Subject: [PATCH 104/117] Fix master mode for avr5 mcus, intermittent failures --- lib/arch/avr/avr5mcu.rob | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/lib/arch/avr/avr5mcu.rob b/lib/arch/avr/avr5mcu.rob index 1f57fc5..43fd235 100644 --- a/lib/arch/avr/avr5mcu.rob +++ b/lib/arch/avr/avr5mcu.rob @@ -13,11 +13,11 @@ void check_irq_handler(uint8 h) { assert(h != void, "IRQ enabled without setting the handler."); } -void irq_usart_rx() signal, section __irqs { +/*void irq_usart_rx() signal, section __irqs { check_irq_handler(typeid(int_usart_rx)); byte = UDR0; int_usart_rx.handler(byte); -} +}*/ type avr5mcu implements mcu { @@ -94,16 +94,32 @@ type avr5mcu implements mcu { } } + void busy_wait_loop5(uint16 count) noopt { + // trusting that ABI will put the count parameter in r25:r24 + // cycles total: 3 + count*5-1 + 3 + // +2 (ldi r25:r24 prior to cal) + count*5 - 1 + 3 + // +1 (ser) + // +count*5-1 (loop) + // +2 (rjmp) + // +1 (ret) + asm "ser r18 + loop: subi r18,1 + sbci r24,0 + sbci r25,0 + brne loop + rjmp end + end: "; // a ret is appended here + } + + // secure range 1 -- 5460 void wait_ms(uint16 ms) { - volatile mms = ms; - while mms > 0 { - wait_us(1000); - mms--; - } + count = uint16(clock() / 1280e3) * ms - 1; + busy_wait_loop5(count); } spi implements databus { /* setup hardware SPI at: + b2 = SS b3 = MOSI b4 = MISO b5 = SCK */ @@ -111,6 +127,11 @@ type avr5mcu implements mcu { b3.mode(port_mode.output); b4.mode(port_mode.input); b5.mode(port_mode.output); + + // set SS pin high before enabling master mode + // (mandatory for master mode) + b2.mode(port_mode.output); + b2.set(true); SPCR.MSTR = true; // master //TODO: ignoring speed for now. Set to fsck/4 = 4Mhz From 8a17838735d646861850a3fce06225a5c4ee9ef9 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Fri, 6 Jun 2025 21:22:09 -0300 Subject: [PATCH 105/117] Improve inline asm to support inputs. --- src/InlineAssembly.cpp | 59 ++++++++++++++++++++++---- src/InlineAssembly.h | 4 +- src/Language.y | 9 ++-- test/atmega328p/inline_asm.rob | 77 ++++++++++++++++++++++++++++++++++ 4 files changed, 137 insertions(+), 12 deletions(-) create mode 100644 test/atmega328p/inline_asm.rob diff --git a/src/InlineAssembly.cpp b/src/InlineAssembly.cpp index db36abf..b217310 100644 --- a/src/InlineAssembly.cpp +++ b/src/InlineAssembly.cpp @@ -1,19 +1,64 @@ +#include #include "InlineAssembly.h" +#include "FunctionImpl.h" Value *InlineAssembly::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - Type *voidty = buildTypes->llvmType(tvoid); - std::vector arg_types; - FunctionType *ftype = FunctionType::get(voidty, ArrayRef(arg_types), false); - InlineAsm *asmcall = InlineAsm::get(ftype, assembly, "", false, false, InlineAsm::AD_ATT); - Error err = asmcall->verify(ftype, ""); + + Function *llvmFunction = func->getLLVMFunction(); + + // Build a map with all argument names and the corresponding llvm::Argument* + // TODO: Include local symbols in the map + map argMap; + for (auto &Arg : llvmFunction->args()) { + argMap[Arg.getName().str()] = &Arg; + } + + bool isFirst = true; + std::string final_constraints; + std::vector ArgTypes; + std::vector Args; + + // constraints format supported: + // "r(arg_name_1)" + // "r(arg_name_1),r(arg_name_2),..." + regex constraint_regex(R"(([0-9a-zA-Z]+)\(([^)]+)\))"); + smatch match; + string::const_iterator searchStart(constraints.cbegin()); + + while (std::regex_search(searchStart, constraints.cend(), match, constraint_regex)) { + final_constraints += (isFirst ? "" : ",") + match[1].str(); + isFirst = false; + std::string argName = match[2].str(); + auto it = argMap.find(argName); + if (it != argMap.end()) { + llvm::Argument* arg = it->second; + ArgTypes.push_back(arg->getType()); + Args.push_back(arg); + } else { + yyerrorcpp(string_format("Parameter '%s' for assembly constraint not found.", + argName.c_str()), this); + } + searchStart = match.suffix().first; + } + + // TODO: Add output constraint when there's r = asm(...) in the language + // constraints = (isFirst ? "=r" : "=r," + constraints); + // returnType = detect! + // FunctionType *asmFuncType = FunctionType::get(returnType, ArgTypes, false); + FunctionType *asmFuncType = FunctionType::get(Type::getVoidTy(global_context), ArgTypes, false); + + InlineAsm *asmcall = InlineAsm::get(asmFuncType, assembly, final_constraints, true, false, InlineAsm::AD_ATT); + Error err = asmcall->verify(asmFuncType, constraints); if (err) { + /* disabled due to false alerts std::string error_message; raw_string_ostream OS(error_message); OS << err; - yyerrorcpp(error_message, this); + OS << " constraints: " << new_constraints; + yywarncpp(error_message, this);*/ } RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); - return Builder->CreateCall(ftype, asmcall, std::nullopt); + return Builder->CreateCall(asmFuncType, asmcall, Args); } diff --git a/src/InlineAssembly.h b/src/InlineAssembly.h index 95e94d1..8ce7bf3 100644 --- a/src/InlineAssembly.h +++ b/src/InlineAssembly.h @@ -6,7 +6,9 @@ class InlineAssembly: public Node { private: string assembly; + string constraints; public: - InlineAssembly(const char *a, location_t loc): Node(loc), assembly(a) { } + InlineAssembly(const char *_asm, location_t loc): Node(loc), assembly(_asm) { } + InlineAssembly(const char *_asm, const char *cons, location_t loc): Node(loc), assembly(_asm), constraints(cons) { } virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; }; diff --git a/src/Language.y b/src/Language.y index f6d1ee7..ab51a72 100644 --- a/src/Language.y +++ b/src/Language.y @@ -17,7 +17,7 @@ %type simplevar_decl call_or_cast complexvar_set %type term term2 expr factor stmt condblock whileblock logicexpr %type logicterm logicfactor TOK_AND TOK_OR event unary logicunary -%type bind +%type bind asminline %type type_impls %type element @@ -36,7 +36,7 @@ %type TOK_FLOAT %type TOK_DOUBLE %type TOK_LDOUBLE -%type TOK_STRING asminline +%type TOK_STRING %type function_attributes %type function_attribute @@ -302,7 +302,8 @@ elements : elements ',' element { $1->append($3); element : expr ':' TOK_INTEGER { $$ = new ArrayElement($1, (unsigned)$3); } | expr { $$ = new ArrayElement($1, 1); } -asminline : TOK_ASM TOK_STRING { $$ = $2; } +asminline : TOK_ASM TOK_STRING { $$ = new InlineAssembly($2, @1); } + | TOK_ASM TOK_STRING ':' TOK_STRING { $$ = new InlineAssembly($2, $4, @1); } stmts : %empty { $$ = new vector(); } | stmts_rec @@ -336,7 +337,7 @@ stmt : ident_or_xident '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Lo Node *bop = new BinaryOp(new LoadMatrix($id, $e1, $e2, @id), '|', $e3); $$ = new UpdateMatrix($id, $e1, $e2, bop, @1); } - | asminline ';' { $$ = new InlineAssembly($1, @1); } + | asminline ';' { $$ = $1; } | qualifier simplevar_decl ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } | simplevar_decl ';' | complexvar_set ';' diff --git a/test/atmega328p/inline_asm.rob b/test/atmega328p/inline_asm.rob new file mode 100644 index 0000000..bb1a1fb --- /dev/null +++ b/test/atmega328p/inline_asm.rob @@ -0,0 +1,77 @@ + +/* AVR inline assembly constraints +Obtained from https://github.com/avr-llvm/architecture/blob/master/Instructions/inline-assembly-constraints.md +Constraint | Used for | Range +---------- | --------------------------------------------------------------------------|---------------------- +a | Simple upper registers | r16 to r23 +b | Base pointer registers pairs | y, z +d | Upper register | r16 to r31 +e | Pointer register pairs | x, y, z +q | Stack pointer register | SPH:SPL +r | Any register | r0 to r31 +t | Temporary register | r0 +w | Special upper register pairs | r24, r26, r28, r30 +x | Pointer register pair X | x (r27:r26) +y | Pointer register pair Y | y (r29:r28) +z | Pointer register pair Z | z (r31:r30) +G | Floating point constant | 0.0 +I | 6-bit positive integer constant | 0 to 63 +J | 6-bit negative integer constant | -63 to 0 +K | Integer constant | 2 +L | Integer constant | 0 +l | Lower registers | r0 to r15 +M | 8-bit integer constant | 0 to 255 +N | Integer constant | -1 +O | Integer constant | 8, 16, 24 +P | Integer constant | 1 +Q | A memory address based on Y or Z pointer with displacement | +R | Integer constant | -6 to 5 +*/ + +void wait_asm_us2(uint16 count1, uint16 count2) noinline { + // wait 4 cycles per count + + // + 2 cycles in add/adc + // + 4 cycles moving r24:r25 to x and r22:r23 to z + asm "add r26, r30 + adc r27, r31 + 1: + sbiw $0, 1 + brne 1b" // a ret is appended here + : "x(count1),z(count2)"; +} + +void wait_asm_us(uint16 count) inline { + // wait 4 cycles per count + asm "1: + sbiw $0, 1 + brne 1b" // a ret is appended here + : "r(count)"; +} + +uint32 clock() { + return 16e6; +} + +void wait_us(uint16 us) { + count = uint16(clock() / 4e6) * us - 1; + wait_asm_us(count); +} + +int16 main() { + wait_us(10); + // return if non zero + asm "or r24, r25 + brne 1f"; + + // start with a dirty X + asm "ldi r26, 0x1 + ldi r27, 0x0"; + // X will decrease to zero + wait_asm_us2(1000, 2000); + // return X + asm "movw r24, X + 1: ret"; + + // unreachable code + return 0; +} From 92e4a55ef088b5a09c8f6e1e2beb357d40743386 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sat, 7 Jun 2025 09:32:38 -0300 Subject: [PATCH 106/117] Fix and expand dependency injection: preparing to sblp2025 --- platformio/integrate2vc | 12 ++ src/Dispatch.cpp | 17 ++- src/Dispatch.h | 7 +- src/FunctionCall.h | 4 + src/FunctionDecl.h | 2 +- src/FunctionImpl.cpp | 6 + src/FunctionImpl.h | 5 + src/Identifier.h | 4 + src/Injections.h | 4 + src/Interface.h | 6 +- src/Node.h | 1 + src/Program.cpp | 117 +++++++++++------- src/Program.h | 2 + src/UserType.cpp | 32 +++-- src/UserType.h | 12 ++ src/semantic/IdentifyVirtualDispatch.cpp | 44 ------- src/semantic/PropagateTypes.cpp | 1 + src/semantic/VirtualDispatchPasses.cpp | 68 ++++++++++ ...tualDispatch.h => VirtualDispatchPasses.h} | 8 +- test/general/global-pointer.rob | 3 - 20 files changed, 243 insertions(+), 112 deletions(-) create mode 100755 platformio/integrate2vc delete mode 100644 src/semantic/IdentifyVirtualDispatch.cpp create mode 100644 src/semantic/VirtualDispatchPasses.cpp rename src/semantic/{IdentifyVirtualDispatch.h => VirtualDispatchPasses.h} (64%) diff --git a/platformio/integrate2vc b/platformio/integrate2vc new file mode 100755 index 0000000..9f2044d --- /dev/null +++ b/platformio/integrate2vc @@ -0,0 +1,12 @@ +mkdir -p toolchain-robcmp +cd toolchain-robcmp && make +cd .. +cd ../lib && make +cd .. +mkdir -p ~/.platformio/platforms +mkdir -p ~/.platformio/packages +ln -sf `realpath ../lib` toolchain-robcmp/stdlib +ln -sf `realpath platform` ~/.platformio/platforms/robcmp +ln -sf `realpath toolchain-robcmp` ~/.platformio/packages/toolchain-robcmp +code --install-extension vscode-syntax/robcmpsyntax-0.0.1.vsix +echo "Open the examples folder and try to build and upload!" diff --git a/src/Dispatch.cpp b/src/Dispatch.cpp index 893e4c9..090cda2 100644 --- a/src/Dispatch.cpp +++ b/src/Dispatch.cpp @@ -4,6 +4,8 @@ #include "Interface.h" #include "FunctionImpl.h" #include "BackLLVM.h" +#include "Program.h" +#include "UserType.h" #include "Scanner.h" void Dispatch::addDataTypeImplementation(DataType base, DataType impl) { @@ -108,12 +110,17 @@ void Dispatch::generateDispatchFunctions(Node *scope) { // add switch case Builder->SetInsertPoint(fblock); if (!hasDefault && destTypeName.find("void_") == string::npos) { + //TODO: The default should halt the MCU? For security reasons, memory corruption, control flow hijack. switchi->setDefaultDest(implDtBlock); hasDefault = true; } else { - // TODO: provide better ids, per baseType - ConstantInt *implDtId = ConstantInt::get(Type::getInt8Ty(global_context), implDt, true); - switchi->addCase(implDtId, implDtBlock); + UserType *type = dynamic_cast(program->findSymbol(destTypeName)); + assert(type && "UserType should exists."); + int concreteId = type->getConcreteId(); + if (concreteId != -1) { + ConstantInt *implDtId = ConstantInt::get(Type::getInt8Ty(global_context), concreteId, true); + switchi->addCase(implDtId, implDtBlock); + } } } } @@ -123,4 +130,8 @@ void Dispatch::generateDispatchFunctions(Node *scope) { void Dispatch::notifyInterface(DataType intf) { dispatchHash[intf]; +} + +bool Dispatch::isIntfInvoked(DataType intf) { + return (intfsInvoked.find(intf) != intfsInvoked.end()); } \ No newline at end of file diff --git a/src/Dispatch.h b/src/Dispatch.h index 5d8cdc5..bec3c4e 100644 --- a/src/Dispatch.h +++ b/src/Dispatch.h @@ -11,15 +11,14 @@ class Dispatch { protected: map> dispatchHash; set intfsInvoked; + set possibleObjectsInvoked; public: void addDataTypeImplementation(DataType base, DataType impl); void addIntfInvocation(DataType intf); + void addNodeInvocation(Node *node); void generateDispatchFunctions(Node *scope); void notifyInterface(DataType intf); int getImplementationCount(DataType intf); - - bool isIntfInvoked(DataType intf) { - return (intfsInvoked.find(intf) != intfsInvoked.end()); - } + bool isIntfInvoked(DataType intf); }; diff --git a/src/FunctionCall.h b/src/FunctionCall.h index bce1e1d..0533aa8 100644 --- a/src/FunctionCall.h +++ b/src/FunctionCall.h @@ -41,4 +41,8 @@ class FunctionCall: public Node { Identifier& getIdent() { return ident; } + + void changeIdentifier(const string& id) { + ident.changeIdentifier(id); + } }; diff --git a/src/FunctionDecl.h b/src/FunctionDecl.h index 65bdc0a..9837686 100644 --- a/src/FunctionDecl.h +++ b/src/FunctionDecl.h @@ -92,7 +92,7 @@ class FunctionBase: public NamedNode { returnIsPointer = r; } - void addThisArgument(DataType dt); + virtual void addThisArgument(DataType dt); DataType getThisArgDt() const { return thisArgDt; diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index ef790c9..fed12be 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -70,6 +70,8 @@ bool FunctionImpl::preGenerate() { RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(falloc); + bool nooptfunc = func->hasFnAttribute(Attribute::OptimizeNone); + unsigned Idx = 0; for (auto &Arg : func->args()) { Variable *fp = parameters->getParameters()[Idx]; @@ -77,6 +79,10 @@ bool FunctionImpl::preGenerate() { const string& argname = fp->getName(); Arg.setName(argname); + if (nooptfunc) { + Arg.addAttr(Attribute::NoUndef); + } + if (buildTypes->isUnsignedDataType(ptype)) Arg.addAttr(Attribute::ZExt); diff --git a/src/FunctionImpl.h b/src/FunctionImpl.h index 79bddc3..4510728 100644 --- a/src/FunctionImpl.h +++ b/src/FunctionImpl.h @@ -37,4 +37,9 @@ class FunctionImpl: public FunctionBase { return func; } + void addThisArgument(DataType dt) override { + if (preGenerated) + assert(!preGenerated && "The function is already generated. This should not happen!\n"); + FunctionBase::addThisArgument(dt); + }; }; diff --git a/src/Identifier.h b/src/Identifier.h index 43fe4c0..97aadbe 100644 --- a/src/Identifier.h +++ b/src/Identifier.h @@ -11,6 +11,10 @@ class Identifier: public SourceLocation { public: Identifier(const string& ident, location_t loc): SourceLocation(loc) { + changeIdentifier(ident); + } + + void changeIdentifier(const string& ident) { this->ident = ident; complex = ident.find('.') != string::npos; } diff --git a/src/Injections.h b/src/Injections.h index bafbbf9..de0f0d6 100644 --- a/src/Injections.h +++ b/src/Injections.h @@ -8,12 +8,16 @@ enum BindScope {bs_singleton, bs_transient}; struct Injection { string bind; string to; + string singletonName; BindScope scope; SourceLocation loc; + Injection(const string& bind, const string& to, BindScope scope, const SourceLocation& loc): loc(loc) { this->bind = bind; this->to = to; this->scope = scope; + if (this->scope == bs_singleton) + this->singletonName = "__var_injection_for_" + bind; } }; diff --git a/src/Interface.h b/src/Interface.h index a6f6eca..50430c3 100644 --- a/src/Interface.h +++ b/src/Interface.h @@ -6,6 +6,7 @@ class Interface: public NamedNode { private: void createDataType(); + int nextConcreteTypeId = 0; public: Interface(const string& name, location_t loc) : NamedNode(name, loc) { @@ -21,5 +22,8 @@ class Interface: public NamedNode { bool validateImplementation(UserType *ut); - + int getNextConcreteId() { + nextConcreteTypeId++; + return nextConcreteTypeId-1; + } }; diff --git a/src/Node.h b/src/Node.h index 985a5df..f9027e6 100644 --- a/src/Node.h +++ b/src/Node.h @@ -99,6 +99,7 @@ class Node : public SourceLocation { friend class Program; friend class MemCopy; friend class PropagateTypes; + friend class IdentifyVirtualDispatch; }; class NamedNode: public Node { diff --git a/src/Program.cpp b/src/Program.cpp index 81ba8f9..3bad6f1 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -4,6 +4,8 @@ #include "FunctionImpl.h" #include "HeaderGlobals.h" #include "BackLLVM.h" +#include "Interface.h" +#include "Pointer.h" #include "UndefInit.h" #include "Return.h" #include "Load.h" @@ -12,7 +14,7 @@ #include "semantic/PrintAstVisitor.h" #include "semantic/PropagateTypes.h" #include "semantic/SymbolizeTree.h" -#include "semantic/IdentifyVirtualDispatch.h" +#include "semantic/VirtualDispatchPasses.h" Program::Program() : Node({0,0,0,0}) { mainmodule = new Module(this->getFile(), global_context); @@ -46,16 +48,57 @@ Value *Program::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo return NULL; } -void Program::generateInjectionSetup(SourceLocation *sl) { - +void Program::generateInjectionGlobals(SourceLocation *sl) { location_t loc = sl->getLoc(); // a function to init global vars for singleton injections - FunctionImpl *funcInitGlobals = new FunctionImpl((DataType)tvoid, "__injections_init", + funcInitGlobals = new FunctionImpl((DataType)tvoid, "__injections_init", new FunctionParams(), vector(), loc, loc, false); funcInitGlobals->setScope(this); + funcInitGlobals->setAttributes(new FunctionAttributes(fa_inline)); addSymbol(funcInitGlobals); + for (auto &[key, itype] : injections) { + Identifier bind(itype->bind, loc); + + // injection validation + auto subTypeName = regex_replace(bind.getFullName(), regex("\\."), ":"); //internal types use : + Identifier bindSubtypes(subTypeName, loc); + Node *injectType = bindSubtypes.getSymbol(this, false); + if (!injectType) { + yyerrorcpp(string_format("Injection symbol %s not found.", + bind.getFullName().c_str()), &itype->loc); + continue; + } + + if (itype->scope == bs_singleton) { + string globalVarName = itype->singletonName; + if (!bind.isComplex()) { + Node *var = findSymbol(globalVarName); + if (!var) { + // alloc the global var + UndefInit *nc = new UndefInit(injectType->getDataType(), loc); + Scalar *svar = new Scalar(globalVarName, nc); + svar->setScope(this); + addSymbol(svar); + svar->generate(NULL, NULL, global_alloc); + var = svar; + + ConstructorCall *cc = new ConstructorCall(bind.getFullName(), loc); + Scalar *sc = new Scalar(globalVarName, cc); + cc->setScope(funcInitGlobals); + sc->setScope(funcInitGlobals); + funcInitGlobals->addChild(sc); + } + } + } + } +} + +void Program::generateInjectionSetup(SourceLocation *sl) { + + location_t loc = sl->getLoc(); + /* create a function for each injection, named :get_injection_for_[to]: function :get_injection_for_[to] { static instance = type() @@ -71,11 +114,6 @@ void Program::generateInjectionSetup(SourceLocation *sl) { auto subTypeName = regex_replace(bind.getFullName(), regex("\\."), ":"); //internal types use : Identifier bindSubtypes(subTypeName, loc); Node *injectType = bindSubtypes.getSymbol(this, false); - if (!injectType) { - yyerrorcpp(string_format("Injection symbol %s not found.", - bind.getFullName().c_str()), &itype->loc); - continue; - } DataType destinationTy = BuildTypes::undefinedType; string destinationTyName; @@ -115,29 +153,7 @@ void Program::generateInjectionSetup(SourceLocation *sl) { finject->setAttributes(new FunctionAttributes(fa_inline)); if (itype->scope == bs_singleton) { - string globalVarName; - if (bind.isComplex()) { - globalVarName = "__var_injection_for_" + bind.getFullName(); - } else { - globalVarName = "__var_injection_for_" + bind.getFullName(); - Node *var = findSymbol(globalVarName); - if (!var) { - // alloc the global var - UndefInit *nc = new UndefInit(injectType->getDataType(), loc); - Scalar *svar = new Scalar(globalVarName, nc); - svar->setScope(this); - addSymbol(svar); - svar->generate(NULL, NULL, global_alloc); - var = svar; - - ConstructorCall *cc = new ConstructorCall(bind.getFullName(), loc); - Scalar *sc = new Scalar(globalVarName, cc); - cc->setScope(funcInitGlobals); - sc->setScope(funcInitGlobals); - funcInitGlobals->addChild(sc); - } - } - + string globalVarName = itype->singletonName; Load *load = new Load(Identifier(globalVarName, loc)); Return *ret = new Return(load); ret->setScope(finject); @@ -210,12 +226,14 @@ void Program::doSemanticAnalysis() { SymbolizeTree st; st.visit(*this); - PropagateTypes pt; - pt.visit(*this); - IdentifyVirtualDispatch ivd; ivd.visit(*this); + PropagateTypes pt; + pt.visit(*this); + + ivd.applyIdentifiedChanges(); + buildTypes->generateDebugInfoForTypes(); /*std::fstream fs; @@ -226,25 +244,36 @@ void Program::doSemanticAnalysis() { void Program::generate() { - Node *mainFunc = NULL; - generateBuiltins(); + + // find the main function + auto mainFuncIt = symbols.find("main"); + if (mainFuncIt == symbols.end()) + mainFuncIt = symbols.find("__main"); + Node *mainFunc = mainFuncIt->second; + + generateInjectionGlobals(mainFunc); + // build types and global vars first + map already_generated; for(auto n: children()) { - if (FunctionImpl *func = dynamic_cast(n)) { - if (func->getName() == "main" || func->getName() == "__main") { - // generate main function after all others - mainFunc = n; - continue; - } + if (dynamic_cast(n) || + dynamic_cast(n) || + dynamic_cast(n) || + dynamic_cast(n)) { + n->generate(NULL, NULL, global_alloc); + already_generated[n] = true; } + } + for(auto n: children()) { + if (n == mainFunc || already_generated[n]) + continue; n->generate(NULL, NULL, global_alloc); } if (mainFunc && injections.size() > 0) { generateInjectionSetup(mainFunc); - FunctionCall *fc = new FunctionCall("__injections_init", new ParamsCall(), mainFunc->getLoc()); fc->setScope(mainFunc); mainFunc->addChild(fc, true); diff --git a/src/Program.h b/src/Program.h index 186cca8..d4c5100 100644 --- a/src/Program.h +++ b/src/Program.h @@ -7,6 +7,7 @@ class Program : public Node { protected: Dispatch *dispatch; + FunctionImpl *funcInitGlobals = NULL; public: Program(); ~Program(); @@ -16,6 +17,7 @@ class Program : public Node { Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); void generate(); void generateInjectionSetup(SourceLocation *sl); + void generateInjectionGlobals(SourceLocation *sl); void declareBuiltins(); void generateBuiltins(); void doSemanticAnalysis(); diff --git a/src/UserType.cpp b/src/UserType.cpp index 02cef05..be7f7e8 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -62,7 +62,6 @@ bool UserType::createDataType() { std::vector elements; // if needed, add typeid as the first field - UInt8 *typeId = NULL; if (implements.size() > 0) { // the typeid field is needed if any implemented interface is unbound // (not injected) and at least one of its methods was invoked @@ -152,12 +151,30 @@ bool UserType::createDataType() { return false; } - if (typeId) - typeId->setNumber(dt); + if (typeId) { + Node *intfsymbol = program->findSymbol(implements[0]); + if (Interface *intf = dynamic_cast(intfsymbol)) + typeId->setNumber(intf->getNextConcreteId()); + } return true; } +void UserType::setThisArgToFunctions() { + /* set function parameters before generate + * A function can call others that are still not generated + * and request their type info. So, here we set all needed + * info to pre-generate their type. + */ + for(auto & [key, stmt] : getSymbols()) { + if (FunctionImpl *f = dynamic_cast(stmt)) { + f->setPrefixName(getTypeName()); + f->addThisArgument(dt); + f->setExternal(declaration); + } + } +} + Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { if (!createDataType()) @@ -184,18 +201,11 @@ Value *UserType::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *all } } - /* set function parameters before generate - * A function can call others that are still not generated - * and request their type info. So, here we set all needed - * info to pre-generate their type. - */ + // add parent fields to the function so that it can use them without prefix for(auto & [key, stmt] : getSymbols()) { if (FunctionImpl *f = dynamic_cast(stmt)) { - f->setPrefixName(getTypeName()); - f->addThisArgument(dt); for(auto &field : fields) f->addSymbol(dynamic_cast(field)); - f->setExternal(declaration); } } diff --git a/src/UserType.h b/src/UserType.h index 798fd14..e03f883 100644 --- a/src/UserType.h +++ b/src/UserType.h @@ -2,6 +2,7 @@ #pragma once #include "Node.h" +#include "Int8.h" class Visitor; @@ -12,10 +13,12 @@ class UserType: public NamedNode { bool declaration = false; UserType *parent = NULL; unsigned bitWidth = 0; + UInt8 *typeId = NULL; bool createDataType(); void setNestedParent(); void createTempDataType(); + void setThisArgToFunctions(); public: @@ -65,5 +68,14 @@ class UserType: public NamedNode { return implements; } + int getConcreteId() { + if (typeId) { + //assert(typeId && "Typeid field is not set."); + return typeId->getNumber(); + } else { + return -1; + } + } + friend class PropagateTypes; }; diff --git a/src/semantic/IdentifyVirtualDispatch.cpp b/src/semantic/IdentifyVirtualDispatch.cpp deleted file mode 100644 index 8a84890..0000000 --- a/src/semantic/IdentifyVirtualDispatch.cpp +++ /dev/null @@ -1,44 +0,0 @@ - -#include "IdentifyVirtualDispatch.h" -#include "FunctionCall.h" -#include "Program.h" -#include "UserType.h" -#include "BackLLVM.h" - -void IdentifyVirtualDispatch::propagateChildren(Node& n) { - for (auto* child : n.children()) { - child->accept(*this); - } -} - -Node* IdentifyVirtualDispatch::visit(Node& n) { - propagateChildren(n); - return NULL; -} - -Node* IdentifyVirtualDispatch::visit(FunctionCall& n) { - auto& ident = n.getIdent(); - - if (ident.isComplex()) { - // get the symbol containing the function being called - Identifier stem = ident.getStem(); - Node *stemSymbol = stem.getSymbol(n.getScope()); - - // identify if exists an injection for the symbol - auto ij = injections.find(stem.getFullName()); - Node *ijsymbol = NULL; - if (ij != injections.end()) - ijsymbol = Identifier(ij->first, program->getLoc()).getSymbol(program); - - // if no injection exists with that name, or the names refer to distinct symbols, - // then there's a call to a method of an unbound interface - if (ij == injections.end() || ijsymbol != stemSymbol) { - DataType dt = stemSymbol->getDataType(); - if (buildTypes->isInterface(dt)) { - //errs() << "Identified a call to " << ident.getFullName() << "\n"; - program->getDispatcher()->addIntfInvocation(dt); - } - } - } - return NULL; -} diff --git a/src/semantic/PropagateTypes.cpp b/src/semantic/PropagateTypes.cpp index 639bab8..d7fe0d2 100644 --- a/src/semantic/PropagateTypes.cpp +++ b/src/semantic/PropagateTypes.cpp @@ -445,6 +445,7 @@ Node* PropagateTypes::visit(UserType& n) { } n.createDataType(); + n.setThisArgToFunctions(); propagateChildren(n); return NULL; } diff --git a/src/semantic/VirtualDispatchPasses.cpp b/src/semantic/VirtualDispatchPasses.cpp new file mode 100644 index 0000000..1a74b28 --- /dev/null +++ b/src/semantic/VirtualDispatchPasses.cpp @@ -0,0 +1,68 @@ + +#include "VirtualDispatchPasses.h" +#include "FunctionCall.h" +#include "Program.h" +#include "UserType.h" +#include "BackLLVM.h" + +void IdentifyVirtualDispatch::propagateChildren(Node& n) { + for (auto* child : n.children()) { + child->accept(*this); + } +} + +Node* IdentifyVirtualDispatch::visit(Node& n) { + propagateChildren(n); + return NULL; +} + +Node* IdentifyVirtualDispatch::visit(FunctionCall& n) { + auto& ident = n.getIdent(); + + if (ident.isComplex()) { + // get the symbol containing the function being called + Identifier stem = ident.getStem(); + Node *stemSymbol = stem.getSymbol(n.getScope()); + + // get the complete hierarquical name + if (UserType *owner = dynamic_cast(stemSymbol->getScope())) { + auto full_name = regex_replace(owner->getTypeName(), regex(":"), "."); + full_name.append("."); + full_name.append(stem.getFullName()); + stem.changeIdentifier(full_name); + } + + // identify if exists an injection for the symbol + auto ij = injections.find(stem.getFullName()); + Node *ijsymbol = NULL; + if (ij != injections.end()) + ijsymbol = Identifier(ij->first, program->getLoc()).getSymbol(program); + + if (ijsymbol == stemSymbol) { + // change the call to the injected symbol if singleton + if (ij->second->scope == bs_singleton) { + string new_call = ident.getFullName(); + string to_replace = ident.getStem().getFullName(); + new_call.replace(new_call.find(to_replace), to_replace.length(), ij->second->singletonName); + identifiedCalls.push_back(CompileTimeInject{&n, new_call}); + } + } else { + // if no injection exists with that name, or the names refer to distinct symbols, + // then there's a call to a method of an unbound interface + // PropagateTypes didn't run at this point, so don't call getDataType here + if (stemSymbol->dt != BuildTypes::undefinedType && + buildTypes->isInterface(stemSymbol->dt)) { + program->getDispatcher()->addIntfInvocation(stemSymbol->dt); + } + } + } + return NULL; +} + +void IdentifyVirtualDispatch::applyIdentifiedChanges() { + for(auto &ic : identifiedCalls) { + //errs() << "Call to " << ic.fc->getIdent().getFullName() << + // " converted to " << ic.new_call << "\n"; + ic.fc->changeIdentifier(ic.new_call); + } +} \ No newline at end of file diff --git a/src/semantic/IdentifyVirtualDispatch.h b/src/semantic/VirtualDispatchPasses.h similarity index 64% rename from src/semantic/IdentifyVirtualDispatch.h rename to src/semantic/VirtualDispatchPasses.h index d829732..09c7e1b 100644 --- a/src/semantic/IdentifyVirtualDispatch.h +++ b/src/semantic/VirtualDispatchPasses.h @@ -2,12 +2,18 @@ #pragma once #include "Visitor.h" +struct CompileTimeInject { + FunctionCall *fc; + string new_call; +}; + class IdentifyVirtualDispatch: public Visitor { protected: - + vector identifiedCalls; public: IdentifyVirtualDispatch() {} void propagateChildren(Node& n); virtual Node* visit(Node& n) override; virtual Node* visit(FunctionCall& n) override; + void applyIdentifiedChanges(); }; diff --git a/test/general/global-pointer.rob b/test/general/global-pointer.rob index 0cf364f..38b0c38 100644 --- a/test/general/global-pointer.rob +++ b/test/general/global-pointer.rob @@ -7,9 +7,6 @@ use intfs.interrupt; myint = interrupt_i8(); -// myint defaults to void_interrupt_i8 -bind void_interrupt_i8 to myint singleton; - value = 0xff; void call_handler() { From abb775d39fba9aedcacf30252474eb8b073d69b3 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Fri, 13 Jun 2025 16:26:07 -0300 Subject: [PATCH 107/117] Enables setting upload_speed in platformio.ini --- platformio/platform/builder/main.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/platformio/platform/builder/main.py b/platformio/platform/builder/main.py index 05fa252..4e605f1 100644 --- a/platformio/platform/builder/main.py +++ b/platformio/platform/builder/main.py @@ -40,6 +40,15 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 hardware_spec = None pass +try: + upload_speed = env.GetProjectOption("upload_speed") +except: + if mcu.startswith("stm32"): + upload_speed = 115200 + else: + upload_speed = 57600 + pass + if mcu == "native": ldflags = [] else: @@ -146,7 +155,7 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 stm32flash_bin = join(platform.get_package_dir("tool-stm32duino"), "stm32flash") env.Replace( UPLOADER=join(stm32flash_bin, "stm32flash"), - UPLOADERFLAGS=["-b", "115200", "-w"], + UPLOADERFLAGS=["-b", upload_speed, "-w"], UPLOADCMD='$UPLOADER $UPLOADERFLAGS "$SOURCE" $UPLOAD_PORT' ) @@ -155,7 +164,7 @@ def BeforeUpload(target, source, env): # pylint: disable=W0613,W0621 avrdude_cfg = join(platform.get_package_dir("tool-avrdude"), "avrdude.conf") env.Replace( UPLOADER=avrdude_bin, - UPLOADERFLAGS=["-C", avrdude_cfg, "-v", "-V", "-c", "arduino", "-p", "m328p", "-b", "57600", "-U"], + UPLOADERFLAGS=["-C", avrdude_cfg, "-v", "-V", "-c", "arduino", "-p", "m328p", "-b", upload_speed, "-U"], UPLOADCMD='$UPLOADER $UPLOADERFLAGS flash:w:${SOURCE}:i -P $UPLOAD_PORT' ) From c5c36596212dba012bca7a7cd24b940e453ecf95 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 22 Jun 2025 14:35:13 -0300 Subject: [PATCH 108/117] Implements array and matrices of types. --- src/Array.cpp | 81 +++++++++++++++++----- src/Array.h | 28 ++++++-- src/ArrayElements.cpp | 31 +++++++-- src/ArrayElements.h | 5 ++ src/BuildTypes.cpp | 37 ++++++---- src/ConstructorCall.cpp | 11 ++- src/ConstructorCall.h | 11 +-- src/FunctionDecl.cpp | 19 +++--- src/LoadArray.cpp | 9 ++- src/LoadArray.h | 11 ++- src/Matrix.cpp | 117 ++++---------------------------- src/Matrix.h | 32 +++------ src/MatrixElements.cpp | 4 +- src/MemCopy.cpp | 11 +-- src/MemCopy.h | 23 +++++-- src/semantic/PropagateTypes.cpp | 7 +- src/semantic/SymbolizeTree.h | 2 +- test/general/matrix_of_type.rob | 83 ++++++++++++++++++++++ test/general/vector_of_type.rob | 76 +++++++++++++++++++++ 19 files changed, 395 insertions(+), 203 deletions(-) create mode 100644 test/general/matrix_of_type.rob create mode 100644 test/general/vector_of_type.rob diff --git a/src/Array.cpp b/src/Array.cpp index 399dbfa..e911427 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -7,14 +7,14 @@ #include "semantic/PropagateTypes.h" #include "semantic/Visitor.h" -Array::Array(const string& n, ArrayElements *aes, location_t loc) : Variable(n, loc), elements(aes) { +Array::Array(const string& n, ArrayElements *aes, location_t loc) : Variable(n, loc), arrayElements(aes) { NamedConst *nc = new NamedConst("size", getNodeForUIntConst(aes->getArraySize(), loc)); addChild(nc); addSymbol(nc); } Array::Array(const string& n, location_t loc) : Variable(n, loc) { - elements = new ArrayElements(getLoc()); + arrayElements = new ArrayElements(getLoc()); } DataType Array::getDataType() { @@ -28,14 +28,19 @@ void Array::createDataType() { return; //Create a constant with the array size - size = elements->getArraySize(); - Value *array_size = ConstantInt::get(Type::getInt8Ty(global_context), size); + size = arrayElements->getArraySize(); //Get Type of elements in Array of Elements, and define as I. - element_dt = elements->getArrayType(); + element_dt = arrayElements->getArrayType(); dt = buildTypes->getArrayType(buildTypes->name(element_dt), this->getLoc(), 1, true); + Type* I = buildTypes->llvmType(element_dt); + if (buildTypes->isComplex(element_dt)) { + // in rob, all arrays of user types (complex types) + // are array of references + I = I->getPointerTo(codeAddrSpace); + } //Declare array type. arrayType = ArrayType::get(I, size); @@ -46,22 +51,39 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb createDataType(); //Generate array elements - unsigned int struct_size = elements->getStructSize(); unsigned int index = 0; bool allConst = true; vector elementValues; - elementValues.reserve(elements->getArraySize()); + map ctorsValues; + + int currentElement = 0; + elementValues.reserve(arrayElements->getArraySize()); + unsigned int struct_size = arrayElements->getStructSize(); for (int i=0; igetStructElement(i); - Value *val = elValue->generate(func, block, allocblock); - if (!val) - return NULL; - if (!dyn_cast(val)) + Node* elValue = arrayElements->getStructElement(i); + Value *val; + Constructor *ctor; + if ((ctor = dynamic_cast(elValue))) { + // constructors are called latter, for each array element + val = nullptr; allConst = false; + } else { + ctor = nullptr; + val = elValue->generate(func, block, allocblock); + if (!val) { + yyerrorcpp(string_format("Can not generate the value for element at pos %d", i).c_str(), elValue, true); + return NULL; + } + if (!dyn_cast(val)) + allConst = false; + } - unsigned elCount = elements->getElementCount(i); + unsigned elCount = arrayElements->getElementCount(i); for (int j=0; j < elCount; j++) { elementValues.push_back(val); + if (!val) // is ctor + ctorsValues[currentElement] = ctor; + currentElement++; } } @@ -106,17 +128,40 @@ Value *Array::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb RobDbgInfo.declareVar(this, alloc, allocblock); } } + + Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); + + // create an array and initialize the Copy/Constructors instances + // e.g. a = {element(), element():2, copy(x1), copy(y)} + if (ctorsValues.size() > 0) { + Type* ctorTy = buildTypes->llvmType(element_dt); + ArrayType *ctorArrayType = ArrayType::get(ctorTy, ctorsValues.size()); + Builder->SetInsertPoint(allocblock); + Value *ctorArray = Builder->CreateAlloca(ctorArrayType, dataAddrSpace, 0, "inlineArrayElems"); + + Builder->SetInsertPoint(block); + int idxCtor = 0; + for(auto &[key, ctor] : ctorsValues) { + Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), idxCtor); + Value* indexList[2] = {zero, idx}; + RobDbgInfo.emitLocation(ctor); + Value* gep = Builder->CreateGEP(ctorArrayType, ctorArray, indexList, "ctorElem"); + ctor->setLeftGEP(gep); + ctor->generate(func, block, allocblock); + elementValues[key] = gep; + idxCtor++; + } + } + RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); - Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); - StoreInst *store = NULL; + // set array elements for(unsigned index = 0; index < elementValues.size(); index++) { Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), index); Value* indexList[2] = {zero, idx}; - Value* gep = Builder->CreateGEP(arrayType, alloc, - ArrayRef(indexList), "elem"); - store = Builder->CreateStore(elementValues[index], gep, false); + Value* gep = Builder->CreateGEP(arrayType, alloc, indexList, "elem"); + Builder->CreateStore(elementValues[index], gep, false); } } diff --git a/src/Array.h b/src/Array.h index d1619f2..9a90aa0 100644 --- a/src/Array.h +++ b/src/Array.h @@ -10,25 +10,37 @@ class ArrayElements; class ParamArray: public Variable { protected: DataType element_dt = BuildTypes::undefinedType; + string element_dt_name; public: ParamArray(const string& n, string element_dt_name, location_t loc): Variable(n, loc) { - this->element_dt = buildTypes->getType(element_dt_name, true); - this->dt = buildTypes->getArrayType(element_dt_name, loc, 1, true); + this->element_dt_name = element_dt_name; } ParamArray(const string &n, DataType dt, location_t loc): Variable(n, loc) { this->dt = dt; this->element_dt = buildTypes->getArrayElementType(dt); } + + virtual int getDimensions() { + return 1; + } + + DataType getDataType() override { + if (dt == BuildTypes::undefinedType) { + element_dt = buildTypes->getType(element_dt_name, true); + dt = buildTypes->getArrayType(element_dt_name, getLoc(), getDimensions(), true); + } + return dt; + } }; class Array: public Variable { -private: +protected: unsigned int size; DataType element_dt = BuildTypes::undefinedType; - ArrayElements *elements; ArrayType *arrayType = NULL; - void createDataType(); + ArrayElements *arrayElements; + virtual void createDataType(); public: Array(const string& n, ArrayElements *aes, location_t loc); @@ -40,7 +52,7 @@ class Array: public Variable { int p1size = -1, int p2size = -1, Node *columnNumber = NULL); virtual std::vector& getElements() { - return elements->getElements(); + return arrayElements->getElements(); } virtual Node* accept(Visitor& v) override; @@ -56,4 +68,8 @@ class Array: public Variable { virtual int getSize() const { return size; } + + const ArrayType* getArrayType() { + return arrayType; + } }; diff --git a/src/ArrayElements.cpp b/src/ArrayElements.cpp index 9075c4d..fb0a4d7 100644 --- a/src/ArrayElements.cpp +++ b/src/ArrayElements.cpp @@ -1,5 +1,7 @@ #include "ArrayElements.h" +#include "ConstructorCall.h" +#include "MemCopy.h" ArrayElements::ArrayElements(location_t loc): location(loc) {}; @@ -19,7 +21,20 @@ unsigned ArrayElements::getStructSize() { } DataType ArrayElements::getArrayConstType(const set& types, SourceLocation *location) { - + + // detect use of two or more usertype + if (types.size() >= 2) { + int userTypesCount = 0; + for(auto &dt : types) { + if (buildTypes->isComplex(dt)) + userTypesCount++; + } + if (userTypesCount > 1) { + yyerrorcpp(string_format("There are %d heterogeneous element types. Can not convert between them.", userTypesCount), location); + return tvoid; + } + } + if (types.size() == 1) { // only one type return *types.begin(); @@ -50,10 +65,9 @@ DataType ArrayElements::getArrayConstType(const set& types, SourceLoca return floatdt; // convert all to largest float else if (largest_int > 0) return intdt; // convert all to largest int - else { - yyerrorcpp("Can't identify the array type based on its values.", location); - return BuildTypes::undefinedType; - } + + yyerrorcpp("Can't identify the array type based on its values.", location); + return BuildTypes::undefinedType; } DataType ArrayElements::getArrayType() { @@ -63,8 +77,13 @@ DataType ArrayElements::getArrayType() { DataType edt = i->value->getDataType(); if (buildTypes->isEnum(edt)) edt = tint8; - types.emplace(edt); + + if (buildTypes->isArrayOrMatrix(edt)) + yyerrorcpp("Can not make array of arrays yet.", i->value); + else + types.emplace(edt); } + return getArrayConstType(types, &location); } diff --git a/src/ArrayElements.h b/src/ArrayElements.h index e5ddac2..8cb3f73 100644 --- a/src/ArrayElements.h +++ b/src/ArrayElements.h @@ -28,4 +28,9 @@ class ArrayElements { std::vector& getElements() { return elements; } + + void insertElements(ArrayElements *newElements) { + elements.insert(elements.end(), + newElements->elements.begin(), newElements->elements.end()); + } }; diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 24fe6cb..8262a94 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -80,17 +80,18 @@ DataType BuildTypes::getArrayType(const string& elementName, SourceLocation n, } else { DataType dt = addDataType(DataTypeInfo(arrayTyName)); DataTypeInfo &info = tinfo[dt]; - info.llvmType = ArrayType::get(elementInfo.llvmType, 0); // we couldn't know the array size at compile time + Type *I = elementInfo.llvmType; + if (elementInfo.isComplex) { + // In rob, any array of complex types is an array of refs + I = elementInfo.llvmType->getPointerTo(); + } + // we don't know the array size at compile time + info.llvmType = ArrayType::get(I, 0); info.isDefined = true; info.isComplex = false; info.arrayDimensions = dimensions; - info.bitWidth = elementInfo.bitWidth; + info.bitWidth = tinfo[targetPointerType].bitWidth; info.dwarfEnc = dwarf::DW_ATE_address; - if (debug_info) { - info.diType = DBuilder->createArrayType(0, 0, elementInfo.diType, {}); - unsigned ptbw = tinfo[currentTarget().pointerType].bitWidth; - info.diPointerType = DBuilder->createPointerType(elementInfo.diType, ptbw); - } return dt; } } @@ -272,13 +273,23 @@ void BuildTypes::generateDebugInfoForTypes() { auto& info = tinfo[dt]; Node *userType = program->findSymbol(info.name); - if (!userType) - continue; + if (userType) { + if (info.isEnum) + generateDebugInfoForEnum(info, userType); + else if (info.isComplex) + generateDebugInfoForUserType(info, userType); - if (info.isEnum) - generateDebugInfoForEnum(info, userType); - else - generateDebugInfoForUserType(info, userType); + } + } + + for (DataType dt = nextt-1; dt >= __bdt_last; dt--) { + auto& info = tinfo[dt]; + if (info.arrayDimensions > 0) { + auto elementInfo = tinfo[getArrayElementType(dt)]; + info.diType = DBuilder->createArrayType(0, 0, elementInfo.diPointerType, {}); + unsigned ptbw = tinfo[currentTarget().pointerType].bitWidth; + info.diPointerType = DBuilder->createPointerType(elementInfo.diType, ptbw); + } } } diff --git a/src/ConstructorCall.cpp b/src/ConstructorCall.cpp index 48dad0d..99625b5 100644 --- a/src/ConstructorCall.cpp +++ b/src/ConstructorCall.cpp @@ -13,7 +13,16 @@ Value* ConstructorCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlo RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); GlobalVariable *gv = NULL; - Value *var = leftValue->getLLVMValue(func); + + Value *var; + if (leftGEP) { + // init a previously set gep (e.g., array element) + var = leftGEP; + } else { + assert(leftValue && "leftValue or gep must be set."); + var = leftValue->getLLVMValue(func); + } + if (var == NULL) { // is a new left var Type *vty = buildTypes->llvmType(dt); diff --git a/src/ConstructorCall.h b/src/ConstructorCall.h index 55ce111..c6f964c 100644 --- a/src/ConstructorCall.h +++ b/src/ConstructorCall.h @@ -2,19 +2,14 @@ #pragma once #include "Node.h" -#include "Variable.h" #include "FunctionImpl.h" +#include "MemCopy.h" -class ConstructorCall: public Node { +class ConstructorCall: public Constructor { protected: - Variable *leftValue = NULL; string name; public: - ConstructorCall(const string tyName, location_t loc): Node(loc), name(tyName) { } - - virtual void setLeftValue(Variable *symbol) override { - leftValue = symbol; - } + ConstructorCall(const string tyName, location_t loc): Constructor(loc), name(tyName) { } virtual Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index eac0b86..aacd286 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -2,6 +2,7 @@ #include "FunctionDecl.h" #include "BackLLVM.h" #include "FunctionAttributes.h" +#include "Array.h" #include "Matrix.h" void FunctionBase::addThisArgument(DataType dt) { @@ -50,15 +51,16 @@ void FunctionBase::addPseudoParameters() { for (int i = 0; i < vparams.size(); ++i) { Variable *p = vparams[i]; - DataType pdt = p->getDataType(); - if (buildTypes->isArrayOrMatrix(pdt)) { + ParamArray *paramArray = dynamic_cast(p); + ParamMatrix *paramMatrix = dynamic_cast(p); + + if (paramArray || paramMatrix) { vector pseudos; - if (buildTypes->isArray(pdt)) - pseudos.push_back("size"); - else if (buildTypes->isMatrix(pdt)) { + if (paramMatrix) { pseudos.push_back("rows"); pseudos.push_back("cols"); - } + } else if (paramArray) + pseudos.push_back("size"); for(const string& s: pseudos) { //TODO: There is something better than fix this to Int32? Fix here and in FunctionCall::generate @@ -72,9 +74,8 @@ void FunctionBase::addPseudoParameters() { } // ParamMatrix need to know the number of cols to compute element indexes - if (buildTypes->isMatrix(pdt)) { - if (ParamMatrix *pm = dynamic_cast(p)) - pm->addSymbol("cols", vparams.back()); + if (paramMatrix) { + paramMatrix->addSymbol("cols", vparams.back()); } } } diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index e731efc..8f91587 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -73,10 +73,17 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); Value *indexList[2] = {zero, indice}; Value *ptr = Builder->CreateGEP(symbol->getLLVMType(), alloc, ArrayRef(indexList), "gep"); + DataType elementDt = buildTypes->getArrayElementType(symbol->getDataType()); Type *elemType = buildTypes->llvmType(elementDt); - LoadInst *ret = Builder->CreateLoad(elemType, ptr, ident.getFullName()); + if (buildTypes->isUserType(elementDt)) { + if (leftValue) { + leftValue->setPointerToPointer(true); + } + elemType = elemType->getPointerTo(); + } + LoadInst *ret = Builder->CreateLoad(elemType, ptr, ident.getFullName()); return ret; } diff --git a/src/LoadArray.h b/src/LoadArray.h index d234990..4eaf47f 100644 --- a/src/LoadArray.h +++ b/src/LoadArray.h @@ -9,6 +9,7 @@ class BaseArrayOper: public Node { Identifier ident; Node *position; Node *position2; + Variable *leftValue = nullptr; public: BaseArrayOper(const string& i, Node *pos, Node *pos2, location_t loc): Node(loc), ident(i, loc), position(pos), position2(pos2) {} @@ -23,13 +24,21 @@ class BaseArrayOper: public Node { return position2; } - const string getIdent() { + const string getIdent() const { return ident.getFullName(); } const int getDimensions() { return children().size(); } + + virtual const string getName() const override { + return getIdent(); + } + + virtual void setLeftValue(Variable *symbol) override { + leftValue = symbol; + } }; class LoadArray: public BaseArrayOper { diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 14b746c..25e7860 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -5,117 +5,27 @@ #include "NamedConst.h" #include "semantic/Visitor.h" -Matrix::Matrix(const char *n, MatrixElements *me, location_t loc) : Variable(n, loc), melements(me) { +Matrix::Matrix(const char *n, MatrixElements *me, location_t loc) : Array(n, loc), melements(me) { NamedConst *rows = new NamedConst("rows", getNodeForUIntConst(me->getRowCount(), this->getLoc())); NamedConst *cols = new NamedConst("cols", getNodeForUIntConst(me->getColumnCount(), this->getLoc())); addChild(rows); addSymbol("rows", rows); addChild(cols); addSymbol("cols", cols); -} - -Value *Matrix::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - - /* - * Matrix is generated as an array and accessed latter accordingly! - */ - createDataType(); - // Allocate elements. Supported formats: - // {{1:3}:3, {1:2,2}:2} - // {{1,1,1},{1,1,1},{1,1,1},{1,1,2},{1,1,2}} - bool allConst = true; - vector elementValues; - elementValues.reserve(rows * cols); - for(MatrixElement *i: getElements()) { - unsigned elCount = i->count; - - for (int j=0; jarray->getElements()) { - Node* elValue = k->value; - Value *val = elValue->generate(func, block, allocblock); - if (!val) - return NULL; - if (!dyn_cast(val)) - allConst = false; - for (int l=0; l < k->count; l++) - elementValues.push_back(val); - } - } + // fill arrayElements with matrix elements copy + for(auto &melem : melements->getElements()) { + for(int repeat = 0; repeat < melem->count; repeat++) + arrayElements->insertElements(melem->array); } - - if (!allConst && (allocblock == NULL || allocblock == global_alloc)) { - // Load will produce an error informing the usage of other variables - // to define a new global variable - return NULL; - } - - auto sp = RobDbgInfo.currScope(); - auto funit = RobDbgInfo.currFile(); - - //Allocate matrix as an array. - if (allocblock == global_alloc) { // when alloc is global - vector constantValues; - constantValues.reserve(elementValues.size()); - for(auto &a : elementValues) - constantValues.push_back(dyn_cast(a)); - ArrayRef constantRefs(constantValues); - GlobalVariable *gv = new GlobalVariable(*mainmodule, matrixType, - false, GlobalValue::InternalLinkage, - ConstantArray::get(matrixType, constantRefs), name); - alloc = gv; - - if (debug_info) { - auto di_ptr = DBuilder->createPointerType(buildTypes->diType(element_dt), - buildTypes->bitWidth(currentTarget().pointerType)); - auto *d = DBuilder->createGlobalVariableExpression(sp, name, "", - funit, this->getLineNo(), di_ptr, false); - gv->addDebugInfo(d); - } - - } else { - Builder->SetInsertPoint(allocblock); - - if (getGEPIndex() != -1) - alloc = getLLVMValue(func); - else { - alloc = Builder->CreateAlloca(matrixType, dataAddrSpace, 0, name); - if (debug_info) { - RobDbgInfo.emitLocation(this); - RobDbgInfo.declareVar(this, alloc, allocblock); - } - } - - RobDbgInfo.emitLocation(this); - Builder->SetInsertPoint(block); - - Value *zero = ConstantInt::get(Type::getInt8Ty(global_context), 0); - StoreInst *store = NULL; - for(unsigned index = 0; index < elementValues.size(); index++) { - Value *idx = ConstantInt::get(Type::getInt32Ty(global_context), index); - Value* indexList[2] = {zero, idx}; - Value* gep = Builder->CreateGEP(matrixType, alloc, - ArrayRef(indexList), "elem"); - store = Builder->CreateStore(elementValues[index], gep, false); - } - } - - return alloc; } Node* Matrix::accept(Visitor& v) { return v.visit(*this); } - -DataType Matrix::getDataType() { - if (matrixType == NULL) - createDataType(); - return dt; -} - void Matrix::createDataType() { - if (matrixType != NULL) + if (arrayType != NULL) return; //Get Type of elements in Vector of Elements, and define as I. @@ -123,14 +33,15 @@ void Matrix::createDataType() { dt = buildTypes->getArrayType(buildTypes->name(element_dt), this->getLoc(), 2, true); Type* I = buildTypes->llvmType(element_dt); - + if (buildTypes->isComplex(element_dt)) { + // in rob, all matrices of user types (complex types) + // are matrices of references + I = I->getPointerTo(codeAddrSpace); + } + // The matrix type and size rows = melements->getRowCount(); cols = melements->getColumnCount(); - matrixType = ArrayType::get(I, rows * cols); -} - -Type* Matrix::getLLVMType() { - createDataType(); - return matrixType; + size = rows * cols; + arrayType = ArrayType::get(I, size); } diff --git a/src/Matrix.h b/src/Matrix.h index 31456f3..a4fbb54 100644 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -1,47 +1,37 @@ #pragma once +#include "Array.h" #include "MatrixElements.h" #include "Variable.h" -class ParamMatrix: public Variable { -private: - DataType element_dt; +class ParamMatrix: public ParamArray { public: - ParamMatrix(const string& n, string element_dt_name, location_t loc): Variable(n, loc) { - this->element_dt = buildTypes->getType(element_dt_name, true); - this->dt = buildTypes->getArrayType(element_dt_name, loc, 2, true); + ParamMatrix(const string& n, string element_dt_name, location_t loc): ParamArray(n, element_dt_name, loc) {} + + virtual int getDimensions() override { + return 2; } }; -class Matrix: public Variable { +class Matrix: public Array { private: MatrixElements *melements; - ArrayType *matrixType = NULL; - DataType element_dt; - void createDataType(); unsigned int rows = 0; unsigned int cols = 0; + +protected: + virtual void createDataType() override; public: Matrix(const char *n, MatrixElements *me, location_t loc); - virtual Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; - - std::vector const& getElements() { + std::vector const& getMatrixElements() { return melements->getElements(); } Node* accept(Visitor& v) override; - virtual Type *getLLVMType() override; - - DataType getDataType() override; - - DataType getElementDataType() { - return element_dt; - } - int getRows() const { return rows; } diff --git a/src/MatrixElements.cpp b/src/MatrixElements.cpp index 0707023..58a118c 100644 --- a/src/MatrixElements.cpp +++ b/src/MatrixElements.cpp @@ -30,9 +30,7 @@ unsigned MatrixElements::getColumnCount() { DataType MatrixElements::getMatrixType() { set types; for(auto& j : elements) { - for (auto& i : j->array->getElements()) { - types.emplace(i->value->getDataType()); - } + types.emplace(j->array->getArrayType()); } return ArrayElements::getArrayConstType(types, &location); } diff --git a/src/MemCopy.cpp b/src/MemCopy.cpp index 7b6adec..e2fb7b9 100644 --- a/src/MemCopy.cpp +++ b/src/MemCopy.cpp @@ -4,10 +4,6 @@ #include "BackLLVM.h" #include "FunctionImpl.h" -void MemCopy::setLeftValue(Variable *symbol) { - leftValue = symbol; -} - Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { RobDbgInfo.emitLocation(this); @@ -55,7 +51,12 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo // Prepare dest memory Type *leftvty; - Value *dest = leftValue->getLLVMValue(func); + Value *dest; + if (leftGEP) + dest = leftGEP; + else + dest = leftValue->getLLVMValue(func); + if (dest) { leftvty = dest->getType(); //FIXME: must check the alloc size for array and matrix diff --git a/src/MemCopy.h b/src/MemCopy.h index ad1dde1..d54d49b 100644 --- a/src/MemCopy.h +++ b/src/MemCopy.h @@ -5,18 +5,31 @@ #include "Variable.h" #include "semantic/Visitor.h" -class MemCopy: public Node { +class Constructor: public Node { +protected: + Variable *leftValue = NULL; + Value *leftGEP = NULL; +public: + Constructor(location_t l): Node(l) {} + + virtual void setLeftValue(Variable *symbol) override { + leftValue = symbol; + } + + virtual void setLeftGEP(Value *gep) { + leftGEP = gep; + } +}; + +class MemCopy: public Constructor { private: Node *expr; - Variable *leftValue = NULL; public: - MemCopy(Node *expr): Node(expr->getLoc()) { + MemCopy(Node *expr): expr(expr), Constructor(expr->getLoc()) { addChild(expr); this->expr = expr; } - - virtual void setLeftValue(Variable *symbol) override; virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; diff --git a/src/semantic/PropagateTypes.cpp b/src/semantic/PropagateTypes.cpp index d7fe0d2..89679be 100644 --- a/src/semantic/PropagateTypes.cpp +++ b/src/semantic/PropagateTypes.cpp @@ -42,7 +42,10 @@ Node* PropagateTypes::coerceToUserTypes(Node *n, const DataType destTy) { Node* PropagateTypes::coerceTo(Node *n, const DataType destTy, bool warns) { if (isUndefined(n)) return NULL; + DataType valueTy = n->getDataType(); + if (valueTy == destTy) + return n; // can coerce only between numeric types bool lIsNumeric = buildTypes->isNumericDataType(destTy); @@ -372,7 +375,7 @@ Node* PropagateTypes::visit(FunctionCall& fc) { Node* PropagateTypes::visit(Matrix& n) { // visit elements to propagate their types - for(MatrixElement *me : n.getElements()) { + for(MatrixElement *me : n.getMatrixElements()) { for(ArrayElement *k: me->array->getElements()) { Node *aux = k->value->accept(*this); if (aux) @@ -385,7 +388,7 @@ Node* PropagateTypes::visit(Matrix& n) { DataType edt = n.getElementDataType(); // visit elements to sext or zext their values - for(MatrixElement *me : n.getElements()) { + for(MatrixElement *me : n.getMatrixElements()) { for(ArrayElement *k: me->array->getElements()) { k->value = coerceTo(k->value, edt); } diff --git a/src/semantic/SymbolizeTree.h b/src/semantic/SymbolizeTree.h index 08fd8a4..2dd0e7c 100644 --- a/src/semantic/SymbolizeTree.h +++ b/src/semantic/SymbolizeTree.h @@ -47,7 +47,7 @@ class SymbolizeTree: public Visitor { n.addSymbol(dynamic_cast(c)); } } - for(MatrixElement *i: n.getElements()) { + for(MatrixElement *i: n.getMatrixElements()) { for(ArrayElement *e: i->array->getElements()) { e->value->setScope(&n); e->value->accept(*this); diff --git a/test/general/matrix_of_type.rob b/test/general/matrix_of_type.rob new file mode 100644 index 0000000..37f313e --- /dev/null +++ b/test/general/matrix_of_type.rob @@ -0,0 +1,83 @@ + +type element { + fa = int16(0); +} + +int16 check(element[][] x) { + values = {10, 20, 30, 40}; + i = 0; + v = 0; + while i < x.rows { + j = 0; + while j < x.cols { + xx = x[i][j]; + if xx.fa != values[v] { + return v+1; + } + v++; + j++; + } + i++; + } + return 0; +} + +int16 test_matrix_of_instances() { + x2 = element(); + x2.fa = 30; + + x3 = element(); + x3.fa = 40; + + x = {{element():2}, {copy(x2), copy(x3)}}; + + x0 = x[0][0]; + x0.fa = 10; + + x1 = x[0][1]; + x1.fa = 20; + + return check(x); +} + +int16 test_matrix_of_pointers() { + x0 = element(); + x1 = element(); + + x2 = element(); + x2.fa = 30; + + x3 = element(); + x3.fa = 50; + + // this will be a vector of references to element + x = {{x0, x1}, {x2, x3}}; + + x0 = x[0][0]; + x0.fa = 10; + + x1 = x[0][1]; + x1.fa = 20; + + // test update of an element + x3_copy = element(); + x3_copy.fa = 40; + x[1][1] = x3_copy; + + return check(x); +} + +int16 main() { + vi = test_matrix_of_instances(); + if vi != 0 { + return vi; + } + + vp = test_matrix_of_pointers(); + if vp != 0 { + return vp; + } + + return 0; +} + diff --git a/test/general/vector_of_type.rob b/test/general/vector_of_type.rob new file mode 100644 index 0000000..72d5765 --- /dev/null +++ b/test/general/vector_of_type.rob @@ -0,0 +1,76 @@ + +type element { + fa = int16(0); +} + +int16 check(element[] x) { + i = 0; + while i < x.size { + xx = x[i]; + if xx.fa != (i+1)*10 { + return i+1; + } + i++; + } + return 0; +} + +int16 test_vector_of_instances() { + x2 = element(); + x2.fa = 30; + + x3 = element(); + x3.fa = 40; + + x = {element():2, copy(x2), copy(x3)}; + + x0 = x[0]; + x0.fa = 10; + + x1 = x[1]; + x1.fa = 20; + + return check(x); +} + +int16 test_vector_of_pointers() { + x0 = element(); + x1 = element(); + + x2 = element(); + x2.fa = 30; + + x3 = element(); + x3.fa = 50; + + // this will be a vector of references to element + x = {x0, x1, x2, x3}; + + x0 = x[0]; + x0.fa = 10; + + x1 = x[1]; + x1.fa = 20; + + // test update of an element + x3_copy = element(); + x3_copy.fa = 40; + x[3] = x3_copy; + + return check(x); +} + +int16 main() { + vi = test_vector_of_instances(); + if vi != 0 { + return vi; + } + + vp = test_vector_of_pointers(); + if vp != 0 { + return vp; + } + + return 0; +} + From a7f9af1b75da3063f236744eee8238a161d3587a Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 22 Jun 2025 14:57:15 -0300 Subject: [PATCH 109/117] Silent LLVM20 messages about getPointerTo. --- src/Array.cpp | 2 +- src/BuildTypes.cpp | 6 +++--- src/ConstructorCall.cpp | 7 ++++--- src/FunctionCall.cpp | 2 +- src/FunctionDecl.cpp | 4 ++-- src/FunctionImpl.cpp | 4 ++-- src/Load.cpp | 6 +++--- src/LoadArray.cpp | 4 ++-- src/Matrix.cpp | 2 +- src/MemCopy.cpp | 2 +- src/Node.cpp | 2 +- src/Pointer.cpp | 2 +- src/Program.cpp | 3 ++- src/Scalar.cpp | 4 ++-- src/UpdateArray.cpp | 2 +- src/UserType.cpp | 2 +- src/Variable.cpp | 8 ++++---- src/ZeroInit.h | 2 +- 18 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/Array.cpp b/src/Array.cpp index e911427..9aa62cb 100644 --- a/src/Array.cpp +++ b/src/Array.cpp @@ -39,7 +39,7 @@ void Array::createDataType() { if (buildTypes->isComplex(element_dt)) { // in rob, all arrays of user types (complex types) // are array of references - I = I->getPointerTo(codeAddrSpace); + I = PointerType::getUnqual(I); } //Declare array type. diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 8262a94..5977d59 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -42,7 +42,7 @@ BuildTypes::BuildTypes(DataType targetPointerType, Program *program) : tinfo[tldouble] = {"ldouble", 128, Type::getFP128Ty(global_context), dwarf::DW_ATE_float}; // a generic internal pointer - tinfo[tobject] = {"object", pts, Type::getVoidTy(global_context)->getPointerTo(), dwarf::DW_ATE_address}; + tinfo[tobject] = {"object", pts, PointerType::getUnqual(Type::getVoidTy(global_context)), dwarf::DW_ATE_address}; tinfo[tobject].isComplex = true; const DataLayout &dl = mainmodule->getDataLayout(); @@ -83,7 +83,7 @@ DataType BuildTypes::getArrayType(const string& elementName, SourceLocation n, Type *I = elementInfo.llvmType; if (elementInfo.isComplex) { // In rob, any array of complex types is an array of refs - I = elementInfo.llvmType->getPointerTo(); + I = PointerType::getUnqual(elementInfo.llvmType); } // we don't know the array size at compile time info.llvmType = ArrayType::get(I, 0); @@ -225,7 +225,7 @@ void BuildTypes::generateDebugInfoForUserType(DataTypeInfo &info, Node *userType DIType *memberDiType = diType(mdt); if (Variable *v = dynamic_cast(m)) { if (v->getPointerMode() == pm_pointer) { - memberTy = memberTy->getPointerTo(); + memberTy = PointerType::getUnqual(memberTy); memberDiType = diPointerType(mdt); if (!memberDiType) { // parent field diff --git a/src/ConstructorCall.cpp b/src/ConstructorCall.cpp index 99625b5..ae56f26 100644 --- a/src/ConstructorCall.cpp +++ b/src/ConstructorCall.cpp @@ -27,13 +27,14 @@ Value* ConstructorCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlo // is a new left var Type *vty = buildTypes->llvmType(dt); if (buildTypes->isInterface(dt)) { - vty = vty->getPointerTo(); + vty = PointerType::getUnqual(vty); leftValue->setPointerToPointer(true); } Builder->SetInsertPoint(allocblock); if (allocblock == global_alloc) { //Constant *init = ConstantAggregateZero::get(buildTypes->llvmType(dt)); - Constant *init = ConstantPointerNull::get(buildTypes->llvmType(dt)->getPointerTo()); + PointerType *dtPointerTy = PointerType::getUnqual(buildTypes->llvmType(dt)); + Constant *init = ConstantPointerNull::get(dtPointerTy); gv = new GlobalVariable(*mainmodule, vty, hasQualifier(qconst), GlobalValue::ExternalLinkage, init, leftValue->getName()); var = gv; @@ -92,7 +93,7 @@ Value* ConstructorCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlo if (initfunc->needsParent()) { Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); - Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + Value *ptr = Builder->CreateLoad(PointerType::getUnqual(thisTy), func->getThisArg(), "derefthis"); args.push_back(ptr); } diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 82fcc1e..0d8397b 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -155,7 +155,7 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock } else if (fsymbol->getThisArgDt() != BuildTypes::undefinedType) { // calling a function of the type itself, without stem Type *thisTy = buildTypes->llvmType(func->getThisArgDt()); - Value *ptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + Value *ptr = Builder->CreateLoad(PointerType::getUnqual(thisTy), func->getThisArg(), "derefthis"); args.push_back(ptr); dataTypes.push_back(fsymbol->getThisArgDt()); } diff --git a/src/FunctionDecl.cpp b/src/FunctionDecl.cpp index aacd286..cfc6b05 100644 --- a/src/FunctionDecl.cpp +++ b/src/FunctionDecl.cpp @@ -29,7 +29,7 @@ bool FunctionBase::validateAndGetArgsTypes(std::vector &argsty) { valid = false; } else { if (buildTypes->isComplex(dt) || buildTypes->isArrayOrMatrix(dt)) { - atype = atype->getPointerTo(); + atype = PointerType::getUnqual(atype); } argsty.push_back(atype); } @@ -140,7 +140,7 @@ Value *FunctionDecl::generate(FunctionImpl*, BasicBlock *, BasicBlock *allocbloc Type *xtype = buildTypes->llvmType(dt); if (returnIsPointer) - xtype = xtype->getPointerTo(); + xtype = PointerType::getUnqual(xtype); FunctionType *ftype = FunctionType::get(xtype, ArrayRef(arg_types), false); Function *nfunc = Function::Create(ftype, linkage, codeAddrSpace, getFinalName(), mainmodule); diff --git a/src/FunctionImpl.cpp b/src/FunctionImpl.cpp index fed12be..eb99c06 100644 --- a/src/FunctionImpl.cpp +++ b/src/FunctionImpl.cpp @@ -27,7 +27,7 @@ bool FunctionImpl::preGenerate() { Type *xtype = buildTypes->llvmType(dt); if (returnIsPointer) - xtype = xtype->getPointerTo(); + xtype = PointerType::getUnqual(xtype); if (fsymbol) { validateImplementation(fsymbol); @@ -88,7 +88,7 @@ bool FunctionImpl::preGenerate() { Type *talloc = buildTypes->llvmType(ptype); if (buildTypes->isComplex(ptype) || buildTypes->isArrayOrMatrix(ptype)) { - talloc = talloc->getPointerTo(); + talloc = PointerType::getUnqual(talloc); fp->setPointerToPointer(true); } Value *variable = Builder->CreateAlloca(talloc, dataAddrSpace, 0, argname); diff --git a/src/Load.cpp b/src/Load.cpp index 3dd7263..3b1eca3 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -105,7 +105,7 @@ Value* Load::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl DataType sdt = symbol->getDataType(); if (buildTypes->isComplex(sdt) || buildTypes->isArrayOrMatrix(sdt)) { if (symbol->isPointerToPointer()) { - Type *ty = buildTypes->llvmType(sdt)->getPointerTo(); + Type *ty = PointerType::getUnqual(buildTypes->llvmType(sdt)); alloc = Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); } if (leftValue) @@ -136,7 +136,7 @@ Value* Load::getRecursiveField(Identifier &ident, Node *scope, FunctionImpl *fun Value *alloc = first->getLLVMValue(func); Type *udt = buildTypes->llvmType(first->getDataType()); if (first->isPointerToPointer()) { - alloc = Builder->CreateLoad(udt->getPointerTo(), alloc, "deref"); + alloc = Builder->CreateLoad(PointerType::getUnqual(udt), alloc, "deref"); } for(auto &x : symbols) { @@ -144,7 +144,7 @@ Value* Load::getRecursiveField(Identifier &ident, Node *scope, FunctionImpl *fun if (var) { int gepidx = var->getGEPIndex(); if (var->isPointerToPointer()) { - alloc = Builder->CreateLoad(udt->getPointerTo(), alloc, "deref"); + alloc = Builder->CreateLoad(PointerType::getUnqual(udt), alloc, "deref"); } alloc = Builder->CreateStructGEP(udt, alloc, gepidx, x->getName()); udt = buildTypes->llvmType(var->getDataType()); diff --git a/src/LoadArray.cpp b/src/LoadArray.cpp index 8f91587..cf001a1 100644 --- a/src/LoadArray.cpp +++ b/src/LoadArray.cpp @@ -65,7 +65,7 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al } if (!ident.isComplex() && symbol->isPointerToPointer()) { - Type *ty = buildTypes->llvmType(symbol->getDataType())->getPointerTo(); + Type *ty = PointerType::getUnqual(buildTypes->llvmType(symbol->getDataType())); alloc = Builder->CreateLoad(ty, alloc, symbol->hasQualifier(qvolatile), "deref"); } @@ -80,7 +80,7 @@ Value *LoadArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *al if (leftValue) { leftValue->setPointerToPointer(true); } - elemType = elemType->getPointerTo(); + elemType = PointerType::getUnqual(elemType); } LoadInst *ret = Builder->CreateLoad(elemType, ptr, ident.getFullName()); diff --git a/src/Matrix.cpp b/src/Matrix.cpp index 25e7860..4e40f55 100644 --- a/src/Matrix.cpp +++ b/src/Matrix.cpp @@ -36,7 +36,7 @@ void Matrix::createDataType() { if (buildTypes->isComplex(element_dt)) { // in rob, all matrices of user types (complex types) // are matrices of references - I = I->getPointerTo(codeAddrSpace); + I = PointerType::getUnqual(I); } // The matrix type and size diff --git a/src/MemCopy.cpp b/src/MemCopy.cpp index e2fb7b9..09779ef 100644 --- a/src/MemCopy.cpp +++ b/src/MemCopy.cpp @@ -65,7 +65,7 @@ Value* MemCopy::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo if (buildTypes->isArrayOrMatrix(dt)) { DataType eldt = buildTypes->getArrayElementType(dt); dest = Builder->CreateAlloca(buildTypes->llvmType(eldt), dataAddrSpace, nelem, leftValue->getName()); - leftvty = buildTypes->llvmType(dt)->getPointerTo(); + leftvty = PointerType::getUnqual(buildTypes->llvmType(dt)); } else { leftvty = buildTypes->llvmType(dt); dest = Builder->CreateAlloca(buildTypes->llvmType(dt), dataAddrSpace, nelem, leftValue->getName()); diff --git a/src/Node.cpp b/src/Node.cpp index c3f8011..e88563c 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -113,7 +113,7 @@ Type* Node::getLLVMType() { DataType aux = getDataType(); Type *taux = buildTypes->llvmType(getDataType()); if (buildTypes->isInterface(aux)) - return taux->getPointerTo(); + return PointerType::getUnqual(taux); else return taux; } diff --git a/src/Pointer.cpp b/src/Pointer.cpp index f86900a..aa34647 100644 --- a/src/Pointer.cpp +++ b/src/Pointer.cpp @@ -32,7 +32,7 @@ Value *Pointer::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allo return NULL; } - Type *targetPointerType = buildTypes->llvmType(dt)->getPointerTo(); + Type *targetPointerType = PointerType::getUnqual(buildTypes->llvmType(dt)); // In favor of faster and smaller code size, we return the pointer // as a ConstantExpr. This limits pointer arithmetic. diff --git a/src/Program.cpp b/src/Program.cpp index 3bad6f1..02cc660 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -194,7 +194,8 @@ void Program::generateBuiltins() { Builder->SetInsertPoint(body); auto& Arg = *typeidFunc->args().begin(); Arg.addAttr(Attribute::ReadOnly); - auto *CmpVoid = Builder->CreateCmp(FCmpInst::ICMP_EQ, &Arg, ConstantPointerNull::get(Arg.getType()->getPointerTo())); + auto *CmpVoid = Builder->CreateCmp(FCmpInst::ICMP_EQ, &Arg, + ConstantPointerNull::get(PointerType::getUnqual(Arg.getType()))); // if pointer is not set, return zero/void BasicBlock *returnVoid = BasicBlock::Create(global_context, "", typeidFunc); diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 00f442d..3859cff 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -84,7 +84,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Type *gty = buildTypes->llvmType(dt); if (expr->isPointerToPointer()) { setPointerToPointer(true); - gty = gty->getPointerTo(); + gty = PointerType::getUnqual(gty); } GlobalVariable *gv = new GlobalVariable(*mainmodule, gty, hasQualifier(qconst), GlobalValue::ExternalLinkage, exprvc, name); @@ -133,7 +133,7 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Type *currty = buildTypes->llvmType(currdt); if (pm == pm_pointer) - currty = currty->getPointerTo(); + currty = PointerType::getUnqual(currty); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(allocblock == global_alloc ? global_alloc : block); diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index 6302dae..3e75c6b 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -59,7 +59,7 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * Builder->SetInsertPoint(block); if (symbol->isPointerToPointer()) { - Type *ty = buildTypes->llvmType(symbol->getDataType())->getPointerTo(); + Type *ty = PointerType::getUnqual(buildTypes->llvmType(symbol->getDataType())); sym = Builder->CreateLoad(ty, sym, symbol->hasQualifier(qvolatile), "deref"); } diff --git a/src/UserType.cpp b/src/UserType.cpp index be7f7e8..0651708 100644 --- a/src/UserType.cpp +++ b/src/UserType.cpp @@ -33,7 +33,7 @@ class ParentScalar: public Scalar { return dt; } virtual Type* getLLVMType() override { - return PointerType::get(global_context, dataAddrSpace); + return PointerType::getUnqual(global_context); } }; diff --git a/src/Variable.cpp b/src/Variable.cpp index 5c85736..08af555 100644 --- a/src/Variable.cpp +++ b/src/Variable.cpp @@ -15,7 +15,7 @@ Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { // generating a function of a type: get the gep on _this or _parent parameters DataType thisDt = func->getThisArgDt(); Type *thisTy = buildTypes->llvmType(thisDt); - Value *thisptr = Builder->CreateLoad(thisTy->getPointerTo(), func->getThisArg(), "derefthis"); + Value *thisptr = Builder->CreateLoad(PointerType::getUnqual(thisTy), func->getThisArg(), "derefthis"); if (!stem->getScope() || this->getScope() == stem->getScope()) { // the var is being accessed in global scope (!stem->getScope()) or @@ -32,7 +32,7 @@ Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { parentscalar->setUsed(true); int idxParentInThis = static_cast(parent)->getGEPIndex(); Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, idxParentInThis, "gepthis"); - Value *parentptr = Builder->CreateLoad(parentTy->getPointerTo(), parentAlloc, "derefparent"); + Value *parentptr = Builder->CreateLoad(PointerType::getUnqual(parentTy), parentAlloc, "derefparent"); return Builder->CreateStructGEP(parentTy, parentptr, gepidx, "gep" + getName()); } else { @@ -47,7 +47,7 @@ Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { int idxParentInThis = parentFieldVar->getGEPIndex(); Type *parentTy = buildTypes->llvmType(parentFieldVar->getDataType()); Value *parentAlloc = Builder->CreateStructGEP(parentTy, thisptr, idxParentInThis, "gepparent"); - Value *parentptr = Builder->CreateLoad(parentTy->getPointerTo(), parentAlloc, "derefparent"); + Value *parentptr = Builder->CreateLoad(PointerType::getUnqual(parentTy), parentAlloc, "derefparent"); return Builder->CreateStructGEP(parentTy, parentptr, gepidx, "gep" + getName()); } } else { @@ -55,7 +55,7 @@ Value *Variable::getLLVMValue(Node *stem, FunctionImpl *gfunc) { Type *udt = buildTypes->llvmType(stem->getDataType()); Value *ptr = stem->getLLVMValue(gfunc); if (stem->isPointerToPointer()) { - ptr = Builder->CreateLoad(udt->getPointerTo(), ptr, "deref"); + ptr = Builder->CreateLoad(PointerType::getUnqual(udt), ptr, "deref"); } return Builder->CreateStructGEP(udt, ptr, gepidx, "gepu"); } diff --git a/src/ZeroInit.h b/src/ZeroInit.h index a64f81d..b9c66c4 100644 --- a/src/ZeroInit.h +++ b/src/ZeroInit.h @@ -13,7 +13,7 @@ class ZeroInit: public Node { virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { return ConstantAggregateZero::get(buildTypes->llvmType(dt)); - //return ConstantPointerNull::get(buildTypes->llvmType(dt)->getPointerTo()); + //return ConstantPointerNull::get(PointerType::getUnqual(buildTypes->llvmType(dt))); } virtual bool isConstExpr() override { From f0955ab6e86ffde6c39cdda442ef1c1d102f94b2 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 15 Jun 2025 12:40:22 -0300 Subject: [PATCH 110/117] Support raspberry pico rp2040: blink led working --- lib/arch/Makefile | 22 + lib/arch/README | 6 + lib/arch/rp/rp2040/boot2.o | Bin 0 -> 888 bytes lib/arch/rp/rp2040/init.rob | 95 + lib/arch/rp/rp2040/mcu.rob | 86 + lib/arch/rp/rp2040/regs.rob | 12978 ++++++++ lib/arch/rp/rp2040/rp2040.ld | 87 + lib/arch/rp/rp2040/rp2040.svd | 51245 ++++++++++++++++++++++++++++++++ lib/arch/svd2rob.py | 263 + src/BackLLVM.cpp | 2 + src/BackLLVM.h | 3 + src/BuildTypes.cpp | 20 + src/BuildTypes.h | 7 +- test/rp2040/Makefile | 57 + test/rp2040/blink.rob | 20 + test/rp2040/runtest.sh | 27 + 16 files changed, 64916 insertions(+), 2 deletions(-) create mode 100644 lib/arch/Makefile create mode 100644 lib/arch/README create mode 100755 lib/arch/rp/rp2040/boot2.o create mode 100644 lib/arch/rp/rp2040/init.rob create mode 100644 lib/arch/rp/rp2040/mcu.rob create mode 100644 lib/arch/rp/rp2040/regs.rob create mode 100644 lib/arch/rp/rp2040/rp2040.ld create mode 100644 lib/arch/rp/rp2040/rp2040.svd create mode 100644 lib/arch/svd2rob.py create mode 100644 test/rp2040/Makefile create mode 100644 test/rp2040/blink.rob create mode 100755 test/rp2040/runtest.sh diff --git a/lib/arch/Makefile b/lib/arch/Makefile new file mode 100644 index 0000000..0f3c346 --- /dev/null +++ b/lib/arch/Makefile @@ -0,0 +1,22 @@ +ATDF=$(shell find . -type f -name '*.atdf') +GEN_SVDS=$(patsubst %.atdf,%.svd,$(ATDF)) + +SVD := $(shell find . -type f -name '*.svd') +DIRS := $(sort $(dir $(SVD))) +ALL_ROBS := $(foreach d,$(DIRS),$(d)regs.rob) + +all: pre $(ALL_ROBS) + +pre: $(GEN_SVDS) + +.SECONDARY: +%.svd : %.atdf + atdf2svd $< > $@ + +define SVD_template +$(1)regs.rob: $(wildcard $(1)*.svd) svd2rob.py + python3 svd2rob.py $$< > $$@ +endef + +$(foreach d,$(DIRS),$(eval $(call SVD_template,$(d)))) + diff --git a/lib/arch/README b/lib/arch/README new file mode 100644 index 0000000..42660e7 --- /dev/null +++ b/lib/arch/README @@ -0,0 +1,6 @@ +AFDT files for AVRs +- http://packs.download.atmel.com +- To convert from .afdt to .svd, use atdf2svd from Rust language, available through cargo install + +SVDs files for STM32 can be downloaded at: +- https://www.st.com/en/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus.html#cad-resources under System View Description diff --git a/lib/arch/rp/rp2040/boot2.o b/lib/arch/rp/rp2040/boot2.o new file mode 100755 index 0000000000000000000000000000000000000000..a167ee0017bc8a8c17b22b167716abd018e023ec GIT binary patch literal 888 zcmah{J#Q015Pf@RJ74^;_Rxmt&7h0{^eBP0uuI7AWNo^SnCz?|l0X5X9Ho!Nc+;L$@N1dIr*ViExvD?*aR z$gCm_2k39?%6!c~Ik4n$`NaS1yFo4Rb|HJdCHDd$hlSpgwMy0(T)CUa@P23&-j|jJ zDVc3zSPZi*p}oA@Tw%P7BWW%tzGA%X|a~X+gnCv8QV;}Ikub-=+POCa2dtf}CPr=&{Q~3WW&auEi0U>|F>CZbCMl*PJu1yJ9nJI1sBV(Om-S!X zdR%X2UsEK;Xs}7;o-eeorAQ91b}S}ETXR+o*0`XP_!=VBlg?1nRMP`poRc?w3#Q)H OIo>A%Wt|X<;r#{mn`|8b literal 0 HcmV?d00001 diff --git a/lib/arch/rp/rp2040/init.rob b/lib/arch/rp/rp2040/init.rob new file mode 100644 index 0000000..de469d3 --- /dev/null +++ b/lib/arch/rp/rp2040/init.rob @@ -0,0 +1,95 @@ +/* + * Robcmp bare-metal routines for rp2040 + */ + +use regs; +//use math.limits; + +int16 main(); + +void __system_config() { + // set vtor table offset from __start symbol of linker + /*asm "LDR R0, =__isr_start"; + asm "LDR R1, =0xE000ED08"; + asm "STR R0, [R1]";*/ + + // disable Watchdog + //WATCHDOG_CTRL.ENABLE = false; + //WATCHDOG_CTRL.TIME = 0; + + //ROSC_CTRL.ENABLE = 0xfab; + //CLK_SYS_CTRL.SRC = 0x1; // CLKSRC_CLK_SYS_AUX + //CLK_SYS_CTRL.AUXSRC = 0x2; // ROSC_CLKSRC + //while (CLK_SYS_SELECTED.CLK_SYS_SELECTED & 0x7) != 1; + + RESET.IO_BANK0 = false; + RESET.PADS_BANK0 = false; + while !RESET_DONE.IO_BANK0; + while !RESET_DONE.PADS_BANK0; +} + +void __error_handler() { + asm "bkpt #0"; // breakpoint +} + +void __enter_vtable_in_r0() naked { + + //#define PPB_BASE _u(0xe0000000) + //#define M0PLUS_VTOR_OFFSET _u(0x0000ed08) + //ldr r1, =(PPB_BASE + ARM_CPU_PREFIXED(VTOR_OFFSET)) + asm "ldr r1, =0xe000ed08 + str r0, [r1] + ldmia r0!, {r1, r2} + msr msp, r1 + bx r2 + "; +} + +void __do_copy_data_and_bss() noinline { +// TODO: Improve __do_copy_data, this is a copy of stm32f1 +asm + "movs r1, #0 + b __do_copy_data_start + __do_copy_data_loop: + ldr r3, =__data_init + ldr r3, [r3, r1] + str r3, [r0, r1] + adds r1, r1, #4 + __do_copy_data_start: + ldr r0, =__data_start + ldr r3, =__data_end + adds r2, r0, r1 + cmp r2, r3 + bcc __do_copy_data_loop + ldr r1, =__bss_start + ldr r2, =__bss_end + movs r0, #0 + b __do_clear_bss_start + __do_clear_bss_loop: + stm r1!, {r0} + __do_clear_bss_start: + cmp r1, r2 + bcc __do_clear_bss_loop"; +} + +void __isr_reset() naked { + // check if core 1 is sleeping in the bootrom + // xx = (SIO_BASE) 0xd0000000 + SIO_CPUID_OFFSET 0x00000000 + // value of xx is 0 when read from processor core 0, and 1 when read from processor core 1 + asm "ldr r0, =0xd0000000 + ldr r0, [r0] + cmp r0, #0 + beq 1f + hold_non_core0_in_bootrom: + ldr r0, #0 //BOOTROM_VTABLE_OFFSET + b __enter_vtable_in_r0 + 1: "; + + __do_copy_data_and_bss(); + + __system_config(); + + ret = main(); + + __error_handler(); +} diff --git a/lib/arch/rp/rp2040/mcu.rob b/lib/arch/rp/rp2040/mcu.rob new file mode 100644 index 0000000..3cc8e74 --- /dev/null +++ b/lib/arch/rp/rp2040/mcu.rob @@ -0,0 +1,86 @@ + +use intfs.mcu; +use intfs.ports; +use intfs.databus; + +use regs; + +type rp2040mcu implements mcu { + + uint32 clock() inline { + // 133Mhz + return 133E6; + } + + void set_interruptions(bool enabled) { + return; + } + + io24 implements digitalport { + void mode(port_mode m) { + GPIO24_CTRL.FUNCSEL = 5; + GPIO24.SLEWFAST = true; + GPIO24.SCHMITT = true; + GPIO24.OD = false; + if m == port_mode.input { + GPIO_OE.IO24 = false; + GPIO24.IE = true; + GPIO24.DRIVE = 0; + } else { + GPIO_OE.IO24 = true; + GPIO24.IE = false; + GPIO24.DRIVE = 3; + } + } + void set(bool v) { + if (v) { GPIO_OUT_SET.IO24 = true; } + else { GPIO_OUT_CLR.IO24 = true; } + } + bool get() { return GPIO_IN.IO24; } + } + + io25 implements digitalport { + void mode(port_mode m) { + GPIO25_CTRL.FUNCSEL = 5; + GPIO25.SLEWFAST = true; + GPIO25.SCHMITT = true; + GPIO25.OD = false; + if m == port_mode.input { + GPIO_OE.IO25 = false; + GPIO25.IE = true; + GPIO25.DRIVE = 0; + } else { + GPIO_OE.IO25 = true; + GPIO25.IE = false; + GPIO25.DRIVE = 3; + } + } + void set(bool v) { + if (v) { GPIO_OUT_SET.IO25 = true; } + else { GPIO_OUT_CLR.IO25 = true; } + } + bool get() { return GPIO_IN.IO25; } + } + + void wait_us(uint16 us) { + volatile x = us; + while x > 0 { + x--; + } + } + + void wait_ms(uint16 ms) { + while ms > 0 { + wait_us(1000); + ms--; + } + } + + uint32 micros() { + return 0; + } + + uint32 millis() { + return micros() / 1000; + } +} diff --git a/lib/arch/rp/rp2040/regs.rob b/lib/arch/rp/rp2040/regs.rob new file mode 100644 index 0000000..48a058a --- /dev/null +++ b/lib/arch/rp/rp2040/regs.rob @@ -0,0 +1,12978 @@ + +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + * + * This file was machine generated from rp/rp2040/rp2040.svd. Don't edit. + */ + +/* + vendor: Raspberry Pi + name: RP2040 + series: RP + version: 0.1 + description: + Dual-core Arm Cortex-M0+ processor, flexible clock running up to 133 MHz + 264KB on-chip SRAM + 2 x UART, 2 x SPI controllers, 2 x I2C controllers, 16 x PWM channels + 1 x USB 1.1 controller and PHY, with host and device support + 8 x Programmable I/O (PIO) state machines for custom peripheral support + Supported input power 1.8-5.5V DC + Operating temperature -20C to +85C + Drag-and-drop programming using mass storage over USB + Low-power sleep and dormant modes + Accurate on-chip clock + Temperature sensor + Accelerated integer and floating-point libraries on-chip + +*/ + +/* Types and registers for RESETS */ + + type RESET_t { + ADC = false; // + BUSCTRL = false; // + DMA = false; // + I2C0 = false; // + I2C1 = false; // + IO_BANK0 = false; // + IO_QSPI = false; // + JTAG = false; // + PADS_BANK0 = false; // + PADS_QSPI = false; // + PIO0 = false; // + PIO1 = false; // + PLL_SYS = false; // + PLL_USB = false; // + PWM = false; // + RTC = false; // + SPI0 = false; // + SPI1 = false; // + SYSCFG = false; // + SYSINFO = false; // + TBMAN = false; // + TIMER = false; // + UART0 = false; // + UART1 = false; // + USBCTRL = false; // + } + + // Reset control. If a bit is set it means the peripheral is in reset. 0 means the peripheral's reset is deasserted. + register RESET_t RESET at 0x4000c000; + + type RESETS_WDSEL_t { + ADC = false; // + BUSCTRL = false; // + DMA = false; // + I2C0 = false; // + I2C1 = false; // + IO_BANK0 = false; // + IO_QSPI = false; // + JTAG = false; // + PADS_BANK0 = false; // + PADS_QSPI = false; // + PIO0 = false; // + PIO1 = false; // + PLL_SYS = false; // + PLL_USB = false; // + PWM = false; // + RTC = false; // + SPI0 = false; // + SPI1 = false; // + SYSCFG = false; // + SYSINFO = false; // + TBMAN = false; // + TIMER = false; // + UART0 = false; // + UART1 = false; // + USBCTRL = false; // + } + + // Watchdog select. If a bit is set then the watchdog will reset this peripheral when the watchdog fires. + register RESETS_WDSEL_t RESETS_WDSEL at 0x4000c004; + + type RESET_DONE_t { + ADC = false; // + BUSCTRL = false; // + DMA = false; // + I2C0 = false; // + I2C1 = false; // + IO_BANK0 = false; // + IO_QSPI = false; // + JTAG = false; // + PADS_BANK0 = false; // + PADS_QSPI = false; // + PIO0 = false; // + PIO1 = false; // + PLL_SYS = false; // + PLL_USB = false; // + PWM = false; // + RTC = false; // + SPI0 = false; // + SPI1 = false; // + SYSCFG = false; // + SYSINFO = false; // + TBMAN = false; // + TIMER = false; // + UART0 = false; // + UART1 = false; // + USBCTRL = false; // + } + + // Reset done. If a bit is set then a reset done signal has been returned by the peripheral. This indicates that the peripheral's registers are ready to be accessed. + register RESET_DONE_t RESET_DONE at 0x4000c008; + + +/* Types and registers for PSM */ + + type FRCE_ON_t { + ROSC = false; // + XOSC = false; // + CLOCKS = false; // + RESETS = false; // + BUSFABRIC = false; // + ROM = false; // + SRAM0 = false; // + SRAM1 = false; // + SRAM2 = false; // + SRAM3 = false; // + SRAM4 = false; // + SRAM5 = false; // + XIP = false; // + VREG_AND_CHIP_RESET = false; // + SIO = false; // + PROC0 = false; // + PROC1 = false; // + } + + // Force block out of reset (i.e. power it on) + register FRCE_ON_t FRCE_ON at 0x40010000; + + type FRCE_OFF_t { + ROSC = false; // + XOSC = false; // + CLOCKS = false; // + RESETS = false; // + BUSFABRIC = false; // + ROM = false; // + SRAM0 = false; // + SRAM1 = false; // + SRAM2 = false; // + SRAM3 = false; // + SRAM4 = false; // + SRAM5 = false; // + XIP = false; // + VREG_AND_CHIP_RESET = false; // + SIO = false; // + PROC0 = false; // + PROC1 = false; // + } + + // Force into reset (i.e. power it off) + register FRCE_OFF_t FRCE_OFF at 0x40010004; + + type PSM_WDSEL_t { + ROSC = false; // + XOSC = false; // + CLOCKS = false; // + RESETS = false; // + BUSFABRIC = false; // + ROM = false; // + SRAM0 = false; // + SRAM1 = false; // + SRAM2 = false; // + SRAM3 = false; // + SRAM4 = false; // + SRAM5 = false; // + XIP = false; // + VREG_AND_CHIP_RESET = false; // + SIO = false; // + PROC0 = false; // + PROC1 = false; // + } + + // Set to 1 if this peripheral should be reset when the watchdog fires. + register PSM_WDSEL_t PSM_WDSEL at 0x40010008; + + type DONE_t { + ROSC = false; // + XOSC = false; // + CLOCKS = false; // + RESETS = false; // + BUSFABRIC = false; // + ROM = false; // + SRAM0 = false; // + SRAM1 = false; // + SRAM2 = false; // + SRAM3 = false; // + SRAM4 = false; // + SRAM5 = false; // + XIP = false; // + VREG_AND_CHIP_RESET = false; // + SIO = false; // + PROC0 = false; // + PROC1 = false; // + } + + // Indicates the peripheral's registers are ready to access. + register DONE_t DONE at 0x4001000c; + + +/* Types and registers for CLOCKS */ + + type CLK_GPOUT0_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint4(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = false; // Reserved, 1 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + DC50 = false; // Enables duty cycle correction for odd divisors + _res3 = uint3(0); // Reserved, 3 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_GPOUT0_CTRL_t CLK_GPOUT0_CTRL at 0x40008000; + + type CLK_GPOUT0_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_GPOUT0_DIV_t CLK_GPOUT0_DIV at 0x40008004; + + type CLK_GPOUT0_SELECTED_t { + CLK_GPOUT0_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_GPOUT0_SELECTED_t CLK_GPOUT0_SELECTED at 0x40008008; + + type CLK_GPOUT1_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint4(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = false; // Reserved, 1 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + DC50 = false; // Enables duty cycle correction for odd divisors + _res3 = uint3(0); // Reserved, 3 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_GPOUT1_CTRL_t CLK_GPOUT1_CTRL at 0x4000800c; + + type CLK_GPOUT1_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_GPOUT1_DIV_t CLK_GPOUT1_DIV at 0x40008010; + + type CLK_GPOUT1_SELECTED_t { + CLK_GPOUT1_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_GPOUT1_SELECTED_t CLK_GPOUT1_SELECTED at 0x40008014; + + type CLK_GPOUT2_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint4(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = false; // Reserved, 1 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + DC50 = false; // Enables duty cycle correction for odd divisors + _res3 = uint3(0); // Reserved, 3 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_GPOUT2_CTRL_t CLK_GPOUT2_CTRL at 0x40008018; + + type CLK_GPOUT2_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_GPOUT2_DIV_t CLK_GPOUT2_DIV at 0x4000801c; + + type CLK_GPOUT2_SELECTED_t { + CLK_GPOUT2_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_GPOUT2_SELECTED_t CLK_GPOUT2_SELECTED at 0x40008020; + + type CLK_GPOUT3_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint4(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = false; // Reserved, 1 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + DC50 = false; // Enables duty cycle correction for odd divisors + _res3 = uint3(0); // Reserved, 3 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_GPOUT3_CTRL_t CLK_GPOUT3_CTRL at 0x40008024; + + type CLK_GPOUT3_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_GPOUT3_DIV_t CLK_GPOUT3_DIV at 0x40008028; + + type CLK_GPOUT3_SELECTED_t { + CLK_GPOUT3_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_GPOUT3_SELECTED_t CLK_GPOUT3_SELECTED at 0x4000802c; + + type CLK_REF_CTRL_t { + SRC = uint2(0); // Selects the clock source glitchlessly, can be changed on-the-fly + _res1 = uint3(0); // Reserved, 3 bits + AUXSRC = uint2(0); // Selects the auxiliary clock source, will glitch when switching + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_REF_CTRL_t CLK_REF_CTRL at 0x40008030; + + type CLK_REF_DIV_t { + _res1 = uint8(0); // Reserved, 8 bits + INT = uint2(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_REF_DIV_t CLK_REF_DIV at 0x40008034; + + type CLK_REF_SELECTED_t { + CLK_REF_SELECTED = uint32(0); // The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_REF_SELECTED_t CLK_REF_SELECTED at 0x40008038; + + type CLK_SYS_CTRL_t { + SRC = false; // Selects the clock source glitchlessly, can be changed on-the-fly + _res1 = uint4(0); // Reserved, 4 bits + AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_SYS_CTRL_t CLK_SYS_CTRL at 0x4000803c; + + type CLK_SYS_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_SYS_DIV_t CLK_SYS_DIV at 0x40008040; + + type CLK_SYS_SELECTED_t { + CLK_SYS_SELECTED = uint32(0); // The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_SYS_SELECTED_t CLK_SYS_SELECTED at 0x40008044; + + type CLK_PERI_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint2(0); // Reserved, 2 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_PERI_CTRL_t CLK_PERI_CTRL at 0x40008048; + + type CLK_PERI_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_PERI_DIV_t CLK_PERI_DIV at 0x4000804c; + + type CLK_PERI_SELECTED_t { + CLK_PERI_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_PERI_SELECTED_t CLK_PERI_SELECTED at 0x40008050; + + type CLK_USB_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint2(0); // Reserved, 2 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + _res3 = uint4(0); // Reserved, 4 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_USB_CTRL_t CLK_USB_CTRL at 0x40008054; + + type CLK_USB_DIV_t { + _res1 = uint8(0); // Reserved, 8 bits + INT = uint2(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_USB_DIV_t CLK_USB_DIV at 0x40008058; + + type CLK_USB_SELECTED_t { + CLK_USB_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_USB_SELECTED_t CLK_USB_SELECTED at 0x4000805c; + + type CLK_ADC_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint2(0); // Reserved, 2 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + _res3 = uint4(0); // Reserved, 4 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_ADC_CTRL_t CLK_ADC_CTRL at 0x40008060; + + type CLK_ADC_DIV_t { + _res1 = uint8(0); // Reserved, 8 bits + INT = uint2(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_ADC_DIV_t CLK_ADC_DIV at 0x40008064; + + type CLK_ADC_SELECTED_t { + CLK_ADC_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_ADC_SELECTED_t CLK_ADC_SELECTED at 0x40008068; + + type CLK_RTC_CTRL_t { + _res1 = uint5(0); // Reserved, 5 bits + AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint2(0); // Reserved, 2 bits + KILL = false; // Asynchronously kills the clock generator + ENABLE = false; // Starts and stops the clock generator cleanly + _res3 = uint4(0); // Reserved, 4 bits + PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect + _res4 = uint2(0); // Reserved, 2 bits + NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + } + + // Clock control, can be changed on-the-fly (except for auxsrc) + register CLK_RTC_CTRL_t CLK_RTC_CTRL at 0x4000806c; + + type CLK_RTC_DIV_t { + FRAC = uint8(0); // Fractional component of the divisor + INT = uint24(0); // Integer component of the divisor, 0 -> divide by 2^16 + } + + // Clock divisor, can be changed on-the-fly + register CLK_RTC_DIV_t CLK_RTC_DIV at 0x40008070; + + type CLK_RTC_SELECTED_t { + CLK_RTC_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + } + + // Indicates which SRC is currently selected by the glitchless mux (one-hot). + register CLK_RTC_SELECTED_t CLK_RTC_SELECTED at 0x40008074; + + type CLK_SYS_RESUS_CTRL_t { + TIMEOUT = uint8(0); // This is expressed as a number of clk_ref cycles and must be >= 2x clk_ref_freq/min_clk_tst_freq + ENABLE = false; // Enable resus + _res1 = uint3(0); // Reserved, 3 bits + FRCE = false; // Force a resus, for test purposes only + _res2 = uint3(0); // Reserved, 3 bits + CLEAR = false; // For clearing the resus after the fault that triggered it has been corrected + } + + // + register CLK_SYS_RESUS_CTRL_t CLK_SYS_RESUS_CTRL at 0x40008078; + + type CLK_SYS_RESUS_STATUS_t { + RESUSSED = false; // Clock has been resuscitated, correct the error then send ctrl_clear=1 + } + + // + register CLK_SYS_RESUS_STATUS_t CLK_SYS_RESUS_STATUS at 0x4000807c; + + type FC0_REF_KHZ_t { + FC0_REF_KHZ = uint20(0); // + } + + // Reference clock frequency in kHz + register FC0_REF_KHZ_t FC0_REF_KHZ at 0x40008080; + + type FC0_MIN_KHZ_t { + FC0_MIN_KHZ = uint25(0); // + } + + // Minimum pass frequency in kHz. This is optional. Set to 0 if you are not using the pass/fail flags + register FC0_MIN_KHZ_t FC0_MIN_KHZ at 0x40008084; + + type FC0_MAX_KHZ_t { + FC0_MAX_KHZ = uint25(0); // + } + + // Maximum pass frequency in kHz. This is optional. Set to 0x1ffffff if you are not using the pass/fail flags + register FC0_MAX_KHZ_t FC0_MAX_KHZ at 0x40008088; + + type FC0_DELAY_t { + FC0_DELAY = uint3(0); // + } + + // Delays the start of frequency counting to allow the mux to settle Delay is measured in multiples of the reference clock period + register FC0_DELAY_t FC0_DELAY at 0x4000808c; + + type FC0_INTERVAL_t { + FC0_INTERVAL = uint4(0); // + } + + // The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval The default gives a test interval of 250us + register FC0_INTERVAL_t FC0_INTERVAL at 0x40008090; + + type FC0_SRC_t { + FC0_SRC = uint8(0); // + } + + // Clock sent to frequency counter, set to 0 when not required Writing to this register initiates the frequency count + register FC0_SRC_t FC0_SRC at 0x40008094; + + type FC0_STATUS_t { + PASS = false; // Test passed + _res1 = uint3(0); // Reserved, 3 bits + DONE = false; // Test complete + _res2 = uint3(0); // Reserved, 3 bits + RUNNING = false; // Test running + _res3 = uint3(0); // Reserved, 3 bits + WAITING = false; // Waiting for test clock to start + _res4 = uint3(0); // Reserved, 3 bits + FAIL = false; // Test failed + _res5 = uint3(0); // Reserved, 3 bits + SLOW = false; // Test clock slower than expected, only valid when status_done=1 + _res6 = uint3(0); // Reserved, 3 bits + FAST = false; // Test clock faster than expected, only valid when status_done=1 + _res7 = uint3(0); // Reserved, 3 bits + DIED = false; // Test clock stopped during test + } + + // Frequency counter status + register FC0_STATUS_t FC0_STATUS at 0x40008098; + + type FC0_RESULT_t { + FRAC = uint5(0); // + KHZ = uint25(0); // + } + + // Result of frequency measurement, only valid when status_done=1 + register FC0_RESULT_t FC0_RESULT at 0x4000809c; + + type WAKE_EN0_t { + CLK_SYS_CLOCKS = false; // + CLK_ADC_ADC = false; // + CLK_SYS_ADC = false; // + CLK_SYS_BUSCTRL = false; // + CLK_SYS_BUSFABRIC = false; // + CLK_SYS_DMA = false; // + CLK_SYS_I2C0 = false; // + CLK_SYS_I2C1 = false; // + CLK_SYS_IO = false; // + CLK_SYS_JTAG = false; // + CLK_SYS_VREG_AND_CHIP_RESET = false; // + CLK_SYS_PADS = false; // + CLK_SYS_PIO0 = false; // + CLK_SYS_PIO1 = false; // + CLK_SYS_PLL_SYS = false; // + CLK_SYS_PLL_USB = false; // + CLK_SYS_PSM = false; // + CLK_SYS_PWM = false; // + CLK_SYS_RESETS = false; // + CLK_SYS_ROM = false; // + CLK_SYS_ROSC = false; // + CLK_RTC_RTC = false; // + CLK_SYS_RTC = false; // + CLK_SYS_SIO = false; // + CLK_PERI_SPI0 = false; // + CLK_SYS_SPI0 = false; // + CLK_PERI_SPI1 = false; // + CLK_SYS_SPI1 = false; // + CLK_SYS_SRAM0 = false; // + CLK_SYS_SRAM1 = false; // + CLK_SYS_SRAM2 = false; // + CLK_SYS_SRAM3 = false; // + } + + // enable clock in wake mode + register WAKE_EN0_t WAKE_EN0 at 0x400080a0; + + type WAKE_EN1_t { + CLK_SYS_SRAM4 = false; // + CLK_SYS_SRAM5 = false; // + CLK_SYS_SYSCFG = false; // + CLK_SYS_SYSINFO = false; // + CLK_SYS_TBMAN = false; // + CLK_SYS_TIMER = false; // + CLK_PERI_UART0 = false; // + CLK_SYS_UART0 = false; // + CLK_PERI_UART1 = false; // + CLK_SYS_UART1 = false; // + CLK_SYS_USBCTRL = false; // + CLK_USB_USBCTRL = false; // + CLK_SYS_WATCHDOG = false; // + CLK_SYS_XIP = false; // + CLK_SYS_XOSC = false; // + } + + // enable clock in wake mode + register WAKE_EN1_t WAKE_EN1 at 0x400080a4; + + type SLEEP_EN0_t { + CLK_SYS_CLOCKS = false; // + CLK_ADC_ADC = false; // + CLK_SYS_ADC = false; // + CLK_SYS_BUSCTRL = false; // + CLK_SYS_BUSFABRIC = false; // + CLK_SYS_DMA = false; // + CLK_SYS_I2C0 = false; // + CLK_SYS_I2C1 = false; // + CLK_SYS_IO = false; // + CLK_SYS_JTAG = false; // + CLK_SYS_VREG_AND_CHIP_RESET = false; // + CLK_SYS_PADS = false; // + CLK_SYS_PIO0 = false; // + CLK_SYS_PIO1 = false; // + CLK_SYS_PLL_SYS = false; // + CLK_SYS_PLL_USB = false; // + CLK_SYS_PSM = false; // + CLK_SYS_PWM = false; // + CLK_SYS_RESETS = false; // + CLK_SYS_ROM = false; // + CLK_SYS_ROSC = false; // + CLK_RTC_RTC = false; // + CLK_SYS_RTC = false; // + CLK_SYS_SIO = false; // + CLK_PERI_SPI0 = false; // + CLK_SYS_SPI0 = false; // + CLK_PERI_SPI1 = false; // + CLK_SYS_SPI1 = false; // + CLK_SYS_SRAM0 = false; // + CLK_SYS_SRAM1 = false; // + CLK_SYS_SRAM2 = false; // + CLK_SYS_SRAM3 = false; // + } + + // enable clock in sleep mode + register SLEEP_EN0_t SLEEP_EN0 at 0x400080a8; + + type SLEEP_EN1_t { + CLK_SYS_SRAM4 = false; // + CLK_SYS_SRAM5 = false; // + CLK_SYS_SYSCFG = false; // + CLK_SYS_SYSINFO = false; // + CLK_SYS_TBMAN = false; // + CLK_SYS_TIMER = false; // + CLK_PERI_UART0 = false; // + CLK_SYS_UART0 = false; // + CLK_PERI_UART1 = false; // + CLK_SYS_UART1 = false; // + CLK_SYS_USBCTRL = false; // + CLK_USB_USBCTRL = false; // + CLK_SYS_WATCHDOG = false; // + CLK_SYS_XIP = false; // + CLK_SYS_XOSC = false; // + } + + // enable clock in sleep mode + register SLEEP_EN1_t SLEEP_EN1 at 0x400080ac; + + type ENABLED0_t { + CLK_SYS_CLOCKS = false; // + CLK_ADC_ADC = false; // + CLK_SYS_ADC = false; // + CLK_SYS_BUSCTRL = false; // + CLK_SYS_BUSFABRIC = false; // + CLK_SYS_DMA = false; // + CLK_SYS_I2C0 = false; // + CLK_SYS_I2C1 = false; // + CLK_SYS_IO = false; // + CLK_SYS_JTAG = false; // + CLK_SYS_VREG_AND_CHIP_RESET = false; // + CLK_SYS_PADS = false; // + CLK_SYS_PIO0 = false; // + CLK_SYS_PIO1 = false; // + CLK_SYS_PLL_SYS = false; // + CLK_SYS_PLL_USB = false; // + CLK_SYS_PSM = false; // + CLK_SYS_PWM = false; // + CLK_SYS_RESETS = false; // + CLK_SYS_ROM = false; // + CLK_SYS_ROSC = false; // + CLK_RTC_RTC = false; // + CLK_SYS_RTC = false; // + CLK_SYS_SIO = false; // + CLK_PERI_SPI0 = false; // + CLK_SYS_SPI0 = false; // + CLK_PERI_SPI1 = false; // + CLK_SYS_SPI1 = false; // + CLK_SYS_SRAM0 = false; // + CLK_SYS_SRAM1 = false; // + CLK_SYS_SRAM2 = false; // + CLK_SYS_SRAM3 = false; // + } + + // indicates the state of the clock enable + register ENABLED0_t ENABLED0 at 0x400080b0; + + type ENABLED1_t { + CLK_SYS_SRAM4 = false; // + CLK_SYS_SRAM5 = false; // + CLK_SYS_SYSCFG = false; // + CLK_SYS_SYSINFO = false; // + CLK_SYS_TBMAN = false; // + CLK_SYS_TIMER = false; // + CLK_PERI_UART0 = false; // + CLK_SYS_UART0 = false; // + CLK_PERI_UART1 = false; // + CLK_SYS_UART1 = false; // + CLK_SYS_USBCTRL = false; // + CLK_USB_USBCTRL = false; // + CLK_SYS_WATCHDOG = false; // + CLK_SYS_XIP = false; // + CLK_SYS_XOSC = false; // + } + + // indicates the state of the clock enable + register ENABLED1_t ENABLED1 at 0x400080b4; + + type CLOCKS_INTR_t { + CLK_SYS_RESUS = false; // + } + + // Raw Interrupts + register CLOCKS_INTR_t CLOCKS_INTR at 0x400080b8; + + type CLOCKS_INTE_t { + CLK_SYS_RESUS = false; // + } + + // Interrupt Enable + register CLOCKS_INTE_t CLOCKS_INTE at 0x400080bc; + + type CLOCKS_INTF_t { + CLK_SYS_RESUS = false; // + } + + // Interrupt Force + register CLOCKS_INTF_t CLOCKS_INTF at 0x400080c0; + + type CLOCKS_INTS_t { + CLK_SYS_RESUS = false; // + } + + // Interrupt status after masking & forcing + register CLOCKS_INTS_t CLOCKS_INTS at 0x400080c4; + + +/* Types and registers for PADS_BANK0 */ + + type PADS_BANK0_VOLTAGE_SELECT_t { + VOLTAGE_SELECT = false; // + } + + // Voltage select. Per bank control + register PADS_BANK0_VOLTAGE_SELECT_t PADS_BANK0_VOLTAGE_SELECT at 0x4001c000; + + type GPIO0_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO0_t GPIO0 at 0x4001c004; + + type GPIO1_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO1_t GPIO1 at 0x4001c008; + + type GPIO2_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO2_t GPIO2 at 0x4001c00c; + + type GPIO3_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO3_t GPIO3 at 0x4001c010; + + type GPIO4_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO4_t GPIO4 at 0x4001c014; + + type GPIO5_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO5_t GPIO5 at 0x4001c018; + + type GPIO6_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO6_t GPIO6 at 0x4001c01c; + + type GPIO7_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO7_t GPIO7 at 0x4001c020; + + type GPIO8_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO8_t GPIO8 at 0x4001c024; + + type GPIO9_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO9_t GPIO9 at 0x4001c028; + + type GPIO10_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO10_t GPIO10 at 0x4001c02c; + + type GPIO11_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO11_t GPIO11 at 0x4001c030; + + type GPIO12_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO12_t GPIO12 at 0x4001c034; + + type GPIO13_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO13_t GPIO13 at 0x4001c038; + + type GPIO14_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO14_t GPIO14 at 0x4001c03c; + + type GPIO15_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO15_t GPIO15 at 0x4001c040; + + type GPIO16_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO16_t GPIO16 at 0x4001c044; + + type GPIO17_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO17_t GPIO17 at 0x4001c048; + + type GPIO18_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO18_t GPIO18 at 0x4001c04c; + + type GPIO19_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO19_t GPIO19 at 0x4001c050; + + type GPIO20_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO20_t GPIO20 at 0x4001c054; + + type GPIO21_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO21_t GPIO21 at 0x4001c058; + + type GPIO22_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO22_t GPIO22 at 0x4001c05c; + + type GPIO23_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO23_t GPIO23 at 0x4001c060; + + type GPIO24_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO24_t GPIO24 at 0x4001c064; + + type GPIO25_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO25_t GPIO25 at 0x4001c068; + + type GPIO26_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO26_t GPIO26 at 0x4001c06c; + + type GPIO27_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO27_t GPIO27 at 0x4001c070; + + type GPIO28_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO28_t GPIO28 at 0x4001c074; + + type GPIO29_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO29_t GPIO29 at 0x4001c078; + + type SWCLK_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register SWCLK_t SWCLK at 0x4001c07c; + + type SWD_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register SWD_t SWD at 0x4001c080; + + +/* Types and registers for PADS_QSPI */ + + type PADS_QSPI_VOLTAGE_SELECT_t { + VOLTAGE_SELECT = false; // + } + + // Voltage select. Per bank control + register PADS_QSPI_VOLTAGE_SELECT_t PADS_QSPI_VOLTAGE_SELECT at 0x40020000; + + type GPIO_QSPI_SCLK_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO_QSPI_SCLK_t GPIO_QSPI_SCLK at 0x40020004; + + type GPIO_QSPI_SD0_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO_QSPI_SD0_t GPIO_QSPI_SD0 at 0x40020008; + + type GPIO_QSPI_SD1_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO_QSPI_SD1_t GPIO_QSPI_SD1 at 0x4002000c; + + type GPIO_QSPI_SD2_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO_QSPI_SD2_t GPIO_QSPI_SD2 at 0x40020010; + + type GPIO_QSPI_SD3_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO_QSPI_SD3_t GPIO_QSPI_SD3 at 0x40020014; + + type GPIO_QSPI_SS_t { + SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow + SCHMITT = false; // Enable schmitt trigger + PDE = false; // Pull down enable + PUE = false; // Pull up enable + DRIVE = uint2(0); // Drive strength. + IE = false; // Input enable + OD = false; // Output disable. Has priority over output enable from peripherals + } + + // Pad control register + register GPIO_QSPI_SS_t GPIO_QSPI_SS at 0x40020018; + + +/* Types and registers for IO_QSPI */ + + type GPIO_QSPI_SCLK_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO_QSPI_SCLK_STATUS_t GPIO_QSPI_SCLK_STATUS at 0x40018000; + + type GPIO_QSPI_SCLK_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SCLK_CTRL_t GPIO_QSPI_SCLK_CTRL at 0x40018004; + + type GPIO_QSPI_SS_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO_QSPI_SS_STATUS_t GPIO_QSPI_SS_STATUS at 0x40018008; + + type GPIO_QSPI_SS_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SS_CTRL_t GPIO_QSPI_SS_CTRL at 0x4001800c; + + type GPIO_QSPI_SD0_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO_QSPI_SD0_STATUS_t GPIO_QSPI_SD0_STATUS at 0x40018010; + + type GPIO_QSPI_SD0_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SD0_CTRL_t GPIO_QSPI_SD0_CTRL at 0x40018014; + + type GPIO_QSPI_SD1_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO_QSPI_SD1_STATUS_t GPIO_QSPI_SD1_STATUS at 0x40018018; + + type GPIO_QSPI_SD1_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SD1_CTRL_t GPIO_QSPI_SD1_CTRL at 0x4001801c; + + type GPIO_QSPI_SD2_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO_QSPI_SD2_STATUS_t GPIO_QSPI_SD2_STATUS at 0x40018020; + + type GPIO_QSPI_SD2_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SD2_CTRL_t GPIO_QSPI_SD2_CTRL at 0x40018024; + + type GPIO_QSPI_SD3_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO_QSPI_SD3_STATUS_t GPIO_QSPI_SD3_STATUS at 0x40018028; + + type GPIO_QSPI_SD3_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO_QSPI_SD3_CTRL_t GPIO_QSPI_SD3_CTRL at 0x4001802c; + + type IO_QSPI_INTR_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + } + + // Raw Interrupts + register IO_QSPI_INTR_t IO_QSPI_INTR at 0x40018030; + + type PROC0_INTE_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc0 + register PROC0_INTE_t PROC0_INTE at 0x40018034; + + type PROC0_INTF_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + } + + // Interrupt Force for proc0 + register PROC0_INTF_t PROC0_INTF at 0x40018038; + + type PROC0_INTS_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc0 + register PROC0_INTS_t PROC0_INTS at 0x4001803c; + + type PROC1_INTE_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc1 + register PROC1_INTE_t PROC1_INTE at 0x40018040; + + type PROC1_INTF_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + } + + // Interrupt Force for proc1 + register PROC1_INTF_t PROC1_INTF at 0x40018044; + + type PROC1_INTS_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc1 + register PROC1_INTS_t PROC1_INTS at 0x40018048; + + type DORMANT_WAKE_INTE_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + } + + // Interrupt Enable for dormant_wake + register DORMANT_WAKE_INTE_t DORMANT_WAKE_INTE at 0x4001804c; + + type DORMANT_WAKE_INTF_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + } + + // Interrupt Force for dormant_wake + register DORMANT_WAKE_INTF_t DORMANT_WAKE_INTF at 0x40018050; + + type DORMANT_WAKE_INTS_t { + GPIO_QSPI_SCLK_LEVEL_LOW = false; // + GPIO_QSPI_SCLK_LEVEL_HIGH = false; // + GPIO_QSPI_SCLK_EDGE_LOW = false; // + GPIO_QSPI_SCLK_EDGE_HIGH = false; // + GPIO_QSPI_SS_LEVEL_LOW = false; // + GPIO_QSPI_SS_LEVEL_HIGH = false; // + GPIO_QSPI_SS_EDGE_LOW = false; // + GPIO_QSPI_SS_EDGE_HIGH = false; // + GPIO_QSPI_SD0_LEVEL_LOW = false; // + GPIO_QSPI_SD0_LEVEL_HIGH = false; // + GPIO_QSPI_SD0_EDGE_LOW = false; // + GPIO_QSPI_SD0_EDGE_HIGH = false; // + GPIO_QSPI_SD1_LEVEL_LOW = false; // + GPIO_QSPI_SD1_LEVEL_HIGH = false; // + GPIO_QSPI_SD1_EDGE_LOW = false; // + GPIO_QSPI_SD1_EDGE_HIGH = false; // + GPIO_QSPI_SD2_LEVEL_LOW = false; // + GPIO_QSPI_SD2_LEVEL_HIGH = false; // + GPIO_QSPI_SD2_EDGE_LOW = false; // + GPIO_QSPI_SD2_EDGE_HIGH = false; // + GPIO_QSPI_SD3_LEVEL_LOW = false; // + GPIO_QSPI_SD3_LEVEL_HIGH = false; // + GPIO_QSPI_SD3_EDGE_LOW = false; // + GPIO_QSPI_SD3_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for dormant_wake + register DORMANT_WAKE_INTS_t DORMANT_WAKE_INTS at 0x40018054; + + +/* Types and registers for IO_BANK0 */ + + type GPIO0_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO0_STATUS_t GPIO0_STATUS at 0x40014000; + + type GPIO0_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO0_CTRL_t GPIO0_CTRL at 0x40014004; + + type GPIO1_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO1_STATUS_t GPIO1_STATUS at 0x40014008; + + type GPIO1_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO1_CTRL_t GPIO1_CTRL at 0x4001400c; + + type GPIO2_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO2_STATUS_t GPIO2_STATUS at 0x40014010; + + type GPIO2_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO2_CTRL_t GPIO2_CTRL at 0x40014014; + + type GPIO3_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO3_STATUS_t GPIO3_STATUS at 0x40014018; + + type GPIO3_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO3_CTRL_t GPIO3_CTRL at 0x4001401c; + + type GPIO4_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO4_STATUS_t GPIO4_STATUS at 0x40014020; + + type GPIO4_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO4_CTRL_t GPIO4_CTRL at 0x40014024; + + type GPIO5_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO5_STATUS_t GPIO5_STATUS at 0x40014028; + + type GPIO5_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO5_CTRL_t GPIO5_CTRL at 0x4001402c; + + type GPIO6_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO6_STATUS_t GPIO6_STATUS at 0x40014030; + + type GPIO6_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO6_CTRL_t GPIO6_CTRL at 0x40014034; + + type GPIO7_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO7_STATUS_t GPIO7_STATUS at 0x40014038; + + type GPIO7_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO7_CTRL_t GPIO7_CTRL at 0x4001403c; + + type GPIO8_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO8_STATUS_t GPIO8_STATUS at 0x40014040; + + type GPIO8_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO8_CTRL_t GPIO8_CTRL at 0x40014044; + + type GPIO9_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO9_STATUS_t GPIO9_STATUS at 0x40014048; + + type GPIO9_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO9_CTRL_t GPIO9_CTRL at 0x4001404c; + + type GPIO10_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO10_STATUS_t GPIO10_STATUS at 0x40014050; + + type GPIO10_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO10_CTRL_t GPIO10_CTRL at 0x40014054; + + type GPIO11_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO11_STATUS_t GPIO11_STATUS at 0x40014058; + + type GPIO11_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO11_CTRL_t GPIO11_CTRL at 0x4001405c; + + type GPIO12_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO12_STATUS_t GPIO12_STATUS at 0x40014060; + + type GPIO12_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO12_CTRL_t GPIO12_CTRL at 0x40014064; + + type GPIO13_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO13_STATUS_t GPIO13_STATUS at 0x40014068; + + type GPIO13_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO13_CTRL_t GPIO13_CTRL at 0x4001406c; + + type GPIO14_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO14_STATUS_t GPIO14_STATUS at 0x40014070; + + type GPIO14_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO14_CTRL_t GPIO14_CTRL at 0x40014074; + + type GPIO15_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO15_STATUS_t GPIO15_STATUS at 0x40014078; + + type GPIO15_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO15_CTRL_t GPIO15_CTRL at 0x4001407c; + + type GPIO16_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO16_STATUS_t GPIO16_STATUS at 0x40014080; + + type GPIO16_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO16_CTRL_t GPIO16_CTRL at 0x40014084; + + type GPIO17_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO17_STATUS_t GPIO17_STATUS at 0x40014088; + + type GPIO17_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO17_CTRL_t GPIO17_CTRL at 0x4001408c; + + type GPIO18_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO18_STATUS_t GPIO18_STATUS at 0x40014090; + + type GPIO18_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO18_CTRL_t GPIO18_CTRL at 0x40014094; + + type GPIO19_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO19_STATUS_t GPIO19_STATUS at 0x40014098; + + type GPIO19_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO19_CTRL_t GPIO19_CTRL at 0x4001409c; + + type GPIO20_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO20_STATUS_t GPIO20_STATUS at 0x400140a0; + + type GPIO20_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO20_CTRL_t GPIO20_CTRL at 0x400140a4; + + type GPIO21_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO21_STATUS_t GPIO21_STATUS at 0x400140a8; + + type GPIO21_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO21_CTRL_t GPIO21_CTRL at 0x400140ac; + + type GPIO22_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO22_STATUS_t GPIO22_STATUS at 0x400140b0; + + type GPIO22_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO22_CTRL_t GPIO22_CTRL at 0x400140b4; + + type GPIO23_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO23_STATUS_t GPIO23_STATUS at 0x400140b8; + + type GPIO23_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO23_CTRL_t GPIO23_CTRL at 0x400140bc; + + type GPIO24_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO24_STATUS_t GPIO24_STATUS at 0x400140c0; + + type GPIO24_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO24_CTRL_t GPIO24_CTRL at 0x400140c4; + + type GPIO25_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO25_STATUS_t GPIO25_STATUS at 0x400140c8; + + type GPIO25_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO25_CTRL_t GPIO25_CTRL at 0x400140cc; + + type GPIO26_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO26_STATUS_t GPIO26_STATUS at 0x400140d0; + + type GPIO26_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO26_CTRL_t GPIO26_CTRL at 0x400140d4; + + type GPIO27_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO27_STATUS_t GPIO27_STATUS at 0x400140d8; + + type GPIO27_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO27_CTRL_t GPIO27_CTRL at 0x400140dc; + + type GPIO28_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO28_STATUS_t GPIO28_STATUS at 0x400140e0; + + type GPIO28_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO28_CTRL_t GPIO28_CTRL at 0x400140e4; + + type GPIO29_STATUS_t { + _res1 = uint8(0); // Reserved, 8 bits + OUTFROMPERI = false; // output signal from selected peripheral, before register override is applied + OUTTOPAD = false; // output signal to pad after register override is applied + _res2 = uint2(0); // Reserved, 2 bits + OEFROMPERI = false; // output enable from selected peripheral, before register override is applied + OETOPAD = false; // output enable to pad after register override is applied + _res3 = uint3(0); // Reserved, 3 bits + INFROMPAD = false; // input signal from pad, before override is applied + _res4 = false; // Reserved, 1 bits + INTOPERI = false; // input signal to peripheral, after override is applied + _res5 = uint4(0); // Reserved, 4 bits + IRQFROMPAD = false; // interrupt from pad before override is applied + _res6 = false; // Reserved, 1 bits + IRQTOPROC = false; // interrupt to processors, after override is applied + } + + // GPIO status + register GPIO29_STATUS_t GPIO29_STATUS at 0x400140e8; + + type GPIO29_CTRL_t { + FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL + _res1 = uint3(0); // Reserved, 3 bits + OUTOVER = uint2(0); // + _res2 = uint2(0); // Reserved, 2 bits + OEOVER = uint2(0); // + _res3 = uint2(0); // Reserved, 2 bits + INOVER = uint2(0); // + _res4 = uint8(0); // Reserved, 10 bits + _res5 = uint2(0); // + IRQOVER = uint2(0); // + } + + // GPIO control including function select and overrides. + register GPIO29_CTRL_t GPIO29_CTRL at 0x400140ec; + + type INTR0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Raw Interrupts + register INTR0_t INTR0 at 0x400140f0; + + type IO_BANK0_INTR1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Raw Interrupts + register IO_BANK0_INTR1_t IO_BANK0_INTR1 at 0x400140f4; + + type INTR2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Raw Interrupts + register INTR2_t INTR2 at 0x400140f8; + + type INTR3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + } + + // Raw Interrupts + register INTR3_t INTR3 at 0x400140fc; + + type PROC0_INTE0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc0 + register PROC0_INTE0_t PROC0_INTE0 at 0x40014100; + + type PROC0_INTE1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc0 + register PROC0_INTE1_t PROC0_INTE1 at 0x40014104; + + type PROC0_INTE2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc0 + register PROC0_INTE2_t PROC0_INTE2 at 0x40014108; + + type PROC0_INTE3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc0 + register PROC0_INTE3_t PROC0_INTE3 at 0x4001410c; + + type PROC0_INTF0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Force for proc0 + register PROC0_INTF0_t PROC0_INTF0 at 0x40014110; + + type PROC0_INTF1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Force for proc0 + register PROC0_INTF1_t PROC0_INTF1 at 0x40014114; + + type PROC0_INTF2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Force for proc0 + register PROC0_INTF2_t PROC0_INTF2 at 0x40014118; + + type PROC0_INTF3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + } + + // Interrupt Force for proc0 + register PROC0_INTF3_t PROC0_INTF3 at 0x4001411c; + + type PROC0_INTS0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc0 + register PROC0_INTS0_t PROC0_INTS0 at 0x40014120; + + type PROC0_INTS1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc0 + register PROC0_INTS1_t PROC0_INTS1 at 0x40014124; + + type PROC0_INTS2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc0 + register PROC0_INTS2_t PROC0_INTS2 at 0x40014128; + + type PROC0_INTS3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc0 + register PROC0_INTS3_t PROC0_INTS3 at 0x4001412c; + + type PROC1_INTE0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc1 + register PROC1_INTE0_t PROC1_INTE0 at 0x40014130; + + type PROC1_INTE1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc1 + register PROC1_INTE1_t PROC1_INTE1 at 0x40014134; + + type PROC1_INTE2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc1 + register PROC1_INTE2_t PROC1_INTE2 at 0x40014138; + + type PROC1_INTE3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + } + + // Interrupt Enable for proc1 + register PROC1_INTE3_t PROC1_INTE3 at 0x4001413c; + + type PROC1_INTF0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Force for proc1 + register PROC1_INTF0_t PROC1_INTF0 at 0x40014140; + + type PROC1_INTF1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Force for proc1 + register PROC1_INTF1_t PROC1_INTF1 at 0x40014144; + + type PROC1_INTF2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Force for proc1 + register PROC1_INTF2_t PROC1_INTF2 at 0x40014148; + + type PROC1_INTF3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + } + + // Interrupt Force for proc1 + register PROC1_INTF3_t PROC1_INTF3 at 0x4001414c; + + type PROC1_INTS0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc1 + register PROC1_INTS0_t PROC1_INTS0 at 0x40014150; + + type PROC1_INTS1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc1 + register PROC1_INTS1_t PROC1_INTS1 at 0x40014154; + + type PROC1_INTS2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc1 + register PROC1_INTS2_t PROC1_INTS2 at 0x40014158; + + type PROC1_INTS3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for proc1 + register PROC1_INTS3_t PROC1_INTS3 at 0x4001415c; + + type DORMANT_WAKE_INTE0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Enable for dormant_wake + register DORMANT_WAKE_INTE0_t DORMANT_WAKE_INTE0 at 0x40014160; + + type DORMANT_WAKE_INTE1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Enable for dormant_wake + register DORMANT_WAKE_INTE1_t DORMANT_WAKE_INTE1 at 0x40014164; + + type DORMANT_WAKE_INTE2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Enable for dormant_wake + register DORMANT_WAKE_INTE2_t DORMANT_WAKE_INTE2 at 0x40014168; + + type DORMANT_WAKE_INTE3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + } + + // Interrupt Enable for dormant_wake + register DORMANT_WAKE_INTE3_t DORMANT_WAKE_INTE3 at 0x4001416c; + + type DORMANT_WAKE_INTF0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt Force for dormant_wake + register DORMANT_WAKE_INTF0_t DORMANT_WAKE_INTF0 at 0x40014170; + + type DORMANT_WAKE_INTF1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt Force for dormant_wake + register DORMANT_WAKE_INTF1_t DORMANT_WAKE_INTF1 at 0x40014174; + + type DORMANT_WAKE_INTF2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt Force for dormant_wake + register DORMANT_WAKE_INTF2_t DORMANT_WAKE_INTF2 at 0x40014178; + + type DORMANT_WAKE_INTF3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + } + + // Interrupt Force for dormant_wake + register DORMANT_WAKE_INTF3_t DORMANT_WAKE_INTF3 at 0x4001417c; + + type DORMANT_WAKE_INTS0_t { + GPIO0_LEVEL_LOW = false; // + GPIO0_LEVEL_HIGH = false; // + GPIO0_EDGE_LOW = false; // + GPIO0_EDGE_HIGH = false; // + GPIO1_LEVEL_LOW = false; // + GPIO1_LEVEL_HIGH = false; // + GPIO1_EDGE_LOW = false; // + GPIO1_EDGE_HIGH = false; // + GPIO2_LEVEL_LOW = false; // + GPIO2_LEVEL_HIGH = false; // + GPIO2_EDGE_LOW = false; // + GPIO2_EDGE_HIGH = false; // + GPIO3_LEVEL_LOW = false; // + GPIO3_LEVEL_HIGH = false; // + GPIO3_EDGE_LOW = false; // + GPIO3_EDGE_HIGH = false; // + GPIO4_LEVEL_LOW = false; // + GPIO4_LEVEL_HIGH = false; // + GPIO4_EDGE_LOW = false; // + GPIO4_EDGE_HIGH = false; // + GPIO5_LEVEL_LOW = false; // + GPIO5_LEVEL_HIGH = false; // + GPIO5_EDGE_LOW = false; // + GPIO5_EDGE_HIGH = false; // + GPIO6_LEVEL_LOW = false; // + GPIO6_LEVEL_HIGH = false; // + GPIO6_EDGE_LOW = false; // + GPIO6_EDGE_HIGH = false; // + GPIO7_LEVEL_LOW = false; // + GPIO7_LEVEL_HIGH = false; // + GPIO7_EDGE_LOW = false; // + GPIO7_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for dormant_wake + register DORMANT_WAKE_INTS0_t DORMANT_WAKE_INTS0 at 0x40014180; + + type DORMANT_WAKE_INTS1_t { + GPIO8_LEVEL_LOW = false; // + GPIO8_LEVEL_HIGH = false; // + GPIO8_EDGE_LOW = false; // + GPIO8_EDGE_HIGH = false; // + GPIO9_LEVEL_LOW = false; // + GPIO9_LEVEL_HIGH = false; // + GPIO9_EDGE_LOW = false; // + GPIO9_EDGE_HIGH = false; // + GPIO10_LEVEL_LOW = false; // + GPIO10_LEVEL_HIGH = false; // + GPIO10_EDGE_LOW = false; // + GPIO10_EDGE_HIGH = false; // + GPIO11_LEVEL_LOW = false; // + GPIO11_LEVEL_HIGH = false; // + GPIO11_EDGE_LOW = false; // + GPIO11_EDGE_HIGH = false; // + GPIO12_LEVEL_LOW = false; // + GPIO12_LEVEL_HIGH = false; // + GPIO12_EDGE_LOW = false; // + GPIO12_EDGE_HIGH = false; // + GPIO13_LEVEL_LOW = false; // + GPIO13_LEVEL_HIGH = false; // + GPIO13_EDGE_LOW = false; // + GPIO13_EDGE_HIGH = false; // + GPIO14_LEVEL_LOW = false; // + GPIO14_LEVEL_HIGH = false; // + GPIO14_EDGE_LOW = false; // + GPIO14_EDGE_HIGH = false; // + GPIO15_LEVEL_LOW = false; // + GPIO15_LEVEL_HIGH = false; // + GPIO15_EDGE_LOW = false; // + GPIO15_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for dormant_wake + register DORMANT_WAKE_INTS1_t DORMANT_WAKE_INTS1 at 0x40014184; + + type DORMANT_WAKE_INTS2_t { + GPIO16_LEVEL_LOW = false; // + GPIO16_LEVEL_HIGH = false; // + GPIO16_EDGE_LOW = false; // + GPIO16_EDGE_HIGH = false; // + GPIO17_LEVEL_LOW = false; // + GPIO17_LEVEL_HIGH = false; // + GPIO17_EDGE_LOW = false; // + GPIO17_EDGE_HIGH = false; // + GPIO18_LEVEL_LOW = false; // + GPIO18_LEVEL_HIGH = false; // + GPIO18_EDGE_LOW = false; // + GPIO18_EDGE_HIGH = false; // + GPIO19_LEVEL_LOW = false; // + GPIO19_LEVEL_HIGH = false; // + GPIO19_EDGE_LOW = false; // + GPIO19_EDGE_HIGH = false; // + GPIO20_LEVEL_LOW = false; // + GPIO20_LEVEL_HIGH = false; // + GPIO20_EDGE_LOW = false; // + GPIO20_EDGE_HIGH = false; // + GPIO21_LEVEL_LOW = false; // + GPIO21_LEVEL_HIGH = false; // + GPIO21_EDGE_LOW = false; // + GPIO21_EDGE_HIGH = false; // + GPIO22_LEVEL_LOW = false; // + GPIO22_LEVEL_HIGH = false; // + GPIO22_EDGE_LOW = false; // + GPIO22_EDGE_HIGH = false; // + GPIO23_LEVEL_LOW = false; // + GPIO23_LEVEL_HIGH = false; // + GPIO23_EDGE_LOW = false; // + GPIO23_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for dormant_wake + register DORMANT_WAKE_INTS2_t DORMANT_WAKE_INTS2 at 0x40014188; + + type DORMANT_WAKE_INTS3_t { + GPIO24_LEVEL_LOW = false; // + GPIO24_LEVEL_HIGH = false; // + GPIO24_EDGE_LOW = false; // + GPIO24_EDGE_HIGH = false; // + GPIO25_LEVEL_LOW = false; // + GPIO25_LEVEL_HIGH = false; // + GPIO25_EDGE_LOW = false; // + GPIO25_EDGE_HIGH = false; // + GPIO26_LEVEL_LOW = false; // + GPIO26_LEVEL_HIGH = false; // + GPIO26_EDGE_LOW = false; // + GPIO26_EDGE_HIGH = false; // + GPIO27_LEVEL_LOW = false; // + GPIO27_LEVEL_HIGH = false; // + GPIO27_EDGE_LOW = false; // + GPIO27_EDGE_HIGH = false; // + GPIO28_LEVEL_LOW = false; // + GPIO28_LEVEL_HIGH = false; // + GPIO28_EDGE_LOW = false; // + GPIO28_EDGE_HIGH = false; // + GPIO29_LEVEL_LOW = false; // + GPIO29_LEVEL_HIGH = false; // + GPIO29_EDGE_LOW = false; // + GPIO29_EDGE_HIGH = false; // + } + + // Interrupt status after masking & forcing for dormant_wake + register DORMANT_WAKE_INTS3_t DORMANT_WAKE_INTS3 at 0x4001418c; + + +/* Types and registers for SYSINFO */ + + type CHIP_ID_t { + MANUFACTURER = uint12(0); // + PART = uint16(0); // + REVISION = uint4(0); // + } + + // JEDEC JEP-106 compliant chip identifier. + register CHIP_ID_t CHIP_ID at 0x40000000; + + type SYSINFO_PLATFORM_t { + FPGA = false; // + ASIC = false; // + } + + // Platform register. Allows software to know what environment it is running in. + register SYSINFO_PLATFORM_t SYSINFO_PLATFORM at 0x40000004; + + type GITREF_RP2040_t { + GITREF_RP2040 = uint32(0); // + } + + // Git hash of the chip source. Used to identify chip version. + register GITREF_RP2040_t GITREF_RP2040 at 0x40000010; + + +/* Types and registers for PPB */ + + type SYST_CSR_t { + ENABLE = false; // Enable SysTick counter: 0 = Counter disabled. 1 = Counter enabled. + TICKINT = false; // Enables SysTick exception request: 0 = Counting down to zero does not assert the SysTick exception request. 1 = Counting down to zero to asserts the SysTick exception request. + CLKSOURCE = false; // SysTick clock source. Always reads as one if SYST_CALIB reports NOREF. Selects the SysTick timer clock source: 0 = External reference clock. 1 = Processor clock. + _res1 = uint8(0); // Reserved, 13 bits + _res2 = uint5(0); // + COUNTFLAG = false; // Returns 1 if timer counted to 0 since last time this was read. Clears on read by application or debugger. + } + + // Use the SysTick Control and Status Register to enable the SysTick features. + register SYST_CSR_t SYST_CSR at 0xe000e010; + + type SYST_RVR_t { + RELOAD = uint24(0); // Value to load into the SysTick Current Value Register when the counter reaches 0. + } + + // Use the SysTick Reload Value Register to specify the start value to load into the current value register when the counter reaches 0. It can be any value between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect because the SysTick interrupt and COUNTFLAG are activated when counting from 1 to 0. The reset value of this register is UNKNOWN. To generate a multi-shot timer with a period of N processor clock cycles, use a RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 clock pulses, set RELOAD to 99. + register SYST_RVR_t SYST_RVR at 0xe000e014; + + type SYST_CVR_t { + CURRENT = uint24(0); // Reads return the current value of the SysTick counter. This register is write-clear. Writing to it with any value clears the register to 0. Clearing this register also clears the COUNTFLAG bit of the SysTick Control and Status Register. + } + + // Use the SysTick Current Value Register to find the current value in the register. The reset value of this register is UNKNOWN. + register SYST_CVR_t SYST_CVR at 0xe000e018; + + type SYST_CALIB_t { + TENMS = uint24(0); // An optional Reload value to be used for 10ms (100Hz) timing, subject to system clock skew errors. If the value reads as 0, the calibration value is not known. + _res1 = uint6(0); // Reserved, 6 bits + SKEW = false; // If reads as 1, the calibration value for 10ms is inexact (due to clock frequency). + NOREF = false; // If reads as 1, the Reference clock is not provided - the CLKSOURCE bit of the SysTick Control and Status register will be forced to 1 and cannot be cleared to 0. + } + + // Use the SysTick Calibration Value Register to enable software to scale to any required speed using divide and multiply. + register SYST_CALIB_t SYST_CALIB at 0xe000e01c; + + type NVIC_ISER_t { + SETENA = uint32(0); // Interrupt set-enable bits. Write: 0 = No effect. 1 = Enable interrupt. Read: 0 = Interrupt disabled. 1 = Interrupt enabled. + } + + // Use the Interrupt Set-Enable Register to enable interrupts and determine which interrupts are currently enabled. If a pending interrupt is enabled, the NVIC activates the interrupt based on its priority. If an interrupt is not enabled, asserting its interrupt signal changes the interrupt state to pending, but the NVIC never activates the interrupt, regardless of its priority. + register NVIC_ISER_t NVIC_ISER at 0xe000e100; + + type NVIC_ICER_t { + CLRENA = uint32(0); // Interrupt clear-enable bits. Write: 0 = No effect. 1 = Disable interrupt. Read: 0 = Interrupt disabled. 1 = Interrupt enabled. + } + + // Use the Interrupt Clear-Enable Registers to disable interrupts and determine which interrupts are currently enabled. + register NVIC_ICER_t NVIC_ICER at 0xe000e180; + + type NVIC_ISPR_t { + SETPEND = uint32(0); // Interrupt set-pending bits. Write: 0 = No effect. 1 = Changes interrupt state to pending. Read: 0 = Interrupt is not pending. 1 = Interrupt is pending. Note: Writing 1 to the NVIC_ISPR bit corresponding to: An interrupt that is pending has no effect. A disabled interrupt sets the state of that interrupt to pending. + } + + // The NVIC_ISPR forces interrupts into the pending state, and shows which interrupts are pending. + register NVIC_ISPR_t NVIC_ISPR at 0xe000e200; + + type NVIC_ICPR_t { + CLRPEND = uint32(0); // Interrupt clear-pending bits. Write: 0 = No effect. 1 = Removes pending state and interrupt. Read: 0 = Interrupt is not pending. 1 = Interrupt is pending. + } + + // Use the Interrupt Clear-Pending Register to clear pending interrupts and determine which interrupts are currently pending. + register NVIC_ICPR_t NVIC_ICPR at 0xe000e280; + + type NVIC_IPR0_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_0 = uint2(0); // Priority of interrupt 0 + _res2 = uint6(0); // Reserved, 6 bits + IP_1 = uint2(0); // Priority of interrupt 1 + _res3 = uint6(0); // Reserved, 6 bits + IP_2 = uint2(0); // Priority of interrupt 2 + _res4 = uint6(0); // Reserved, 6 bits + IP_3 = uint2(0); // Priority of interrupt 3 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. Note: Writing 1 to an NVIC_ICPR bit does not affect the active state of the corresponding interrupt. These registers are only word-accessible + register NVIC_IPR0_t NVIC_IPR0 at 0xe000e400; + + type NVIC_IPR1_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_4 = uint2(0); // Priority of interrupt 4 + _res2 = uint6(0); // Reserved, 6 bits + IP_5 = uint2(0); // Priority of interrupt 5 + _res3 = uint6(0); // Reserved, 6 bits + IP_6 = uint2(0); // Priority of interrupt 6 + _res4 = uint6(0); // Reserved, 6 bits + IP_7 = uint2(0); // Priority of interrupt 7 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR1_t NVIC_IPR1 at 0xe000e404; + + type NVIC_IPR2_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_8 = uint2(0); // Priority of interrupt 8 + _res2 = uint6(0); // Reserved, 6 bits + IP_9 = uint2(0); // Priority of interrupt 9 + _res3 = uint6(0); // Reserved, 6 bits + IP_10 = uint2(0); // Priority of interrupt 10 + _res4 = uint6(0); // Reserved, 6 bits + IP_11 = uint2(0); // Priority of interrupt 11 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR2_t NVIC_IPR2 at 0xe000e408; + + type NVIC_IPR3_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_12 = uint2(0); // Priority of interrupt 12 + _res2 = uint6(0); // Reserved, 6 bits + IP_13 = uint2(0); // Priority of interrupt 13 + _res3 = uint6(0); // Reserved, 6 bits + IP_14 = uint2(0); // Priority of interrupt 14 + _res4 = uint6(0); // Reserved, 6 bits + IP_15 = uint2(0); // Priority of interrupt 15 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR3_t NVIC_IPR3 at 0xe000e40c; + + type NVIC_IPR4_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_16 = uint2(0); // Priority of interrupt 16 + _res2 = uint6(0); // Reserved, 6 bits + IP_17 = uint2(0); // Priority of interrupt 17 + _res3 = uint6(0); // Reserved, 6 bits + IP_18 = uint2(0); // Priority of interrupt 18 + _res4 = uint6(0); // Reserved, 6 bits + IP_19 = uint2(0); // Priority of interrupt 19 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR4_t NVIC_IPR4 at 0xe000e410; + + type NVIC_IPR5_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_20 = uint2(0); // Priority of interrupt 20 + _res2 = uint6(0); // Reserved, 6 bits + IP_21 = uint2(0); // Priority of interrupt 21 + _res3 = uint6(0); // Reserved, 6 bits + IP_22 = uint2(0); // Priority of interrupt 22 + _res4 = uint6(0); // Reserved, 6 bits + IP_23 = uint2(0); // Priority of interrupt 23 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR5_t NVIC_IPR5 at 0xe000e414; + + type NVIC_IPR6_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_24 = uint2(0); // Priority of interrupt 24 + _res2 = uint6(0); // Reserved, 6 bits + IP_25 = uint2(0); // Priority of interrupt 25 + _res3 = uint6(0); // Reserved, 6 bits + IP_26 = uint2(0); // Priority of interrupt 26 + _res4 = uint6(0); // Reserved, 6 bits + IP_27 = uint2(0); // Priority of interrupt 27 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR6_t NVIC_IPR6 at 0xe000e418; + + type NVIC_IPR7_t { + _res1 = uint6(0); // Reserved, 6 bits + IP_28 = uint2(0); // Priority of interrupt 28 + _res2 = uint6(0); // Reserved, 6 bits + IP_29 = uint2(0); // Priority of interrupt 29 + _res3 = uint6(0); // Reserved, 6 bits + IP_30 = uint2(0); // Priority of interrupt 30 + _res4 = uint6(0); // Reserved, 6 bits + IP_31 = uint2(0); // Priority of interrupt 31 + } + + // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + register NVIC_IPR7_t NVIC_IPR7 at 0xe000e41c; + + type PPB_CPUID_t { + REVISION = uint4(0); // Minor revision number m in the rnpm revision status: 0x1 = Patch 1. + PARTNO = uint12(0); // Number of processor within family: 0xC60 = Cortex-M0+ + ARCHITECTURE = uint4(0); // Constant that defines the architecture of the processor: 0xC = ARMv6-M architecture. + VARIANT = uint4(0); // Major revision number n in the rnpm revision status: 0x0 = Revision 0. + IMPLEMENTER = uint8(0); // Implementor code: 0x41 = ARM + } + + // Read the CPU ID Base Register to determine: the ID number of the processor core, the version number of the processor core, the implementation details of the processor core. + register PPB_CPUID_t PPB_CPUID at 0xe000ed00; + + type ICSR_t { + VECTACTIVE = uint9(0); // Active exception number field. Reset clears the VECTACTIVE field. + _res1 = uint3(0); // Reserved, 3 bits + VECTPENDING = uint9(0); // Indicates the exception number for the highest priority pending exception: 0 = no pending exceptions. Non zero = The pending state includes the effect of memory-mapped enable and mask registers. It does not include the PRIMASK special-purpose register qualifier. + _res2 = false; // Reserved, 1 bits + ISRPENDING = false; // External interrupt pending flag + ISRPREEMPT = false; // The system can only access this bit when the core is halted. It indicates that a pending interrupt is to be taken in the next running cycle. If C_MASKINTS is clear in the Debug Halting Control and Status Register, the interrupt is serviced. + _res3 = false; // Reserved, 1 bits + PENDSTCLR = false; // SysTick exception clear-pending bit. Write: 0 = No effect. 1 = Removes the pending state from the SysTick exception. This bit is WO. On a register read its value is Unknown. + PENDSTSET = false; // SysTick exception set-pending bit. Write: 0 = No effect. 1 = Changes SysTick exception state to pending. Read: 0 = SysTick exception is not pending. 1 = SysTick exception is pending. + PENDSVCLR = false; // PendSV clear-pending bit. Write: 0 = No effect. 1 = Removes the pending state from the PendSV exception. + PENDSVSET = false; // PendSV set-pending bit. Write: 0 = No effect. 1 = Changes PendSV exception state to pending. Read: 0 = PendSV exception is not pending. 1 = PendSV exception is pending. Writing 1 to this bit is the only way to set the PendSV exception state to pending. + _res4 = uint2(0); // Reserved, 2 bits + NMIPENDSET = false; // Setting this bit will activate an NMI. Since NMI is the highest priority exception, it will activate as soon as it is registered. NMI set-pending bit. Write: 0 = No effect. 1 = Changes NMI exception state to pending. Read: 0 = NMI exception is not pending. 1 = NMI exception is pending. Because NMI is the highest-priority exception, normally the processor enters the NMI exception handler as soon as it detects a write of 1 to this bit. Entering the handler then clears this bit to 0. This means a read of this bit by the NMI exception handler returns 1 only if the NMI signal is reasserted while the processor is executing that handler. + } + + // Use the Interrupt Control State Register to set a pending Non-Maskable Interrupt (NMI), set or clear a pending PendSV, set or clear a pending SysTick, check for pending exceptions, check the vector number of the highest priority pended exception, check the vector number of the active exception. + register ICSR_t ICSR at 0xe000ed04; + + type VTOR_t { + _res1 = uint8(0); // Reserved, 8 bits + TBLOFF = uint24(0); // Bits [31:8] of the indicate the vector table offset address. + } + + // The VTOR holds the vector table offset address. + register VTOR_t VTOR at 0xe000ed08; + + type AIRCR_t { + _res1 = false; // Reserved, 1 bits + VECTCLRACTIVE = false; // Clears all active state information for fixed and configurable exceptions. This bit: is self-clearing, can only be set by the DAP when the core is halted. When set: clears all active exception status of the processor, forces a return to Thread mode, forces an IPSR of 0. A debugger must re-initialize the stack. + SYSRESETREQ = false; // Writing 1 to this bit causes the SYSRESETREQ signal to the outer system to be asserted to request a reset. The intention is to force a large system reset of all major components except for debug. The C_HALT bit in the DHCSR is cleared as a result of the system reset requested. The debugger does not lose contact with the device. + _res2 = uint8(0); // Reserved, 12 bits + _res3 = uint4(0); // + ENDIANESS = false; // Data endianness implemented: 0 = Little-endian. + VECTKEY = uint16(0); // Register key: Reads as Unknown On writes, write 0x05FA to VECTKEY, otherwise the write is ignored. + } + + // Use the Application Interrupt and Reset Control Register to: determine data endianness, clear all active state information from debug halt mode, request a system reset. + register AIRCR_t AIRCR at 0xe000ed0c; + + type SCR_t { + _res1 = false; // Reserved, 1 bits + SLEEPONEXIT = false; // Indicates sleep-on-exit when returning from Handler mode to Thread mode: 0 = Do not sleep when returning to Thread mode. 1 = Enter sleep, or deep sleep, on return from an ISR to Thread mode. Setting this bit to 1 enables an interrupt driven application to avoid returning to an empty main application. + SLEEPDEEP = false; // Controls whether the processor uses sleep or deep sleep as its low power mode: 0 = Sleep. 1 = Deep sleep. + _res2 = false; // Reserved, 1 bits + SEVONPEND = false; // Send Event on Pending bit: 0 = Only enabled interrupts or events can wakeup the processor, disabled interrupts are excluded. 1 = Enabled events and all interrupts, including disabled interrupts, can wakeup the processor. When an event or interrupt becomes pending, the event signal wakes up the processor from WFE. If the processor is not waiting for an event, the event is registered and affects the next WFE. The processor also wakes up on execution of an SEV instruction or an external event. + } + + // System Control Register. Use the System Control Register for power-management functions: signal to the system when the processor can enter a low power state, control how the processor enters and exits low power states. + register SCR_t SCR at 0xe000ed10; + + type CCR_t { + _res1 = uint3(0); // Reserved, 3 bits + UNALIGN_TRP = false; // Always reads as one, indicates that all unaligned accesses generate a HardFault. + _res2 = uint5(0); // Reserved, 5 bits + STKALIGN = false; // Always reads as one, indicates 8-byte stack alignment on exception entry. On exception entry, the processor uses bit[9] of the stacked PSR to indicate the stack alignment. On return from the exception it uses this stacked bit to restore the correct stack alignment. + } + + // The Configuration and Control Register permanently enables stack alignment and causes unaligned accesses to result in a Hard Fault. + register CCR_t CCR at 0xe000ed14; + + type SHPR2_t { + _res1 = uint16(0); // Reserved, 30 bits + _res2 = uint8(0); // + _res3 = uint6(0); // + PRI_11 = uint2(0); // Priority of system handler 11, SVCall + } + + // System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 2 to set the priority of SVCall. + register SHPR2_t SHPR2 at 0xe000ed1c; + + type SHPR3_t { + _res1 = uint16(0); // Reserved, 22 bits + _res2 = uint6(0); // + PRI_14 = uint2(0); // Priority of system handler 14, PendSV + _res3 = uint6(0); // Reserved, 6 bits + PRI_15 = uint2(0); // Priority of system handler 15, SysTick + } + + // System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 3 to set the priority of PendSV and SysTick. + register SHPR3_t SHPR3 at 0xe000ed20; + + type SHCSR_t { + _res1 = uint8(0); // Reserved, 15 bits + _res2 = uint7(0); // + SVCALLPENDED = false; // Reads as 1 if SVCall is Pending. Write 1 to set pending SVCall, write 0 to clear pending SVCall. + } + + // Use the System Handler Control and State Register to determine or clear the pending status of SVCall. + register SHCSR_t SHCSR at 0xe000ed24; + + type MPU_TYPE_t { + SEPARATE = false; // Indicates support for separate instruction and data address maps. Reads as 0 as ARMv6-M only supports a unified MPU. + _res1 = uint7(0); // Reserved, 7 bits + DREGION = uint8(0); // Number of regions supported by the MPU. + IREGION = uint8(0); // Instruction region. Reads as zero as ARMv6-M only supports a unified MPU. + } + + // Read the MPU Type Register to determine if the processor implements an MPU, and how many regions the MPU supports. + register MPU_TYPE_t MPU_TYPE at 0xe000ed90; + + type MPU_CTRL_t { + ENABLE = false; // Enables the MPU. If the MPU is disabled, privileged and unprivileged accesses use the default memory map. 0 = MPU disabled. 1 = MPU enabled. + HFNMIENA = false; // Controls the use of the MPU for HardFaults and NMIs. Setting this bit when ENABLE is clear results in UNPREDICTABLE behaviour. When the MPU is enabled: 0 = MPU is disabled during HardFault and NMI handlers, regardless of the value of the ENABLE bit. 1 = the MPU is enabled during HardFault and NMI handlers. + PRIVDEFENA = false; // Controls whether the default memory map is enabled as a background region for privileged accesses. This bit is ignored when ENABLE is clear. 0 = If the MPU is enabled, disables use of the default memory map. Any memory access to a location not covered by any enabled region causes a fault. 1 = If the MPU is enabled, enables use of the default memory map as a background region for privileged software accesses. When enabled, the background region acts as if it is region number -1. Any region that is defined and enabled has priority over this default map. + } + + // Use the MPU Control Register to enable and disable the MPU, and to control whether the default memory map is enabled as a background region for privileged accesses, and whether the MPU is enabled for HardFaults and NMIs. + register MPU_CTRL_t MPU_CTRL at 0xe000ed94; + + type MPU_RNR_t { + REGION = uint4(0); // Indicates the MPU region referenced by the MPU_RBAR and MPU_RASR registers. The MPU supports 8 memory regions, so the permitted values of this field are 0-7. + } + + // Use the MPU Region Number Register to select the region currently accessed by MPU_RBAR and MPU_RASR. + register MPU_RNR_t MPU_RNR at 0xe000ed98; + + type MPU_RBAR_t { + REGION = uint4(0); // On writes, specifies the number of the region whose base address to update provided VALID is set written as 1. On reads, returns bits [3:0] of MPU_RNR. + VALID = false; // On writes, indicates whether the write must update the base address of the region identified by the REGION field, updating the MPU_RNR to indicate this new region. Write: 0 = MPU_RNR not changed, and the processor: Updates the base address for the region specified in the MPU_RNR. Ignores the value of the REGION field. 1 = The processor: Updates the value of the MPU_RNR to the value of the REGION field. Updates the base address for the region specified in the REGION field. Always reads as zero. + _res1 = uint3(0); // Reserved, 3 bits + ADDR = uint24(0); // Base address of the region. + } + + // Read the MPU Region Base Address Register to determine the base address of the region identified by MPU_RNR. Write to update the base address of said region or that of a specified region, with whose number MPU_RNR will also be updated. + register MPU_RBAR_t MPU_RBAR at 0xe000ed9c; + + type MPU_RASR_t { + ENABLE = false; // Enables the region. + SIZE = uint5(0); // Indicates the region size. Region size in bytes = 2^(SIZE+1). The minimum permitted value is 7 (b00111) = 256Bytes + _res1 = uint2(0); // Reserved, 2 bits + SRD = uint8(0); // Subregion Disable. For regions of 256 bytes or larger, each bit of this field controls whether one of the eight equal subregions is enabled. + ATTRS = uint16(0); // The MPU Region Attribute field. Use to define the region attribute control. 28 = XN: Instruction access disable bit: 0 = Instruction fetches enabled. 1 = Instruction fetches disabled. 26:24 = AP: Access permission field 18 = S: Shareable bit 17 = C: Cacheable bit 16 = B: Bufferable bit + } + + // Use the MPU Region Attribute and Size Register to define the size, access behaviour and memory type of the region identified by MPU_RNR, and enable that region. + register MPU_RASR_t MPU_RASR at 0xe000eda0; + + +/* Types and registers for SSI + DW_apb_ssi has the following features: * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. * APB3 and APB4 protocol support. * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits. * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices. * Programmable Dual/Quad/Octal SPI support in Master Mode. * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation. * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes. * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes. * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests. * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently. * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus. * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains. * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates. * Programmable features: - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire. - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation. - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer. * Configured features: - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits. - 1 slave select output. - Hardware slave-select – Dedicated hardware slave-select line. - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller. - Interrupt polarity – active high interrupt lines. - Serial clock polarity – low serial-clock polarity directly after reset. - Serial clock phase – capture on first edge of serial-clock directly after reset. + */ + + type CTRLR0_t { + DFS = uint4(0); // Data frame size + FRF = uint2(0); // Frame format + SCPH = false; // Serial clock phase + SCPOL = false; // Serial clock polarity + TMOD = uint2(0); // Transfer mode + SLV_OE = false; // Slave output enable + SRL = false; // Shift register loop (test mode) + CFS = uint4(0); // Control frame size Value of n -> n+1 clocks per frame. + DFS_32 = uint5(0); // Data frame size in 32b transfer mode Value of n -> n+1 clocks per frame. + SPI_FRF = uint2(0); // SPI frame format + _res1 = false; // Reserved, 1 bits + SSTE = false; // Slave select toggle enable + } + + // Control register 0 + register CTRLR0_t CTRLR0 at 0x18000000; + + type CTRLR1_t { + NDF = uint16(0); // Number of data frames + } + + // Master Control register 1 + register CTRLR1_t CTRLR1 at 0x18000004; + + type SSIENR_t { + SSI_EN = false; // SSI enable + } + + // SSI Enable + register SSIENR_t SSIENR at 0x18000008; + + type MWCR_t { + MWMOD = false; // Microwire transfer mode + MDD = false; // Microwire control + MHS = false; // Microwire handshaking + } + + // Microwire Control + register MWCR_t MWCR at 0x1800000c; + + type SER_t { + SER = false; // For each bit: 0 -> slave not selected 1 -> slave selected + } + + // Slave enable + register SER_t SER at 0x18000010; + + type BAUDR_t { + SCKDV = uint16(0); // SSI clock divider + } + + // Baud rate + register BAUDR_t BAUDR at 0x18000014; + + type TXFTLR_t { + TFT = uint8(0); // Transmit FIFO threshold + } + + // TX FIFO threshold level + register TXFTLR_t TXFTLR at 0x18000018; + + type RXFTLR_t { + RFT = uint8(0); // Receive FIFO threshold + } + + // RX FIFO threshold level + register RXFTLR_t RXFTLR at 0x1800001c; + + type TXFLR_t { + TFTFL = uint8(0); // Transmit FIFO level + } + + // TX FIFO level + register TXFLR_t TXFLR at 0x18000020; + + type RXFLR_t { + RXTFL = uint8(0); // Receive FIFO level + } + + // RX FIFO level + register RXFLR_t RXFLR at 0x18000024; + + type SR_t { + BUSY = false; // SSI busy flag + TFNF = false; // Transmit FIFO not full + TFE = false; // Transmit FIFO empty + RFNE = false; // Receive FIFO not empty + RFF = false; // Receive FIFO full + TXE = false; // Transmission error + DCOL = false; // Data collision error + } + + // Status register + register SR_t SR at 0x18000028; + + type IMR_t { + TXEIM = false; // Transmit FIFO empty interrupt mask + TXOIM = false; // Transmit FIFO overflow interrupt mask + RXUIM = false; // Receive FIFO underflow interrupt mask + RXOIM = false; // Receive FIFO overflow interrupt mask + RXFIM = false; // Receive FIFO full interrupt mask + MSTIM = false; // Multi-master contention interrupt mask + } + + // Interrupt mask + register IMR_t IMR at 0x1800002c; + + type ISR_t { + TXEIS = false; // Transmit FIFO empty interrupt status + TXOIS = false; // Transmit FIFO overflow interrupt status + RXUIS = false; // Receive FIFO underflow interrupt status + RXOIS = false; // Receive FIFO overflow interrupt status + RXFIS = false; // Receive FIFO full interrupt status + MSTIS = false; // Multi-master contention interrupt status + } + + // Interrupt status + register ISR_t ISR at 0x18000030; + + type RISR_t { + TXEIR = false; // Transmit FIFO empty raw interrupt status + TXOIR = false; // Transmit FIFO overflow raw interrupt status + RXUIR = false; // Receive FIFO underflow raw interrupt status + RXOIR = false; // Receive FIFO overflow raw interrupt status + RXFIR = false; // Receive FIFO full raw interrupt status + MSTIR = false; // Multi-master contention raw interrupt status + } + + // Raw interrupt status + register RISR_t RISR at 0x18000034; + + type TXOICR_t { + TXOICR = false; // Clear-on-read transmit FIFO overflow interrupt + } + + // TX FIFO overflow interrupt clear + register TXOICR_t TXOICR at 0x18000038; + + type RXOICR_t { + RXOICR = false; // Clear-on-read receive FIFO overflow interrupt + } + + // RX FIFO overflow interrupt clear + register RXOICR_t RXOICR at 0x1800003c; + + type RXUICR_t { + RXUICR = false; // Clear-on-read receive FIFO underflow interrupt + } + + // RX FIFO underflow interrupt clear + register RXUICR_t RXUICR at 0x18000040; + + type MSTICR_t { + MSTICR = false; // Clear-on-read multi-master contention interrupt + } + + // Multi-master interrupt clear + register MSTICR_t MSTICR at 0x18000044; + + type ICR_t { + ICR = false; // Clear-on-read all active interrupts + } + + // Interrupt clear + register ICR_t ICR at 0x18000048; + + type DMACR_t { + RDMAE = false; // Receive DMA enable + TDMAE = false; // Transmit DMA enable + } + + // DMA control + register DMACR_t DMACR at 0x1800004c; + + type DMATDLR_t { + DMATDL = uint8(0); // Transmit data watermark level + } + + // DMA TX data level + register DMATDLR_t DMATDLR at 0x18000050; + + type DMARDLR_t { + DMARDL = uint8(0); // Receive data watermark level (DMARDLR+1) + } + + // DMA RX data level + register DMARDLR_t DMARDLR at 0x18000054; + + type IDR_t { + IDCODE = uint32(0); // Peripheral dentification code + } + + // Identification register + register IDR_t IDR at 0x18000058; + + type SSI_VERSION_ID_t { + SSI_COMP_VERSION = uint32(0); // SNPS component version (format X.YY) + } + + // Version ID + register SSI_VERSION_ID_t SSI_VERSION_ID at 0x1800005c; + + type DR0_t { + DR = uint32(0); // First data register of 36 + } + + // Data Register 0 (of 36) + register DR0_t DR0 at 0x18000060; + + type RX_SAMPLE_DLY_t { + RSD = uint8(0); // RXD sample delay (in SCLK cycles) + } + + // RX sample delay + register RX_SAMPLE_DLY_t RX_SAMPLE_DLY at 0x180000f0; + + type SPI_CTRLR0_t { + TRANS_TYPE = uint2(0); // Address and instruction transfer format + ADDR_L = uint4(0); // Address length (0b-60b in 4b increments) + _res1 = uint2(0); // Reserved, 2 bits + INST_L = uint2(0); // Instruction length (0/4/8/16b) + _res2 = false; // Reserved, 1 bits + WAIT_CYCLES = uint5(0); // Wait cycles between control frame transmit and data reception (in SCLK cycles) + SPI_DDR_EN = false; // SPI DDR transfer enable + INST_DDR_EN = false; // Instruction DDR transfer enable + SPI_RXDS_EN = false; // Read data strobe enable + _res3 = uint5(0); // Reserved, 5 bits + XIP_CMD = uint8(0); // SPI Command to send in XIP mode (INST_L = 8-bit) or to append to Address (INST_L = 0-bit) + } + + // SPI control + register SPI_CTRLR0_t SPI_CTRLR0 at 0x180000f4; + + type TXD_DRIVE_EDGE_t { + TDE = uint8(0); // TXD drive edge + } + + // TX drive edge + register TXD_DRIVE_EDGE_t TXD_DRIVE_EDGE at 0x180000f8; + + +/* Types and registers for XIP_CTRL + QSPI flash execute-in-place block + */ + + type XIP_CTRL_CTRL_t { + EN = false; // When 1, enable the cache. When the cache is disabled, all XIP accesses will go straight to the flash, without querying the cache. When enabled, cacheable XIP accesses will query the cache, and the flash will not be accessed if the tag matches and the valid bit is set. If the cache is enabled, cache-as-SRAM accesses have no effect on the cache data RAM, and will produce a bus error response. + ERR_BADWRITE = false; // When 1, writes to any alias other than 0x0 (caching, allocating) will produce a bus fault. When 0, these writes are silently ignored. In either case, writes to the 0x0 alias will deallocate on tag match, as usual. + _res1 = false; // Reserved, 1 bits + POWER_DOWN = false; // When 1, the cache memories are powered down. They retain state, but can not be accessed. This reduces static power dissipation. Writing 1 to this bit forces CTRL_EN to 0, i.e. the cache cannot be enabled when powered down. Cache-as-SRAM accesses will produce a bus error response when the cache is powered down. + } + + // Cache control + register XIP_CTRL_CTRL_t XIP_CTRL_CTRL at 0x14000000; + + type FLUSH_t { + FLUSH = false; // Write 1 to flush the cache. This clears the tag memory, but the data memory retains its contents. (This means cache-as-SRAM contents is not affected by flush or reset.) Reading will hold the bus (stall the processor) until the flush completes. Alternatively STAT can be polled until completion. + } + + // Cache Flush control + register FLUSH_t FLUSH at 0x14000004; + + type STAT_t { + FLUSH_READY = false; // Reads as 0 while a cache flush is in progress, and 1 otherwise. The cache is flushed whenever the XIP block is reset, and also when requested via the FLUSH register. + FIFO_EMPTY = false; // When 1, indicates the XIP streaming FIFO is completely empty. + FIFO_FULL = false; // When 1, indicates the XIP streaming FIFO is completely full. The streaming FIFO is 2 entries deep, so the full and empty flag allow its level to be ascertained. + } + + // Cache Status + register STAT_t STAT at 0x14000008; + + type CTR_HIT_t { + CTR_HIT = uint32(0); // A 32 bit saturating counter that increments upon each cache hit, i.e. when an XIP access is serviced directly from cached data. Write any value to clear. + } + + // Cache Hit counter + register CTR_HIT_t CTR_HIT at 0x1400000c; + + type CTR_ACC_t { + CTR_ACC = uint32(0); // A 32 bit saturating counter that increments upon each XIP access, whether the cache is hit or not. This includes noncacheable accesses. Write any value to clear. + } + + // Cache Access counter + register CTR_ACC_t CTR_ACC at 0x14000010; + + type STREAM_ADDR_t { + _res1 = uint2(0); // Reserved, 2 bits + STREAM_ADDR = uint30(0); // The address of the next word to be streamed from flash to the streaming FIFO. Increments automatically after each flash access. Write the initial access address here before starting a streaming read. + } + + // FIFO stream address + register STREAM_ADDR_t STREAM_ADDR at 0x14000014; + + type STREAM_CTR_t { + STREAM_CTR = uint22(0); // Write a nonzero value to start a streaming read. This will then progress in the background, using flash idle cycles to transfer a linear data block from flash to the streaming FIFO. Decrements automatically (1 at a time) as the stream progresses, and halts on reaching 0. Write 0 to halt an in-progress stream, and discard any in-flight read, so that a new stream can immediately be started (after draining the FIFO and reinitialising STREAM_ADDR) + } + + // FIFO stream control + register STREAM_CTR_t STREAM_CTR at 0x14000018; + + type STREAM_FIFO_t { + STREAM_FIFO = uint32(0); // Streamed data is buffered here, for retrieval by the system DMA. This FIFO can also be accessed via the XIP_AUX slave, to avoid exposing the DMA to bus stalls caused by other XIP traffic. + } + + // FIFO stream data + register STREAM_FIFO_t STREAM_FIFO at 0x1400001c; + + +/* Types and registers for SYSCFG + Register block for various chip control signals + */ + + type PROC0_NMI_MASK_t { + PROC0_NMI_MASK = uint32(0); // Set a bit high to enable NMI from that IRQ + } + + // Processor core 0 NMI source mask + register PROC0_NMI_MASK_t PROC0_NMI_MASK at 0x40004000; + + type PROC1_NMI_MASK_t { + PROC1_NMI_MASK = uint32(0); // Set a bit high to enable NMI from that IRQ + } + + // Processor core 1 NMI source mask + register PROC1_NMI_MASK_t PROC1_NMI_MASK at 0x40004004; + + type PROC_CONFIG_t { + PROC0_HALTED = false; // Indication that proc0 has halted + PROC1_HALTED = false; // Indication that proc1 has halted + _res1 = uint16(0); // Reserved, 22 bits + _res2 = uint6(0); // + PROC0_DAP_INSTID = uint4(0); // Configure proc0 DAP instance ID. Recommend that this is NOT changed until you require debug access in multi-chip environment WARNING: do not set to 15 as this is reserved for RescueDP + PROC1_DAP_INSTID = uint4(0); // Configure proc1 DAP instance ID. Recommend that this is NOT changed until you require debug access in multi-chip environment WARNING: do not set to 15 as this is reserved for RescueDP + } + + // Configuration for processors + register PROC_CONFIG_t PROC_CONFIG at 0x40004008; + + type PROC_IN_SYNC_BYPASS_t { + PROC_IN_SYNC_BYPASS = uint30(0); // + } + + // For each bit, if 1, bypass the input synchronizer between that GPIO and the GPIO input register in the SIO. The input synchronizers should generally be unbypassed, to avoid injecting metastabilities into processors. If you're feeling brave, you can bypass to save two cycles of input latency. This register applies to GPIO 0...29. + register PROC_IN_SYNC_BYPASS_t PROC_IN_SYNC_BYPASS at 0x4000400c; + + type PROC_IN_SYNC_BYPASS_HI_t { + PROC_IN_SYNC_BYPASS_HI = uint6(0); // + } + + // For each bit, if 1, bypass the input synchronizer between that GPIO and the GPIO input register in the SIO. The input synchronizers should generally be unbypassed, to avoid injecting metastabilities into processors. If you're feeling brave, you can bypass to save two cycles of input latency. This register applies to GPIO 30...35 (the QSPI IOs). + register PROC_IN_SYNC_BYPASS_HI_t PROC_IN_SYNC_BYPASS_HI at 0x40004010; + + type DBGFORCE_t { + PROC0_SWDO = false; // Observe the value of processor 0 SWDIO output. + PROC0_SWDI = false; // Directly drive processor 0 SWDIO input, if PROC0_ATTACH is set + PROC0_SWCLK = false; // Directly drive processor 0 SWCLK, if PROC0_ATTACH is set + PROC0_ATTACH = false; // Attach processor 0 debug port to syscfg controls, and disconnect it from external SWD pads. + PROC1_SWDO = false; // Observe the value of processor 1 SWDIO output. + PROC1_SWDI = false; // Directly drive processor 1 SWDIO input, if PROC1_ATTACH is set + PROC1_SWCLK = false; // Directly drive processor 1 SWCLK, if PROC1_ATTACH is set + PROC1_ATTACH = false; // Attach processor 1 debug port to syscfg controls, and disconnect it from external SWD pads. + } + + // Directly control the SWD debug port of either processor + register DBGFORCE_t DBGFORCE at 0x40004014; + + type MEMPOWERDOWN_t { + SRAM0 = false; // + SRAM1 = false; // + SRAM2 = false; // + SRAM3 = false; // + SRAM4 = false; // + SRAM5 = false; // + USB = false; // + ROM = false; // + } + + // Control power downs to memories. Set high to power down memories. Use with extreme caution + register MEMPOWERDOWN_t MEMPOWERDOWN at 0x40004018; + + +/* Types and registers for XOSC + Controls the crystal oscillator + */ + + type XOSC_CTRL_t { + FREQ_RANGE = uint12(0); // Frequency range. An invalid setting will retain the previous value. The actual value being used can be read from STATUS_FREQ_RANGE. This resets to 0xAA0 and cannot be changed. + ENABLE = uint12(0); // On power-up this field is initialised to DISABLE and the chip runs from the ROSC. If the chip has subsequently been programmed to run from the XOSC then DISABLE may lock-up the chip. If this is a concern then run the clk_ref from the ROSC and enable the clk_sys RESUS feature. The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + } + + // Crystal Oscillator Control + register XOSC_CTRL_t XOSC_CTRL at 0x40024000; + + type XOSC_STATUS_t { + FREQ_RANGE = uint2(0); // The current frequency range setting, always reads 0 + _res1 = uint8(0); // Reserved, 10 bits + _res2 = uint2(0); // + ENABLED = false; // Oscillator is enabled but not necessarily running and stable, resets to 0 + _res3 = uint8(0); // Reserved, 11 bits + _res4 = uint3(0); // + BADWRITE = false; // An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or DORMANT + _res5 = uint6(0); // Reserved, 6 bits + STABLE = false; // Oscillator is running and stable + } + + // Crystal Oscillator Status + register XOSC_STATUS_t XOSC_STATUS at 0x40024004; + + type XOSC_DORMANT_t { + DORMANT = uint32(0); // This is used to save power by pausing the XOSC On power-up this field is initialised to WAKE An invalid write will also select WAKE Warning: stop the PLLs before selecting dormant mode Warning: setup the irq before selecting dormant mode + } + + // Crystal Oscillator pause control + register XOSC_DORMANT_t XOSC_DORMANT at 0x40024008; + + type STARTUP_t { + DELAY = uint14(0); // in multiples of 256*xtal_period. The reset value of 0xc4 corresponds to approx 50 000 cycles. + _res1 = uint6(0); // Reserved, 6 bits + X4 = false; // Multiplies the startup_delay by 4. This is of little value to the user given that the delay can be programmed directly. + } + + // Controls the startup delay + register STARTUP_t STARTUP at 0x4002400c; + + type XOSC_COUNT_t { + COUNT = uint8(0); // + } + + // A down counter running at the xosc frequency which counts to zero and stops. To start the counter write a non-zero value. Can be used for short software pauses when setting up time sensitive hardware. + register XOSC_COUNT_t XOSC_COUNT at 0x4002401c; + + +/* Types and registers for PLL_SYS */ + + type PLL_SYS_CS_t { + REFDIV = uint6(0); // Divides the PLL input reference clock. Behaviour is undefined for div=0. PLL output will be unpredictable during refdiv changes, wait for lock=1 before using it. + _res1 = uint2(0); // Reserved, 2 bits + BYPASS = false; // Passes the reference clock to the output instead of the divided VCO. The VCO continues to run so the user can switch between the reference clock and the divided VCO but the output will glitch when doing so. + _res2 = uint16(0); // Reserved, 22 bits + _res3 = uint6(0); // + LOCK = false; // PLL is locked + } + + // PLL_SYS Control and Status GENERAL CONSTRAINTS: Reference clock frequency min=5MHz, max=800MHz Feedback divider min=16, max=320 VCO frequency min=750MHz, max=1600MHz + register PLL_SYS_CS_t PLL_SYS_PLL_SYS_CS at 0x40028000; + + type PWR_t { + PD = false; // PLL powerdown To save power set high when PLL output not required. + _res1 = false; // Reserved, 1 bits + DSMPD = false; // PLL DSM powerdown Nothing is achieved by setting this low. + POSTDIVPD = false; // PLL post divider powerdown To save power set high when PLL output not required or bypass=1. + _res2 = false; // Reserved, 1 bits + VCOPD = false; // PLL VCO powerdown To save power set high when PLL output not required or bypass=1. + } + + // PLL_SYS Controls the PLL power modes. + register PWR_t PLL_SYS_PWR at 0x40028004; + + type FBDIV_INT_t { + FBDIV_INT = uint12(0); // see ctrl reg description for constraints + } + + // PLL_SYS Feedback divisor (note: this PLL does not support fractional division) + register FBDIV_INT_t PLL_SYS_FBDIV_INT at 0x40028008; + + type PRIM_t { + _res1 = uint8(0); // Reserved, 12 bits + _res2 = uint4(0); // + POSTDIV2 = uint3(0); // divide by 1-7 + _res3 = false; // Reserved, 1 bits + POSTDIV1 = uint3(0); // divide by 1-7 + } + + // PLL_SYS Controls the PLL post dividers for the primary output (note: this PLL does not have a secondary output) the primary output is driven from VCO divided by postdiv1*postdiv2 + register PRIM_t PLL_SYS_PRIM at 0x4002800c; + + +/* Types and registers for PLL_USB */ + + // PLL_USB Control and Status GENERAL CONSTRAINTS: Reference clock frequency min=5MHz, max=800MHz Feedback divider min=16, max=320 VCO frequency min=750MHz, max=1600MHz + register PLL_SYS_CS_t PLL_USB_CS at 0x4002c000; + + // PLL_USB Controls the PLL power modes. + register PWR_t PLL_USB_PWR at 0x4002c004; + + // PLL_USB Feedback divisor (note: this PLL does not support fractional division) + register FBDIV_INT_t PLL_USB_FBDIV_INT at 0x4002c008; + + // PLL_USB Controls the PLL post dividers for the primary output (note: this PLL does not have a secondary output) the primary output is driven from VCO divided by postdiv1*postdiv2 + register PRIM_t PLL_USB_PRIM at 0x4002c00c; + + +/* Types and registers for UART0 */ + + type UARTDR_t { + DATA = uint8(0); // Receive (read) data character. Transmit (write) data character. + FE = false; // Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is associated with the character at the top of the FIFO. + PE = false; // Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. In FIFO mode, this error is associated with the character at the top of the FIFO. + BE = false; // Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity and stop bits). In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state), and the next valid start bit is received. + OE = false; // Overrun error. This bit is set to 1 if data is received and the receive FIFO is already full. This is cleared to 0 once there is an empty space in the FIFO and a new character can be written to it. + } + + // UART0 Data Register, UARTDR + register UARTDR_t UART0_UARTDR at 0x40034000; + + type UARTRSR_t { + FE = false; // Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + PE = false; // Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + BE = false; // Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity, and stop bits). This bit is cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state) and the next valid start bit is received. + OE = false; // Overrun error. This bit is set to 1 if data is received and the FIFO is already full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain valid because no more data is written when the FIFO is full, only the contents of the shift register are overwritten. The CPU must now read the data, to empty the FIFO. + } + + // UART0 Receive Status Register/Error Clear Register, UARTRSR/UARTECR + register UARTRSR_t UART0_UARTRSR at 0x40034004; + + type UARTFR_t { + CTS = false; // Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW. + DSR = false; // Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW. + DCD = false; // Data carrier detect. This bit is the complement of the UART data carrier detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. + BUSY = false; // UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit remains set until the complete byte, including all the stop bits, has been sent from the shift register. This bit is set as soon as the transmit FIFO becomes non-empty, regardless of whether the UART is enabled or not. + RXFE = false; // Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set when the receive FIFO is empty. + TXFF = false; // Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set when the transmit FIFO is full. + RXFF = false; // Receive FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is full. If the FIFO is enabled, the RXFF bit is set when the receive FIFO is full. + TXFE = false; // Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is set when the transmit holding register is empty. If the FIFO is enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if there is data in the transmit shift register. + RI = false; // Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW. + } + + // UART0 Flag Register, UARTFR + register UARTFR_t UART0_UARTFR at 0x40034018; + + type UARTILPR_t { + ILPDVSR = uint8(0); // 8-bit low-power divisor value. These bits are cleared to 0 at reset. + } + + // UART0 IrDA Low-Power Counter Register, UARTILPR + register UARTILPR_t UART0_UARTILPR at 0x40034020; + + type UARTIBRD_t { + BAUD_DIVINT = uint16(0); // The integer baud rate divisor. These bits are cleared to 0 on reset. + } + + // UART0 Integer Baud Rate Register, UARTIBRD + register UARTIBRD_t UART0_UARTIBRD at 0x40034024; + + type UARTFBRD_t { + BAUD_DIVFRAC = uint6(0); // The fractional baud rate divisor. These bits are cleared to 0 on reset. + } + + // UART0 Fractional Baud Rate Register, UARTFBRD + register UARTFBRD_t UART0_UARTFBRD at 0x40034028; + + type UARTLCR_H_t { + BRK = false; // Send break. If this bit is set to 1, a low-level is continually output on the UARTTXD output, after completing transmission of the current character. For the proper execution of the break command, the software must set this bit for at least two complete frames. For normal use, this bit must be cleared to 0. + PEN = false; // Parity enable: 0 = parity is disabled and no parity bit added to the data frame 1 = parity checking and generation is enabled. + EPS = false; // Even parity select. Controls the type of parity the UART uses during transmission and reception: 0 = odd parity. The UART generates or checks for an odd number of 1s in the data and parity bits. 1 = even parity. The UART generates or checks for an even number of 1s in the data and parity bits. This bit has no effect when the PEN bit disables parity checking and generation. + STP2 = false; // Two stop bits select. If this bit is set to 1, two stop bits are transmitted at the end of the frame. The receive logic does not check for two stop bits being received. + FEN = false; // Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled (FIFO mode). + WLEN = uint2(0); // Word length. These bits indicate the number of data bits transmitted or received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. + SPS = false; // Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then the parity bit is transmitted and checked as a 0. This bit has no effect when the PEN bit disables parity checking and generation. + } + + // UART0 Line Control Register, UARTLCR_H + register UARTLCR_H_t UART0_UARTLCR_H at 0x4003402c; + + type UARTCR_t { + UARTEN = false; // UART enable: 0 = UART is disabled. If the UART is disabled in the middle of transmission or reception, it completes the current character before stopping. 1 = the UART is enabled. Data transmission and reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. + SIREN = false; // SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD remains HIGH, in the marking state. Signal transitions on UARTRXD or modem status inputs have no effect. This bit has no effect if the UARTEN bit disables the UART. + SIRLP = false; // SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is cleared to 0, low-level bits are transmitted as an active high pulse with a width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are transmitted with a pulse width that is 3 times the period of the IrLPBaud16 input signal, regardless of the selected bit rate. Setting this bit uses less power, but might reduce transmission distances. + _res1 = uint4(0); // Reserved, 4 bits + LBE = false; // Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test register must be set to 1 to override the normal half-duplex SIR operation. This must be the requirement for accessing the test registers during normal operation, and SIRTEST must be cleared to 0 when loopback testing is finished. This feature reduces the amount of external coupling required during system test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path is fed through to the UARTRXD path. In either SIR mode or UART mode, when this bit is set, the modem outputs are also fed through to the modem inputs. This bit is cleared to 0 on reset, to disable loopback. + TXE = false; // Transmit enable. If this bit is set to 1, the transmit section of the UART is enabled. Data transmission occurs for either UART signals, or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of transmission, it completes the current character before stopping. + RXE = false; // Receive enable. If this bit is set to 1, the receive section of the UART is enabled. Data reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of reception, it completes the current character before stopping. + DTR = false; // Data transmit ready. This bit is the complement of the UART data transmit ready, nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then nUARTDTR is LOW. + RTS = false; // Request to send. This bit is the complement of the UART request to send, nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then nUARTRTS is LOW. + OUT1 = false; // This bit is the complement of the UART Out1 (nUARTOut1) modem status output. That is, when the bit is programmed to a 1 the output is 0. For DTE this can be used as Data Carrier Detect (DCD). + OUT2 = false; // This bit is the complement of the UART Out2 (nUARTOut2) modem status output. That is, when the bit is programmed to a 1, the output is 0. For DTE this can be used as Ring Indicator (RI). + RTSEN = false; // RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow control is enabled. Data is only requested when there is space in the receive FIFO for it to be received. + CTSEN = false; // CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow control is enabled. Data is only transmitted when the nUARTCTS signal is asserted. + } + + // UART0 Control Register, UARTCR + register UARTCR_t UART0_UARTCR at 0x40034030; + + type UARTIFLS_t { + TXIFLSEL = uint3(0); // Transmit interrupt FIFO level select. The trigger points for the transmit interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 full b101-b111 = reserved. + RXIFLSEL = uint3(0); // Receive interrupt FIFO level select. The trigger points for the receive interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 full b101-b111 = reserved. + } + + // UART0 Interrupt FIFO Level Select Register, UARTIFLS + register UARTIFLS_t UART0_UARTIFLS at 0x40034034; + + type UARTIMSC_t { + RIMIM = false; // nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write of 0 clears the mask. + CTSMIM = false; // nUARTCTS modem interrupt mask. A read returns the current mask for the UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is set. A write of 0 clears the mask. + DCDMIM = false; // nUARTDCD modem interrupt mask. A read returns the current mask for the UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is set. A write of 0 clears the mask. + DSRMIM = false; // nUARTDSR modem interrupt mask. A read returns the current mask for the UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is set. A write of 0 clears the mask. + RXIM = false; // Receive interrupt mask. A read returns the current mask for the UARTRXINTR interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write of 0 clears the mask. + TXIM = false; // Transmit interrupt mask. A read returns the current mask for the UARTTXINTR interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write of 0 clears the mask. + RTIM = false; // Receive timeout interrupt mask. A read returns the current mask for the UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is set. A write of 0 clears the mask. + FEIM = false; // Framing error interrupt mask. A read returns the current mask for the UARTFEINTR interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write of 0 clears the mask. + PEIM = false; // Parity error interrupt mask. A read returns the current mask for the UARTPEINTR interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write of 0 clears the mask. + BEIM = false; // Break error interrupt mask. A read returns the current mask for the UARTBEINTR interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write of 0 clears the mask. + OEIM = false; // Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write of 0 clears the mask. + } + + // UART0 Interrupt Mask Set/Clear Register, UARTIMSC + register UARTIMSC_t UART0_UARTIMSC at 0x40034038; + + type UARTRIS_t { + RIRMIS = false; // nUARTRI modem interrupt status. Returns the raw interrupt state of the UARTRIINTR interrupt. + CTSRMIS = false; // nUARTCTS modem interrupt status. Returns the raw interrupt state of the UARTCTSINTR interrupt. + DCDRMIS = false; // nUARTDCD modem interrupt status. Returns the raw interrupt state of the UARTDCDINTR interrupt. + DSRRMIS = false; // nUARTDSR modem interrupt status. Returns the raw interrupt state of the UARTDSRINTR interrupt. + RXRIS = false; // Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR interrupt. + TXRIS = false; // Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR interrupt. + RTRIS = false; // Receive timeout interrupt status. Returns the raw interrupt state of the UARTRTINTR interrupt. a + FERIS = false; // Framing error interrupt status. Returns the raw interrupt state of the UARTFEINTR interrupt. + PERIS = false; // Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR interrupt. + BERIS = false; // Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR interrupt. + OERIS = false; // Overrun error interrupt status. Returns the raw interrupt state of the UARTOEINTR interrupt. + } + + // UART0 Raw Interrupt Status Register, UARTRIS + register UARTRIS_t UART0_UARTRIS at 0x4003403c; + + type UARTMIS_t { + RIMMIS = false; // nUARTRI modem masked interrupt status. Returns the masked interrupt state of the UARTRIINTR interrupt. + CTSMMIS = false; // nUARTCTS modem masked interrupt status. Returns the masked interrupt state of the UARTCTSINTR interrupt. + DCDMMIS = false; // nUARTDCD modem masked interrupt status. Returns the masked interrupt state of the UARTDCDINTR interrupt. + DSRMMIS = false; // nUARTDSR modem masked interrupt status. Returns the masked interrupt state of the UARTDSRINTR interrupt. + RXMIS = false; // Receive masked interrupt status. Returns the masked interrupt state of the UARTRXINTR interrupt. + TXMIS = false; // Transmit masked interrupt status. Returns the masked interrupt state of the UARTTXINTR interrupt. + RTMIS = false; // Receive timeout masked interrupt status. Returns the masked interrupt state of the UARTRTINTR interrupt. + FEMIS = false; // Framing error masked interrupt status. Returns the masked interrupt state of the UARTFEINTR interrupt. + PEMIS = false; // Parity error masked interrupt status. Returns the masked interrupt state of the UARTPEINTR interrupt. + BEMIS = false; // Break error masked interrupt status. Returns the masked interrupt state of the UARTBEINTR interrupt. + OEMIS = false; // Overrun error masked interrupt status. Returns the masked interrupt state of the UARTOEINTR interrupt. + } + + // UART0 Masked Interrupt Status Register, UARTMIS + register UARTMIS_t UART0_UARTMIS at 0x40034040; + + type UARTICR_t { + RIMIC = false; // nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. + CTSMIC = false; // nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt. + DCDMIC = false; // nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt. + DSRMIC = false; // nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt. + RXIC = false; // Receive interrupt clear. Clears the UARTRXINTR interrupt. + TXIC = false; // Transmit interrupt clear. Clears the UARTTXINTR interrupt. + RTIC = false; // Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. + FEIC = false; // Framing error interrupt clear. Clears the UARTFEINTR interrupt. + PEIC = false; // Parity error interrupt clear. Clears the UARTPEINTR interrupt. + BEIC = false; // Break error interrupt clear. Clears the UARTBEINTR interrupt. + OEIC = false; // Overrun error interrupt clear. Clears the UARTOEINTR interrupt. + } + + // UART0 Interrupt Clear Register, UARTICR + register UARTICR_t UART0_UARTICR at 0x40034044; + + type UARTDMACR_t { + RXDMAE = false; // Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is enabled. + TXDMAE = false; // Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + DMAONERR = false; // DMA on error. If this bit is set to 1, the DMA receive request outputs, UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is asserted. + } + + // UART0 DMA Control Register, UARTDMACR + register UARTDMACR_t UART0_UARTDMACR at 0x40034048; + + type UARTPERIPHID0_t { + PARTNUMBER0 = uint8(0); // These bits read back as 0x11 + } + + // UART0 UARTPeriphID0 Register + register UARTPERIPHID0_t UART0_UARTPERIPHID0 at 0x40034fe0; + + type UARTPERIPHID1_t { + PARTNUMBER1 = uint4(0); // These bits read back as 0x0 + DESIGNER0 = uint4(0); // These bits read back as 0x1 + } + + // UART0 UARTPeriphID1 Register + register UARTPERIPHID1_t UART0_UARTPERIPHID1 at 0x40034fe4; + + type UARTPERIPHID2_t { + DESIGNER1 = uint4(0); // These bits read back as 0x4 + REVISION = uint4(0); // This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 0x2 r1p5 0x3 + } + + // UART0 UARTPeriphID2 Register + register UARTPERIPHID2_t UART0_UARTPERIPHID2 at 0x40034fe8; + + type UARTPERIPHID3_t { + CONFIGURATION = uint8(0); // These bits read back as 0x00 + } + + // UART0 UARTPeriphID3 Register + register UARTPERIPHID3_t UART0_UARTPERIPHID3 at 0x40034fec; + + type UARTPCELLID0_t { + UARTPCELLID0 = uint8(0); // These bits read back as 0x0D + } + + // UART0 UARTPCellID0 Register + register UARTPCELLID0_t UART0_UARTPCELLID0 at 0x40034ff0; + + type UARTPCELLID1_t { + UARTPCELLID1 = uint8(0); // These bits read back as 0xF0 + } + + // UART0 UARTPCellID1 Register + register UARTPCELLID1_t UART0_UARTPCELLID1 at 0x40034ff4; + + type UARTPCELLID2_t { + UARTPCELLID2 = uint8(0); // These bits read back as 0x05 + } + + // UART0 UARTPCellID2 Register + register UARTPCELLID2_t UART0_UARTPCELLID2 at 0x40034ff8; + + type UARTPCELLID3_t { + UARTPCELLID3 = uint8(0); // These bits read back as 0xB1 + } + + // UART0 UARTPCellID3 Register + register UARTPCELLID3_t UART0_UARTPCELLID3 at 0x40034ffc; + + +/* Types and registers for UART1 */ + + // UART1 Data Register, UARTDR + register UARTDR_t UART1_UARTDR at 0x40038000; + + // UART1 Receive Status Register/Error Clear Register, UARTRSR/UARTECR + register UARTRSR_t UART1_UARTRSR at 0x40038004; + + // UART1 Flag Register, UARTFR + register UARTFR_t UART1_UARTFR at 0x40038018; + + // UART1 IrDA Low-Power Counter Register, UARTILPR + register UARTILPR_t UART1_UARTILPR at 0x40038020; + + // UART1 Integer Baud Rate Register, UARTIBRD + register UARTIBRD_t UART1_UARTIBRD at 0x40038024; + + // UART1 Fractional Baud Rate Register, UARTFBRD + register UARTFBRD_t UART1_UARTFBRD at 0x40038028; + + // UART1 Line Control Register, UARTLCR_H + register UARTLCR_H_t UART1_UARTLCR_H at 0x4003802c; + + // UART1 Control Register, UARTCR + register UARTCR_t UART1_UARTCR at 0x40038030; + + // UART1 Interrupt FIFO Level Select Register, UARTIFLS + register UARTIFLS_t UART1_UARTIFLS at 0x40038034; + + // UART1 Interrupt Mask Set/Clear Register, UARTIMSC + register UARTIMSC_t UART1_UARTIMSC at 0x40038038; + + // UART1 Raw Interrupt Status Register, UARTRIS + register UARTRIS_t UART1_UARTRIS at 0x4003803c; + + // UART1 Masked Interrupt Status Register, UARTMIS + register UARTMIS_t UART1_UARTMIS at 0x40038040; + + // UART1 Interrupt Clear Register, UARTICR + register UARTICR_t UART1_UARTICR at 0x40038044; + + // UART1 DMA Control Register, UARTDMACR + register UARTDMACR_t UART1_UARTDMACR at 0x40038048; + + // UART1 UARTPeriphID0 Register + register UARTPERIPHID0_t UART1_UARTPERIPHID0 at 0x40038fe0; + + // UART1 UARTPeriphID1 Register + register UARTPERIPHID1_t UART1_UARTPERIPHID1 at 0x40038fe4; + + // UART1 UARTPeriphID2 Register + register UARTPERIPHID2_t UART1_UARTPERIPHID2 at 0x40038fe8; + + // UART1 UARTPeriphID3 Register + register UARTPERIPHID3_t UART1_UARTPERIPHID3 at 0x40038fec; + + // UART1 UARTPCellID0 Register + register UARTPCELLID0_t UART1_UARTPCELLID0 at 0x40038ff0; + + // UART1 UARTPCellID1 Register + register UARTPCELLID1_t UART1_UARTPCELLID1 at 0x40038ff4; + + // UART1 UARTPCellID2 Register + register UARTPCELLID2_t UART1_UARTPCELLID2 at 0x40038ff8; + + // UART1 UARTPCellID3 Register + register UARTPCELLID3_t UART1_UARTPCELLID3 at 0x40038ffc; + + +/* Types and registers for ROSC */ + + type ROSC_CTRL_t { + FREQ_RANGE = uint12(0); // Controls the number of delay stages in the ROSC ring LOW uses stages 0 to 7 MEDIUM uses stages 2 to 7 HIGH uses stages 4 to 7 TOOHIGH uses stages 6 to 7 and should not be used because its frequency exceeds design specifications The clock output will not glitch when changing the range up one step at a time The clock output will glitch when changing the range down Note: the values here are gray coded which is why HIGH comes before TOOHIGH + ENABLE = uint12(0); // On power-up this field is initialised to ENABLE The system clock must be switched to another source before setting this field to DISABLE otherwise the chip will lock up The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + } + + // Ring Oscillator control + register ROSC_CTRL_t ROSC_CTRL at 0x40060000; + + type FREQA_t { + DS0 = uint3(0); // Stage 0 drive strength + _res1 = false; // Reserved, 1 bits + DS1 = uint3(0); // Stage 1 drive strength + _res2 = false; // Reserved, 1 bits + DS2 = uint3(0); // Stage 2 drive strength + _res3 = false; // Reserved, 1 bits + DS3 = uint3(0); // Stage 3 drive strength + _res4 = false; // Reserved, 1 bits + PASSWD = uint16(0); // Set to 0x9696 to apply the settings Any other value in this field will set all drive strengths to 0 + } + + // The FREQA & FREQB registers control the frequency by controlling the drive strength of each stage The drive strength has 4 levels determined by the number of bits set Increasing the number of bits set increases the drive strength and increases the oscillation frequency 0 bits set is the default drive strength 1 bit set doubles the drive strength 2 bits set triples drive strength 3 bits set quadruples drive strength + register FREQA_t FREQA at 0x40060004; + + type FREQB_t { + DS4 = uint3(0); // Stage 4 drive strength + _res1 = false; // Reserved, 1 bits + DS5 = uint3(0); // Stage 5 drive strength + _res2 = false; // Reserved, 1 bits + DS6 = uint3(0); // Stage 6 drive strength + _res3 = false; // Reserved, 1 bits + DS7 = uint3(0); // Stage 7 drive strength + _res4 = false; // Reserved, 1 bits + PASSWD = uint16(0); // Set to 0x9696 to apply the settings Any other value in this field will set all drive strengths to 0 + } + + // For a detailed description see freqa register + register FREQB_t FREQB at 0x40060008; + + type ROSC_DORMANT_t { + DORMANT = uint32(0); // This is used to save power by pausing the ROSC On power-up this field is initialised to WAKE An invalid write will also select WAKE Warning: setup the irq before selecting dormant mode + } + + // Ring Oscillator pause control + register ROSC_DORMANT_t ROSC_DORMANT at 0x4006000c; + + type ROSC_DIV_t { + DIV = uint12(0); // set to 0xaa0 + div where div = 0 divides by 32 div = 1-31 divides by div any other value sets div=31 this register resets to div=16 + } + + // Controls the output divider + register ROSC_DIV_t ROSC_DIV at 0x40060010; + + type PHASE_t { + SHIFT = uint2(0); // phase shift the phase-shifted output by SHIFT input clocks this can be changed on-the-fly must be set to 0 before setting div=1 + FLIP = false; // invert the phase-shifted output this is ignored when div=1 + ENABLE = false; // enable the phase-shifted output this can be changed on-the-fly + PASSWD = uint8(0); // set to 0xaa any other value enables the output with shift=0 + } + + // Controls the phase shifted output + register PHASE_t PHASE at 0x40060014; + + type ROSC_STATUS_t { + _res1 = uint8(0); // Reserved, 12 bits + _res2 = uint4(0); // + ENABLED = false; // Oscillator is enabled but not necessarily running and stable this resets to 0 but transitions to 1 during chip startup + _res3 = uint3(0); // Reserved, 3 bits + DIV_RUNNING = false; // post-divider is running this resets to 0 but transitions to 1 during chip startup + _res4 = uint7(0); // Reserved, 7 bits + BADWRITE = false; // An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or FREQA or FREQB or DIV or PHASE or DORMANT + _res5 = uint6(0); // Reserved, 6 bits + STABLE = false; // Oscillator is running and stable + } + + // Ring Oscillator Status + register ROSC_STATUS_t ROSC_STATUS at 0x40060018; + + type RANDOMBIT_t { + RANDOMBIT = false; // + } + + // This just reads the state of the oscillator output so randomness is compromised if the ring oscillator is stopped or run at a harmonic of the bus frequency + register RANDOMBIT_t RANDOMBIT at 0x4006001c; + + type ROSC_COUNT_t { + COUNT = uint8(0); // + } + + // A down counter running at the ROSC frequency which counts to zero and stops. To start the counter write a non-zero value. Can be used for short software pauses when setting up time sensitive hardware. + register ROSC_COUNT_t ROSC_COUNT at 0x40060020; + + +/* Types and registers for WATCHDOG */ + + type WATCHDOG_CTRL_t { + TIME = uint24(0); // Indicates the number of ticks / 2 (see errata RP2040-E1) before a watchdog reset will be triggered + PAUSE_JTAG = false; // Pause the watchdog timer when JTAG is accessing the bus fabric + PAUSE_DBG0 = false; // Pause the watchdog timer when processor 0 is in debug mode + PAUSE_DBG1 = false; // Pause the watchdog timer when processor 1 is in debug mode + _res1 = uint3(0); // Reserved, 3 bits + ENABLE = false; // When not enabled the watchdog timer is paused + TRIGGER = false; // Trigger a watchdog reset + } + + // Watchdog control The rst_wdsel register determines which subsystems are reset when the watchdog is triggered. The watchdog can be triggered in software. + register WATCHDOG_CTRL_t WATCHDOG_CTRL at 0x40058000; + + type LOAD_t { + LOAD = uint24(0); // + } + + // Load the watchdog timer. The maximum setting is 0xffffff which corresponds to 0xffffff / 2 ticks before triggering a watchdog reset (see errata RP2040-E1). + register LOAD_t LOAD at 0x40058004; + + type REASON_t { + TIMER = false; // + FORCE = false; // + } + + // Logs the reason for the last reset. Both bits are zero for the case of a hardware reset. + register REASON_t REASON at 0x40058008; + + type SCRATCH0_t { + SCRATCH0 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH0_t SCRATCH0 at 0x4005800c; + + type SCRATCH1_t { + SCRATCH1 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH1_t SCRATCH1 at 0x40058010; + + type SCRATCH2_t { + SCRATCH2 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH2_t SCRATCH2 at 0x40058014; + + type SCRATCH3_t { + SCRATCH3 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH3_t SCRATCH3 at 0x40058018; + + type SCRATCH4_t { + SCRATCH4 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH4_t SCRATCH4 at 0x4005801c; + + type SCRATCH5_t { + SCRATCH5 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH5_t SCRATCH5 at 0x40058020; + + type SCRATCH6_t { + SCRATCH6 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH6_t SCRATCH6 at 0x40058024; + + type SCRATCH7_t { + SCRATCH7 = uint32(0); // + } + + // Scratch register. Information persists through soft reset of the chip. + register SCRATCH7_t SCRATCH7 at 0x40058028; + + type TICK_t { + CYCLES = uint9(0); // Total number of clk_tick cycles before the next tick. + ENABLE = false; // start / stop tick generation + RUNNING = false; // Is the tick generator running? + COUNT = uint9(0); // Count down timer: the remaining number clk_tick cycles before the next tick is generated. + } + + // Controls the tick generator + register TICK_t TICK at 0x4005802c; + + +/* Types and registers for DMA + DMA with separate read and write masters + */ + + type CH0_READ_ADDR_t { + CH0_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 0 Read Address pointer + register CH0_READ_ADDR_t CH0_READ_ADDR at 0x50000000; + + type CH0_WRITE_ADDR_t { + CH0_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 0 Write Address pointer + register CH0_WRITE_ADDR_t CH0_WRITE_ADDR at 0x50000004; + + type CH0_TRANS_COUNT_t { + CH0_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 0 Transfer Count + register CH0_TRANS_COUNT_t CH0_TRANS_COUNT at 0x50000008; + + type CH0_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 0 Control and Status + register CH0_CTRL_TRIG_t CH0_CTRL_TRIG at 0x5000000c; + + type CH0_AL1_CTRL_t { + CH0_AL1_CTRL = uint32(0); // + } + + // Alias for channel 0 CTRL register + register CH0_AL1_CTRL_t CH0_AL1_CTRL at 0x50000010; + + type CH0_AL1_READ_ADDR_t { + CH0_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 0 READ_ADDR register + register CH0_AL1_READ_ADDR_t CH0_AL1_READ_ADDR at 0x50000014; + + type CH0_AL1_WRITE_ADDR_t { + CH0_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 0 WRITE_ADDR register + register CH0_AL1_WRITE_ADDR_t CH0_AL1_WRITE_ADDR at 0x50000018; + + type CH0_AL1_TRANS_COUNT_TRIG_t { + CH0_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 0 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH0_AL1_TRANS_COUNT_TRIG_t CH0_AL1_TRANS_COUNT_TRIG at 0x5000001c; + + type CH0_AL2_CTRL_t { + CH0_AL2_CTRL = uint32(0); // + } + + // Alias for channel 0 CTRL register + register CH0_AL2_CTRL_t CH0_AL2_CTRL at 0x50000020; + + type CH0_AL2_TRANS_COUNT_t { + CH0_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 0 TRANS_COUNT register + register CH0_AL2_TRANS_COUNT_t CH0_AL2_TRANS_COUNT at 0x50000024; + + type CH0_AL2_READ_ADDR_t { + CH0_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 0 READ_ADDR register + register CH0_AL2_READ_ADDR_t CH0_AL2_READ_ADDR at 0x50000028; + + type CH0_AL2_WRITE_ADDR_TRIG_t { + CH0_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 0 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH0_AL2_WRITE_ADDR_TRIG_t CH0_AL2_WRITE_ADDR_TRIG at 0x5000002c; + + type CH0_AL3_CTRL_t { + CH0_AL3_CTRL = uint32(0); // + } + + // Alias for channel 0 CTRL register + register CH0_AL3_CTRL_t CH0_AL3_CTRL at 0x50000030; + + type CH0_AL3_WRITE_ADDR_t { + CH0_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 0 WRITE_ADDR register + register CH0_AL3_WRITE_ADDR_t CH0_AL3_WRITE_ADDR at 0x50000034; + + type CH0_AL3_TRANS_COUNT_t { + CH0_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 0 TRANS_COUNT register + register CH0_AL3_TRANS_COUNT_t CH0_AL3_TRANS_COUNT at 0x50000038; + + type CH0_AL3_READ_ADDR_TRIG_t { + CH0_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 0 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH0_AL3_READ_ADDR_TRIG_t CH0_AL3_READ_ADDR_TRIG at 0x5000003c; + + type CH1_READ_ADDR_t { + CH1_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 1 Read Address pointer + register CH1_READ_ADDR_t CH1_READ_ADDR at 0x50000040; + + type CH1_WRITE_ADDR_t { + CH1_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 1 Write Address pointer + register CH1_WRITE_ADDR_t CH1_WRITE_ADDR at 0x50000044; + + type CH1_TRANS_COUNT_t { + CH1_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 1 Transfer Count + register CH1_TRANS_COUNT_t CH1_TRANS_COUNT at 0x50000048; + + type CH1_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 1 Control and Status + register CH1_CTRL_TRIG_t CH1_CTRL_TRIG at 0x5000004c; + + type CH1_AL1_CTRL_t { + CH1_AL1_CTRL = uint32(0); // + } + + // Alias for channel 1 CTRL register + register CH1_AL1_CTRL_t CH1_AL1_CTRL at 0x50000050; + + type CH1_AL1_READ_ADDR_t { + CH1_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 1 READ_ADDR register + register CH1_AL1_READ_ADDR_t CH1_AL1_READ_ADDR at 0x50000054; + + type CH1_AL1_WRITE_ADDR_t { + CH1_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 1 WRITE_ADDR register + register CH1_AL1_WRITE_ADDR_t CH1_AL1_WRITE_ADDR at 0x50000058; + + type CH1_AL1_TRANS_COUNT_TRIG_t { + CH1_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 1 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH1_AL1_TRANS_COUNT_TRIG_t CH1_AL1_TRANS_COUNT_TRIG at 0x5000005c; + + type CH1_AL2_CTRL_t { + CH1_AL2_CTRL = uint32(0); // + } + + // Alias for channel 1 CTRL register + register CH1_AL2_CTRL_t CH1_AL2_CTRL at 0x50000060; + + type CH1_AL2_TRANS_COUNT_t { + CH1_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 1 TRANS_COUNT register + register CH1_AL2_TRANS_COUNT_t CH1_AL2_TRANS_COUNT at 0x50000064; + + type CH1_AL2_READ_ADDR_t { + CH1_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 1 READ_ADDR register + register CH1_AL2_READ_ADDR_t CH1_AL2_READ_ADDR at 0x50000068; + + type CH1_AL2_WRITE_ADDR_TRIG_t { + CH1_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 1 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH1_AL2_WRITE_ADDR_TRIG_t CH1_AL2_WRITE_ADDR_TRIG at 0x5000006c; + + type CH1_AL3_CTRL_t { + CH1_AL3_CTRL = uint32(0); // + } + + // Alias for channel 1 CTRL register + register CH1_AL3_CTRL_t CH1_AL3_CTRL at 0x50000070; + + type CH1_AL3_WRITE_ADDR_t { + CH1_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 1 WRITE_ADDR register + register CH1_AL3_WRITE_ADDR_t CH1_AL3_WRITE_ADDR at 0x50000074; + + type CH1_AL3_TRANS_COUNT_t { + CH1_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 1 TRANS_COUNT register + register CH1_AL3_TRANS_COUNT_t CH1_AL3_TRANS_COUNT at 0x50000078; + + type CH1_AL3_READ_ADDR_TRIG_t { + CH1_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 1 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH1_AL3_READ_ADDR_TRIG_t CH1_AL3_READ_ADDR_TRIG at 0x5000007c; + + type CH2_READ_ADDR_t { + CH2_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 2 Read Address pointer + register CH2_READ_ADDR_t CH2_READ_ADDR at 0x50000080; + + type CH2_WRITE_ADDR_t { + CH2_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 2 Write Address pointer + register CH2_WRITE_ADDR_t CH2_WRITE_ADDR at 0x50000084; + + type CH2_TRANS_COUNT_t { + CH2_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 2 Transfer Count + register CH2_TRANS_COUNT_t CH2_TRANS_COUNT at 0x50000088; + + type CH2_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 2 Control and Status + register CH2_CTRL_TRIG_t CH2_CTRL_TRIG at 0x5000008c; + + type CH2_AL1_CTRL_t { + CH2_AL1_CTRL = uint32(0); // + } + + // Alias for channel 2 CTRL register + register CH2_AL1_CTRL_t CH2_AL1_CTRL at 0x50000090; + + type CH2_AL1_READ_ADDR_t { + CH2_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 2 READ_ADDR register + register CH2_AL1_READ_ADDR_t CH2_AL1_READ_ADDR at 0x50000094; + + type CH2_AL1_WRITE_ADDR_t { + CH2_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 2 WRITE_ADDR register + register CH2_AL1_WRITE_ADDR_t CH2_AL1_WRITE_ADDR at 0x50000098; + + type CH2_AL1_TRANS_COUNT_TRIG_t { + CH2_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 2 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH2_AL1_TRANS_COUNT_TRIG_t CH2_AL1_TRANS_COUNT_TRIG at 0x5000009c; + + type CH2_AL2_CTRL_t { + CH2_AL2_CTRL = uint32(0); // + } + + // Alias for channel 2 CTRL register + register CH2_AL2_CTRL_t CH2_AL2_CTRL at 0x500000a0; + + type CH2_AL2_TRANS_COUNT_t { + CH2_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 2 TRANS_COUNT register + register CH2_AL2_TRANS_COUNT_t CH2_AL2_TRANS_COUNT at 0x500000a4; + + type CH2_AL2_READ_ADDR_t { + CH2_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 2 READ_ADDR register + register CH2_AL2_READ_ADDR_t CH2_AL2_READ_ADDR at 0x500000a8; + + type CH2_AL2_WRITE_ADDR_TRIG_t { + CH2_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 2 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH2_AL2_WRITE_ADDR_TRIG_t CH2_AL2_WRITE_ADDR_TRIG at 0x500000ac; + + type CH2_AL3_CTRL_t { + CH2_AL3_CTRL = uint32(0); // + } + + // Alias for channel 2 CTRL register + register CH2_AL3_CTRL_t CH2_AL3_CTRL at 0x500000b0; + + type CH2_AL3_WRITE_ADDR_t { + CH2_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 2 WRITE_ADDR register + register CH2_AL3_WRITE_ADDR_t CH2_AL3_WRITE_ADDR at 0x500000b4; + + type CH2_AL3_TRANS_COUNT_t { + CH2_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 2 TRANS_COUNT register + register CH2_AL3_TRANS_COUNT_t CH2_AL3_TRANS_COUNT at 0x500000b8; + + type CH2_AL3_READ_ADDR_TRIG_t { + CH2_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 2 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH2_AL3_READ_ADDR_TRIG_t CH2_AL3_READ_ADDR_TRIG at 0x500000bc; + + type CH3_READ_ADDR_t { + CH3_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 3 Read Address pointer + register CH3_READ_ADDR_t CH3_READ_ADDR at 0x500000c0; + + type CH3_WRITE_ADDR_t { + CH3_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 3 Write Address pointer + register CH3_WRITE_ADDR_t CH3_WRITE_ADDR at 0x500000c4; + + type CH3_TRANS_COUNT_t { + CH3_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 3 Transfer Count + register CH3_TRANS_COUNT_t CH3_TRANS_COUNT at 0x500000c8; + + type CH3_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 3 Control and Status + register CH3_CTRL_TRIG_t CH3_CTRL_TRIG at 0x500000cc; + + type CH3_AL1_CTRL_t { + CH3_AL1_CTRL = uint32(0); // + } + + // Alias for channel 3 CTRL register + register CH3_AL1_CTRL_t CH3_AL1_CTRL at 0x500000d0; + + type CH3_AL1_READ_ADDR_t { + CH3_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 3 READ_ADDR register + register CH3_AL1_READ_ADDR_t CH3_AL1_READ_ADDR at 0x500000d4; + + type CH3_AL1_WRITE_ADDR_t { + CH3_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 3 WRITE_ADDR register + register CH3_AL1_WRITE_ADDR_t CH3_AL1_WRITE_ADDR at 0x500000d8; + + type CH3_AL1_TRANS_COUNT_TRIG_t { + CH3_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 3 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH3_AL1_TRANS_COUNT_TRIG_t CH3_AL1_TRANS_COUNT_TRIG at 0x500000dc; + + type CH3_AL2_CTRL_t { + CH3_AL2_CTRL = uint32(0); // + } + + // Alias for channel 3 CTRL register + register CH3_AL2_CTRL_t CH3_AL2_CTRL at 0x500000e0; + + type CH3_AL2_TRANS_COUNT_t { + CH3_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 3 TRANS_COUNT register + register CH3_AL2_TRANS_COUNT_t CH3_AL2_TRANS_COUNT at 0x500000e4; + + type CH3_AL2_READ_ADDR_t { + CH3_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 3 READ_ADDR register + register CH3_AL2_READ_ADDR_t CH3_AL2_READ_ADDR at 0x500000e8; + + type CH3_AL2_WRITE_ADDR_TRIG_t { + CH3_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 3 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH3_AL2_WRITE_ADDR_TRIG_t CH3_AL2_WRITE_ADDR_TRIG at 0x500000ec; + + type CH3_AL3_CTRL_t { + CH3_AL3_CTRL = uint32(0); // + } + + // Alias for channel 3 CTRL register + register CH3_AL3_CTRL_t CH3_AL3_CTRL at 0x500000f0; + + type CH3_AL3_WRITE_ADDR_t { + CH3_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 3 WRITE_ADDR register + register CH3_AL3_WRITE_ADDR_t CH3_AL3_WRITE_ADDR at 0x500000f4; + + type CH3_AL3_TRANS_COUNT_t { + CH3_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 3 TRANS_COUNT register + register CH3_AL3_TRANS_COUNT_t CH3_AL3_TRANS_COUNT at 0x500000f8; + + type CH3_AL3_READ_ADDR_TRIG_t { + CH3_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 3 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH3_AL3_READ_ADDR_TRIG_t CH3_AL3_READ_ADDR_TRIG at 0x500000fc; + + type CH4_READ_ADDR_t { + CH4_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 4 Read Address pointer + register CH4_READ_ADDR_t CH4_READ_ADDR at 0x50000100; + + type CH4_WRITE_ADDR_t { + CH4_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 4 Write Address pointer + register CH4_WRITE_ADDR_t CH4_WRITE_ADDR at 0x50000104; + + type CH4_TRANS_COUNT_t { + CH4_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 4 Transfer Count + register CH4_TRANS_COUNT_t CH4_TRANS_COUNT at 0x50000108; + + type CH4_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 4 Control and Status + register CH4_CTRL_TRIG_t CH4_CTRL_TRIG at 0x5000010c; + + type CH4_AL1_CTRL_t { + CH4_AL1_CTRL = uint32(0); // + } + + // Alias for channel 4 CTRL register + register CH4_AL1_CTRL_t CH4_AL1_CTRL at 0x50000110; + + type CH4_AL1_READ_ADDR_t { + CH4_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 4 READ_ADDR register + register CH4_AL1_READ_ADDR_t CH4_AL1_READ_ADDR at 0x50000114; + + type CH4_AL1_WRITE_ADDR_t { + CH4_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 4 WRITE_ADDR register + register CH4_AL1_WRITE_ADDR_t CH4_AL1_WRITE_ADDR at 0x50000118; + + type CH4_AL1_TRANS_COUNT_TRIG_t { + CH4_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 4 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH4_AL1_TRANS_COUNT_TRIG_t CH4_AL1_TRANS_COUNT_TRIG at 0x5000011c; + + type CH4_AL2_CTRL_t { + CH4_AL2_CTRL = uint32(0); // + } + + // Alias for channel 4 CTRL register + register CH4_AL2_CTRL_t CH4_AL2_CTRL at 0x50000120; + + type CH4_AL2_TRANS_COUNT_t { + CH4_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 4 TRANS_COUNT register + register CH4_AL2_TRANS_COUNT_t CH4_AL2_TRANS_COUNT at 0x50000124; + + type CH4_AL2_READ_ADDR_t { + CH4_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 4 READ_ADDR register + register CH4_AL2_READ_ADDR_t CH4_AL2_READ_ADDR at 0x50000128; + + type CH4_AL2_WRITE_ADDR_TRIG_t { + CH4_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 4 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH4_AL2_WRITE_ADDR_TRIG_t CH4_AL2_WRITE_ADDR_TRIG at 0x5000012c; + + type CH4_AL3_CTRL_t { + CH4_AL3_CTRL = uint32(0); // + } + + // Alias for channel 4 CTRL register + register CH4_AL3_CTRL_t CH4_AL3_CTRL at 0x50000130; + + type CH4_AL3_WRITE_ADDR_t { + CH4_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 4 WRITE_ADDR register + register CH4_AL3_WRITE_ADDR_t CH4_AL3_WRITE_ADDR at 0x50000134; + + type CH4_AL3_TRANS_COUNT_t { + CH4_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 4 TRANS_COUNT register + register CH4_AL3_TRANS_COUNT_t CH4_AL3_TRANS_COUNT at 0x50000138; + + type CH4_AL3_READ_ADDR_TRIG_t { + CH4_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 4 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH4_AL3_READ_ADDR_TRIG_t CH4_AL3_READ_ADDR_TRIG at 0x5000013c; + + type CH5_READ_ADDR_t { + CH5_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 5 Read Address pointer + register CH5_READ_ADDR_t CH5_READ_ADDR at 0x50000140; + + type CH5_WRITE_ADDR_t { + CH5_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 5 Write Address pointer + register CH5_WRITE_ADDR_t CH5_WRITE_ADDR at 0x50000144; + + type CH5_TRANS_COUNT_t { + CH5_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 5 Transfer Count + register CH5_TRANS_COUNT_t CH5_TRANS_COUNT at 0x50000148; + + type CH5_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 5 Control and Status + register CH5_CTRL_TRIG_t CH5_CTRL_TRIG at 0x5000014c; + + type CH5_AL1_CTRL_t { + CH5_AL1_CTRL = uint32(0); // + } + + // Alias for channel 5 CTRL register + register CH5_AL1_CTRL_t CH5_AL1_CTRL at 0x50000150; + + type CH5_AL1_READ_ADDR_t { + CH5_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 5 READ_ADDR register + register CH5_AL1_READ_ADDR_t CH5_AL1_READ_ADDR at 0x50000154; + + type CH5_AL1_WRITE_ADDR_t { + CH5_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 5 WRITE_ADDR register + register CH5_AL1_WRITE_ADDR_t CH5_AL1_WRITE_ADDR at 0x50000158; + + type CH5_AL1_TRANS_COUNT_TRIG_t { + CH5_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 5 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH5_AL1_TRANS_COUNT_TRIG_t CH5_AL1_TRANS_COUNT_TRIG at 0x5000015c; + + type CH5_AL2_CTRL_t { + CH5_AL2_CTRL = uint32(0); // + } + + // Alias for channel 5 CTRL register + register CH5_AL2_CTRL_t CH5_AL2_CTRL at 0x50000160; + + type CH5_AL2_TRANS_COUNT_t { + CH5_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 5 TRANS_COUNT register + register CH5_AL2_TRANS_COUNT_t CH5_AL2_TRANS_COUNT at 0x50000164; + + type CH5_AL2_READ_ADDR_t { + CH5_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 5 READ_ADDR register + register CH5_AL2_READ_ADDR_t CH5_AL2_READ_ADDR at 0x50000168; + + type CH5_AL2_WRITE_ADDR_TRIG_t { + CH5_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 5 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH5_AL2_WRITE_ADDR_TRIG_t CH5_AL2_WRITE_ADDR_TRIG at 0x5000016c; + + type CH5_AL3_CTRL_t { + CH5_AL3_CTRL = uint32(0); // + } + + // Alias for channel 5 CTRL register + register CH5_AL3_CTRL_t CH5_AL3_CTRL at 0x50000170; + + type CH5_AL3_WRITE_ADDR_t { + CH5_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 5 WRITE_ADDR register + register CH5_AL3_WRITE_ADDR_t CH5_AL3_WRITE_ADDR at 0x50000174; + + type CH5_AL3_TRANS_COUNT_t { + CH5_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 5 TRANS_COUNT register + register CH5_AL3_TRANS_COUNT_t CH5_AL3_TRANS_COUNT at 0x50000178; + + type CH5_AL3_READ_ADDR_TRIG_t { + CH5_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 5 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH5_AL3_READ_ADDR_TRIG_t CH5_AL3_READ_ADDR_TRIG at 0x5000017c; + + type CH6_READ_ADDR_t { + CH6_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 6 Read Address pointer + register CH6_READ_ADDR_t CH6_READ_ADDR at 0x50000180; + + type CH6_WRITE_ADDR_t { + CH6_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 6 Write Address pointer + register CH6_WRITE_ADDR_t CH6_WRITE_ADDR at 0x50000184; + + type CH6_TRANS_COUNT_t { + CH6_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 6 Transfer Count + register CH6_TRANS_COUNT_t CH6_TRANS_COUNT at 0x50000188; + + type CH6_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 6 Control and Status + register CH6_CTRL_TRIG_t CH6_CTRL_TRIG at 0x5000018c; + + type CH6_AL1_CTRL_t { + CH6_AL1_CTRL = uint32(0); // + } + + // Alias for channel 6 CTRL register + register CH6_AL1_CTRL_t CH6_AL1_CTRL at 0x50000190; + + type CH6_AL1_READ_ADDR_t { + CH6_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 6 READ_ADDR register + register CH6_AL1_READ_ADDR_t CH6_AL1_READ_ADDR at 0x50000194; + + type CH6_AL1_WRITE_ADDR_t { + CH6_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 6 WRITE_ADDR register + register CH6_AL1_WRITE_ADDR_t CH6_AL1_WRITE_ADDR at 0x50000198; + + type CH6_AL1_TRANS_COUNT_TRIG_t { + CH6_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 6 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH6_AL1_TRANS_COUNT_TRIG_t CH6_AL1_TRANS_COUNT_TRIG at 0x5000019c; + + type CH6_AL2_CTRL_t { + CH6_AL2_CTRL = uint32(0); // + } + + // Alias for channel 6 CTRL register + register CH6_AL2_CTRL_t CH6_AL2_CTRL at 0x500001a0; + + type CH6_AL2_TRANS_COUNT_t { + CH6_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 6 TRANS_COUNT register + register CH6_AL2_TRANS_COUNT_t CH6_AL2_TRANS_COUNT at 0x500001a4; + + type CH6_AL2_READ_ADDR_t { + CH6_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 6 READ_ADDR register + register CH6_AL2_READ_ADDR_t CH6_AL2_READ_ADDR at 0x500001a8; + + type CH6_AL2_WRITE_ADDR_TRIG_t { + CH6_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 6 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH6_AL2_WRITE_ADDR_TRIG_t CH6_AL2_WRITE_ADDR_TRIG at 0x500001ac; + + type CH6_AL3_CTRL_t { + CH6_AL3_CTRL = uint32(0); // + } + + // Alias for channel 6 CTRL register + register CH6_AL3_CTRL_t CH6_AL3_CTRL at 0x500001b0; + + type CH6_AL3_WRITE_ADDR_t { + CH6_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 6 WRITE_ADDR register + register CH6_AL3_WRITE_ADDR_t CH6_AL3_WRITE_ADDR at 0x500001b4; + + type CH6_AL3_TRANS_COUNT_t { + CH6_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 6 TRANS_COUNT register + register CH6_AL3_TRANS_COUNT_t CH6_AL3_TRANS_COUNT at 0x500001b8; + + type CH6_AL3_READ_ADDR_TRIG_t { + CH6_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 6 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH6_AL3_READ_ADDR_TRIG_t CH6_AL3_READ_ADDR_TRIG at 0x500001bc; + + type CH7_READ_ADDR_t { + CH7_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 7 Read Address pointer + register CH7_READ_ADDR_t CH7_READ_ADDR at 0x500001c0; + + type CH7_WRITE_ADDR_t { + CH7_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 7 Write Address pointer + register CH7_WRITE_ADDR_t CH7_WRITE_ADDR at 0x500001c4; + + type CH7_TRANS_COUNT_t { + CH7_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 7 Transfer Count + register CH7_TRANS_COUNT_t CH7_TRANS_COUNT at 0x500001c8; + + type CH7_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 7 Control and Status + register CH7_CTRL_TRIG_t CH7_CTRL_TRIG at 0x500001cc; + + type CH7_AL1_CTRL_t { + CH7_AL1_CTRL = uint32(0); // + } + + // Alias for channel 7 CTRL register + register CH7_AL1_CTRL_t CH7_AL1_CTRL at 0x500001d0; + + type CH7_AL1_READ_ADDR_t { + CH7_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 7 READ_ADDR register + register CH7_AL1_READ_ADDR_t CH7_AL1_READ_ADDR at 0x500001d4; + + type CH7_AL1_WRITE_ADDR_t { + CH7_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 7 WRITE_ADDR register + register CH7_AL1_WRITE_ADDR_t CH7_AL1_WRITE_ADDR at 0x500001d8; + + type CH7_AL1_TRANS_COUNT_TRIG_t { + CH7_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 7 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH7_AL1_TRANS_COUNT_TRIG_t CH7_AL1_TRANS_COUNT_TRIG at 0x500001dc; + + type CH7_AL2_CTRL_t { + CH7_AL2_CTRL = uint32(0); // + } + + // Alias for channel 7 CTRL register + register CH7_AL2_CTRL_t CH7_AL2_CTRL at 0x500001e0; + + type CH7_AL2_TRANS_COUNT_t { + CH7_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 7 TRANS_COUNT register + register CH7_AL2_TRANS_COUNT_t CH7_AL2_TRANS_COUNT at 0x500001e4; + + type CH7_AL2_READ_ADDR_t { + CH7_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 7 READ_ADDR register + register CH7_AL2_READ_ADDR_t CH7_AL2_READ_ADDR at 0x500001e8; + + type CH7_AL2_WRITE_ADDR_TRIG_t { + CH7_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 7 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH7_AL2_WRITE_ADDR_TRIG_t CH7_AL2_WRITE_ADDR_TRIG at 0x500001ec; + + type CH7_AL3_CTRL_t { + CH7_AL3_CTRL = uint32(0); // + } + + // Alias for channel 7 CTRL register + register CH7_AL3_CTRL_t CH7_AL3_CTRL at 0x500001f0; + + type CH7_AL3_WRITE_ADDR_t { + CH7_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 7 WRITE_ADDR register + register CH7_AL3_WRITE_ADDR_t CH7_AL3_WRITE_ADDR at 0x500001f4; + + type CH7_AL3_TRANS_COUNT_t { + CH7_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 7 TRANS_COUNT register + register CH7_AL3_TRANS_COUNT_t CH7_AL3_TRANS_COUNT at 0x500001f8; + + type CH7_AL3_READ_ADDR_TRIG_t { + CH7_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 7 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH7_AL3_READ_ADDR_TRIG_t CH7_AL3_READ_ADDR_TRIG at 0x500001fc; + + type CH8_READ_ADDR_t { + CH8_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 8 Read Address pointer + register CH8_READ_ADDR_t CH8_READ_ADDR at 0x50000200; + + type CH8_WRITE_ADDR_t { + CH8_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 8 Write Address pointer + register CH8_WRITE_ADDR_t CH8_WRITE_ADDR at 0x50000204; + + type CH8_TRANS_COUNT_t { + CH8_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 8 Transfer Count + register CH8_TRANS_COUNT_t CH8_TRANS_COUNT at 0x50000208; + + type CH8_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 8 Control and Status + register CH8_CTRL_TRIG_t CH8_CTRL_TRIG at 0x5000020c; + + type CH8_AL1_CTRL_t { + CH8_AL1_CTRL = uint32(0); // + } + + // Alias for channel 8 CTRL register + register CH8_AL1_CTRL_t CH8_AL1_CTRL at 0x50000210; + + type CH8_AL1_READ_ADDR_t { + CH8_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 8 READ_ADDR register + register CH8_AL1_READ_ADDR_t CH8_AL1_READ_ADDR at 0x50000214; + + type CH8_AL1_WRITE_ADDR_t { + CH8_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 8 WRITE_ADDR register + register CH8_AL1_WRITE_ADDR_t CH8_AL1_WRITE_ADDR at 0x50000218; + + type CH8_AL1_TRANS_COUNT_TRIG_t { + CH8_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 8 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH8_AL1_TRANS_COUNT_TRIG_t CH8_AL1_TRANS_COUNT_TRIG at 0x5000021c; + + type CH8_AL2_CTRL_t { + CH8_AL2_CTRL = uint32(0); // + } + + // Alias for channel 8 CTRL register + register CH8_AL2_CTRL_t CH8_AL2_CTRL at 0x50000220; + + type CH8_AL2_TRANS_COUNT_t { + CH8_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 8 TRANS_COUNT register + register CH8_AL2_TRANS_COUNT_t CH8_AL2_TRANS_COUNT at 0x50000224; + + type CH8_AL2_READ_ADDR_t { + CH8_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 8 READ_ADDR register + register CH8_AL2_READ_ADDR_t CH8_AL2_READ_ADDR at 0x50000228; + + type CH8_AL2_WRITE_ADDR_TRIG_t { + CH8_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 8 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH8_AL2_WRITE_ADDR_TRIG_t CH8_AL2_WRITE_ADDR_TRIG at 0x5000022c; + + type CH8_AL3_CTRL_t { + CH8_AL3_CTRL = uint32(0); // + } + + // Alias for channel 8 CTRL register + register CH8_AL3_CTRL_t CH8_AL3_CTRL at 0x50000230; + + type CH8_AL3_WRITE_ADDR_t { + CH8_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 8 WRITE_ADDR register + register CH8_AL3_WRITE_ADDR_t CH8_AL3_WRITE_ADDR at 0x50000234; + + type CH8_AL3_TRANS_COUNT_t { + CH8_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 8 TRANS_COUNT register + register CH8_AL3_TRANS_COUNT_t CH8_AL3_TRANS_COUNT at 0x50000238; + + type CH8_AL3_READ_ADDR_TRIG_t { + CH8_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 8 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH8_AL3_READ_ADDR_TRIG_t CH8_AL3_READ_ADDR_TRIG at 0x5000023c; + + type CH9_READ_ADDR_t { + CH9_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 9 Read Address pointer + register CH9_READ_ADDR_t CH9_READ_ADDR at 0x50000240; + + type CH9_WRITE_ADDR_t { + CH9_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 9 Write Address pointer + register CH9_WRITE_ADDR_t CH9_WRITE_ADDR at 0x50000244; + + type CH9_TRANS_COUNT_t { + CH9_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 9 Transfer Count + register CH9_TRANS_COUNT_t CH9_TRANS_COUNT at 0x50000248; + + type CH9_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 9 Control and Status + register CH9_CTRL_TRIG_t CH9_CTRL_TRIG at 0x5000024c; + + type CH9_AL1_CTRL_t { + CH9_AL1_CTRL = uint32(0); // + } + + // Alias for channel 9 CTRL register + register CH9_AL1_CTRL_t CH9_AL1_CTRL at 0x50000250; + + type CH9_AL1_READ_ADDR_t { + CH9_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 9 READ_ADDR register + register CH9_AL1_READ_ADDR_t CH9_AL1_READ_ADDR at 0x50000254; + + type CH9_AL1_WRITE_ADDR_t { + CH9_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 9 WRITE_ADDR register + register CH9_AL1_WRITE_ADDR_t CH9_AL1_WRITE_ADDR at 0x50000258; + + type CH9_AL1_TRANS_COUNT_TRIG_t { + CH9_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 9 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH9_AL1_TRANS_COUNT_TRIG_t CH9_AL1_TRANS_COUNT_TRIG at 0x5000025c; + + type CH9_AL2_CTRL_t { + CH9_AL2_CTRL = uint32(0); // + } + + // Alias for channel 9 CTRL register + register CH9_AL2_CTRL_t CH9_AL2_CTRL at 0x50000260; + + type CH9_AL2_TRANS_COUNT_t { + CH9_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 9 TRANS_COUNT register + register CH9_AL2_TRANS_COUNT_t CH9_AL2_TRANS_COUNT at 0x50000264; + + type CH9_AL2_READ_ADDR_t { + CH9_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 9 READ_ADDR register + register CH9_AL2_READ_ADDR_t CH9_AL2_READ_ADDR at 0x50000268; + + type CH9_AL2_WRITE_ADDR_TRIG_t { + CH9_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 9 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH9_AL2_WRITE_ADDR_TRIG_t CH9_AL2_WRITE_ADDR_TRIG at 0x5000026c; + + type CH9_AL3_CTRL_t { + CH9_AL3_CTRL = uint32(0); // + } + + // Alias for channel 9 CTRL register + register CH9_AL3_CTRL_t CH9_AL3_CTRL at 0x50000270; + + type CH9_AL3_WRITE_ADDR_t { + CH9_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 9 WRITE_ADDR register + register CH9_AL3_WRITE_ADDR_t CH9_AL3_WRITE_ADDR at 0x50000274; + + type CH9_AL3_TRANS_COUNT_t { + CH9_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 9 TRANS_COUNT register + register CH9_AL3_TRANS_COUNT_t CH9_AL3_TRANS_COUNT at 0x50000278; + + type CH9_AL3_READ_ADDR_TRIG_t { + CH9_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 9 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH9_AL3_READ_ADDR_TRIG_t CH9_AL3_READ_ADDR_TRIG at 0x5000027c; + + type CH10_READ_ADDR_t { + CH10_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 10 Read Address pointer + register CH10_READ_ADDR_t CH10_READ_ADDR at 0x50000280; + + type CH10_WRITE_ADDR_t { + CH10_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 10 Write Address pointer + register CH10_WRITE_ADDR_t CH10_WRITE_ADDR at 0x50000284; + + type CH10_TRANS_COUNT_t { + CH10_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 10 Transfer Count + register CH10_TRANS_COUNT_t CH10_TRANS_COUNT at 0x50000288; + + type CH10_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 10 Control and Status + register CH10_CTRL_TRIG_t CH10_CTRL_TRIG at 0x5000028c; + + type CH10_AL1_CTRL_t { + CH10_AL1_CTRL = uint32(0); // + } + + // Alias for channel 10 CTRL register + register CH10_AL1_CTRL_t CH10_AL1_CTRL at 0x50000290; + + type CH10_AL1_READ_ADDR_t { + CH10_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 10 READ_ADDR register + register CH10_AL1_READ_ADDR_t CH10_AL1_READ_ADDR at 0x50000294; + + type CH10_AL1_WRITE_ADDR_t { + CH10_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 10 WRITE_ADDR register + register CH10_AL1_WRITE_ADDR_t CH10_AL1_WRITE_ADDR at 0x50000298; + + type CH10_AL1_TRANS_COUNT_TRIG_t { + CH10_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 10 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH10_AL1_TRANS_COUNT_TRIG_t CH10_AL1_TRANS_COUNT_TRIG at 0x5000029c; + + type CH10_AL2_CTRL_t { + CH10_AL2_CTRL = uint32(0); // + } + + // Alias for channel 10 CTRL register + register CH10_AL2_CTRL_t CH10_AL2_CTRL at 0x500002a0; + + type CH10_AL2_TRANS_COUNT_t { + CH10_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 10 TRANS_COUNT register + register CH10_AL2_TRANS_COUNT_t CH10_AL2_TRANS_COUNT at 0x500002a4; + + type CH10_AL2_READ_ADDR_t { + CH10_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 10 READ_ADDR register + register CH10_AL2_READ_ADDR_t CH10_AL2_READ_ADDR at 0x500002a8; + + type CH10_AL2_WRITE_ADDR_TRIG_t { + CH10_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 10 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH10_AL2_WRITE_ADDR_TRIG_t CH10_AL2_WRITE_ADDR_TRIG at 0x500002ac; + + type CH10_AL3_CTRL_t { + CH10_AL3_CTRL = uint32(0); // + } + + // Alias for channel 10 CTRL register + register CH10_AL3_CTRL_t CH10_AL3_CTRL at 0x500002b0; + + type CH10_AL3_WRITE_ADDR_t { + CH10_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 10 WRITE_ADDR register + register CH10_AL3_WRITE_ADDR_t CH10_AL3_WRITE_ADDR at 0x500002b4; + + type CH10_AL3_TRANS_COUNT_t { + CH10_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 10 TRANS_COUNT register + register CH10_AL3_TRANS_COUNT_t CH10_AL3_TRANS_COUNT at 0x500002b8; + + type CH10_AL3_READ_ADDR_TRIG_t { + CH10_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 10 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH10_AL3_READ_ADDR_TRIG_t CH10_AL3_READ_ADDR_TRIG at 0x500002bc; + + type CH11_READ_ADDR_t { + CH11_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + } + + // DMA Channel 11 Read Address pointer + register CH11_READ_ADDR_t CH11_READ_ADDR at 0x500002c0; + + type CH11_WRITE_ADDR_t { + CH11_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + } + + // DMA Channel 11 Write Address pointer + register CH11_WRITE_ADDR_t CH11_WRITE_ADDR at 0x500002c4; + + type CH11_TRANS_COUNT_t { + CH11_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + } + + // DMA Channel 11 Transfer Count + register CH11_TRANS_COUNT_t CH11_TRANS_COUNT at 0x500002c8; + + type CH11_CTRL_TRIG_t { + EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + HIGH_PRIORITY = false; // HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + DATA_SIZE = uint2(0); // Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + INCR_READ = false; // If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. Generally this should be disabled for peripheral-to-memory transfers. + INCR_WRITE = false; // If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. Generally this should be disabled for memory-to-peripheral transfers. + RING_SIZE = uint4(0); // Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + RING_SEL = false; // Select whether RING_SIZE applies to read or write addresses. If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + CHAIN_TO = uint4(0); // When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + TREQ_SEL = uint6(0); // Select a Transfer Request signal. The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). 0x0 to 0x3a -> select DREQ n as TREQ + IRQ_QUIET = false; // In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + BSWAP = false; // Apply byte-swap transformation to DMA data. For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + SNIFF_EN = false; // If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. This allows checksum to be enabled or disabled on a per-control- block basis. + BUSY = false; // This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + _res1 = uint4(0); // Reserved, 4 bits + WRITE_ERROR = false; // If 1, the channel received a write bus error. Write one to clear. WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + READ_ERROR = false; // If 1, the channel received a read bus error. Write one to clear. READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + AHB_ERROR = false; // Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + } + + // DMA Channel 11 Control and Status + register CH11_CTRL_TRIG_t CH11_CTRL_TRIG at 0x500002cc; + + type CH11_AL1_CTRL_t { + CH11_AL1_CTRL = uint32(0); // + } + + // Alias for channel 11 CTRL register + register CH11_AL1_CTRL_t CH11_AL1_CTRL at 0x500002d0; + + type CH11_AL1_READ_ADDR_t { + CH11_AL1_READ_ADDR = uint32(0); // + } + + // Alias for channel 11 READ_ADDR register + register CH11_AL1_READ_ADDR_t CH11_AL1_READ_ADDR at 0x500002d4; + + type CH11_AL1_WRITE_ADDR_t { + CH11_AL1_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 11 WRITE_ADDR register + register CH11_AL1_WRITE_ADDR_t CH11_AL1_WRITE_ADDR at 0x500002d8; + + type CH11_AL1_TRANS_COUNT_TRIG_t { + CH11_AL1_TRANS_COUNT_TRIG = uint32(0); // + } + + // Alias for channel 11 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH11_AL1_TRANS_COUNT_TRIG_t CH11_AL1_TRANS_COUNT_TRIG at 0x500002dc; + + type CH11_AL2_CTRL_t { + CH11_AL2_CTRL = uint32(0); // + } + + // Alias for channel 11 CTRL register + register CH11_AL2_CTRL_t CH11_AL2_CTRL at 0x500002e0; + + type CH11_AL2_TRANS_COUNT_t { + CH11_AL2_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 11 TRANS_COUNT register + register CH11_AL2_TRANS_COUNT_t CH11_AL2_TRANS_COUNT at 0x500002e4; + + type CH11_AL2_READ_ADDR_t { + CH11_AL2_READ_ADDR = uint32(0); // + } + + // Alias for channel 11 READ_ADDR register + register CH11_AL2_READ_ADDR_t CH11_AL2_READ_ADDR at 0x500002e8; + + type CH11_AL2_WRITE_ADDR_TRIG_t { + CH11_AL2_WRITE_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 11 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH11_AL2_WRITE_ADDR_TRIG_t CH11_AL2_WRITE_ADDR_TRIG at 0x500002ec; + + type CH11_AL3_CTRL_t { + CH11_AL3_CTRL = uint32(0); // + } + + // Alias for channel 11 CTRL register + register CH11_AL3_CTRL_t CH11_AL3_CTRL at 0x500002f0; + + type CH11_AL3_WRITE_ADDR_t { + CH11_AL3_WRITE_ADDR = uint32(0); // + } + + // Alias for channel 11 WRITE_ADDR register + register CH11_AL3_WRITE_ADDR_t CH11_AL3_WRITE_ADDR at 0x500002f4; + + type CH11_AL3_TRANS_COUNT_t { + CH11_AL3_TRANS_COUNT = uint32(0); // + } + + // Alias for channel 11 TRANS_COUNT register + register CH11_AL3_TRANS_COUNT_t CH11_AL3_TRANS_COUNT at 0x500002f8; + + type CH11_AL3_READ_ADDR_TRIG_t { + CH11_AL3_READ_ADDR_TRIG = uint32(0); // + } + + // Alias for channel 11 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. + register CH11_AL3_READ_ADDR_TRIG_t CH11_AL3_READ_ADDR_TRIG at 0x500002fc; + + type DMA_INTR_t { + INTR = uint16(0); // Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + } + + // Interrupt Status (raw) + register DMA_INTR_t DMA_INTR at 0x50000400; + + type INTE0_t { + INTE0 = uint16(0); // Set bit n to pass interrupts from channel n to DMA IRQ 0. + } + + // Interrupt Enables for IRQ 0 + register INTE0_t INTE0 at 0x50000404; + + type INTF0_t { + INTF0 = uint16(0); // Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + } + + // Force Interrupts + register INTF0_t INTF0 at 0x50000408; + + type INTS0_t { + INTS0 = uint16(0); // Indicates active channel interrupt requests which are currently causing IRQ 0 to be asserted. Channel interrupts can be cleared by writing a bit mask here. + } + + // Interrupt Status for IRQ 0 + register INTS0_t INTS0 at 0x5000040c; + + type DMA_INTR1_t { + INTR1 = uint16(0); // Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + } + + // Interrupt Status (raw) + register DMA_INTR1_t DMA_INTR1 at 0x50000410; + + type INTE1_t { + INTE1 = uint16(0); // Set bit n to pass interrupts from channel n to DMA IRQ 1. + } + + // Interrupt Enables for IRQ 1 + register INTE1_t INTE1 at 0x50000414; + + type INTF1_t { + INTF1 = uint16(0); // Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + } + + // Force Interrupts for IRQ 1 + register INTF1_t INTF1 at 0x50000418; + + type INTS1_t { + INTS1 = uint16(0); // Indicates active channel interrupt requests which are currently causing IRQ 1 to be asserted. Channel interrupts can be cleared by writing a bit mask here. + } + + // Interrupt Status (masked) for IRQ 1 + register INTS1_t INTS1 at 0x5000041c; + + type TIMER0_t { + Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + X = uint16(0); // Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + } + + // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + register TIMER0_t TIMER0 at 0x50000420; + + type TIMER1_t { + Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + X = uint16(0); // Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + } + + // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + register TIMER1_t TIMER1 at 0x50000424; + + type TIMER2_t { + Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + X = uint16(0); // Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + } + + // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + register TIMER2_t TIMER2 at 0x50000428; + + type TIMER3_t { + Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + X = uint16(0); // Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + } + + // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + register TIMER3_t TIMER3 at 0x5000042c; + + type MULTI_CHAN_TRIGGER_t { + MULTI_CHAN_TRIGGER = uint16(0); // Each bit in this register corresponds to a DMA channel. Writing a 1 to the relevant bit is the same as writing to that channel's trigger register; the channel will start if it is currently enabled and not already busy. + } + + // Trigger one or more channels simultaneously + register MULTI_CHAN_TRIGGER_t MULTI_CHAN_TRIGGER at 0x50000430; + + type SNIFF_CTRL_t { + EN = false; // Enable sniffer + DMACH = uint4(0); // DMA channel for Sniffer to observe + CALC = uint4(0); // + BSWAP = false; // Locally perform a byte reverse on the sniffed data, before feeding into checksum. Note that the sniff hardware is downstream of the DMA channel byteswap performed in the read master: if channel CTRL_BSWAP and SNIFF_CTRL_BSWAP are both enabled, their effects cancel from the sniffer's point of view. + OUT_REV = false; // If set, the result appears bit-reversed when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + OUT_INV = false; // If set, the result appears inverted (bitwise complement) when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + } + + // Sniffer Control + register SNIFF_CTRL_t SNIFF_CTRL at 0x50000434; + + type SNIFF_DATA_t { + SNIFF_DATA = uint32(0); // Write an initial seed value here before starting a DMA transfer on the channel indicated by SNIFF_CTRL_DMACH. The hardware will update this register each time it observes a read from the indicated channel. Once the channel completes, the final result can be read from this register. + } + + // Data accumulator for sniff hardware + register SNIFF_DATA_t SNIFF_DATA at 0x50000438; + + type FIFO_LEVELS_t { + TDF_LVL = uint8(0); // Current Transfer-Data-FIFO fill level + WAF_LVL = uint8(0); // Current Write-Address-FIFO fill level + RAF_LVL = uint8(0); // Current Read-Address-FIFO fill level + } + + // Debug RAF, WAF, TDF levels + register FIFO_LEVELS_t FIFO_LEVELS at 0x50000440; + + type CHAN_ABORT_t { + CHAN_ABORT = uint16(0); // Each bit corresponds to a channel. Writing a 1 aborts whatever transfer sequence is in progress on that channel. The bit will remain high until any in-flight transfers have been flushed through the address and data FIFOs. After writing, this register must be polled until it returns all-zero. Until this point, it is unsafe to restart the channel. + } + + // Abort an in-progress transfer sequence on one or more channels + register CHAN_ABORT_t CHAN_ABORT at 0x50000444; + + type N_CHANNELS_t { + N_CHANNELS = uint5(0); // + } + + // The number of channels this DMA instance is equipped with. This DMA supports up to 16 hardware channels, but can be configured with as few as one, to minimise silicon area. + register N_CHANNELS_t N_CHANNELS at 0x50000448; + + type CH0_DBG_CTDREQ_t { + CH0_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH0_DBG_CTDREQ_t CH0_DBG_CTDREQ at 0x50000800; + + type CH0_DBG_TCR_t { + CH0_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH0_DBG_TCR_t CH0_DBG_TCR at 0x50000804; + + type CH1_DBG_CTDREQ_t { + CH1_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH1_DBG_CTDREQ_t CH1_DBG_CTDREQ at 0x50000840; + + type CH1_DBG_TCR_t { + CH1_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH1_DBG_TCR_t CH1_DBG_TCR at 0x50000844; + + type CH2_DBG_CTDREQ_t { + CH2_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH2_DBG_CTDREQ_t CH2_DBG_CTDREQ at 0x50000880; + + type CH2_DBG_TCR_t { + CH2_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH2_DBG_TCR_t CH2_DBG_TCR at 0x50000884; + + type CH3_DBG_CTDREQ_t { + CH3_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH3_DBG_CTDREQ_t CH3_DBG_CTDREQ at 0x500008c0; + + type CH3_DBG_TCR_t { + CH3_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH3_DBG_TCR_t CH3_DBG_TCR at 0x500008c4; + + type CH4_DBG_CTDREQ_t { + CH4_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH4_DBG_CTDREQ_t CH4_DBG_CTDREQ at 0x50000900; + + type CH4_DBG_TCR_t { + CH4_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH4_DBG_TCR_t CH4_DBG_TCR at 0x50000904; + + type CH5_DBG_CTDREQ_t { + CH5_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH5_DBG_CTDREQ_t CH5_DBG_CTDREQ at 0x50000940; + + type CH5_DBG_TCR_t { + CH5_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH5_DBG_TCR_t CH5_DBG_TCR at 0x50000944; + + type CH6_DBG_CTDREQ_t { + CH6_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH6_DBG_CTDREQ_t CH6_DBG_CTDREQ at 0x50000980; + + type CH6_DBG_TCR_t { + CH6_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH6_DBG_TCR_t CH6_DBG_TCR at 0x50000984; + + type CH7_DBG_CTDREQ_t { + CH7_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH7_DBG_CTDREQ_t CH7_DBG_CTDREQ at 0x500009c0; + + type CH7_DBG_TCR_t { + CH7_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH7_DBG_TCR_t CH7_DBG_TCR at 0x500009c4; + + type CH8_DBG_CTDREQ_t { + CH8_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH8_DBG_CTDREQ_t CH8_DBG_CTDREQ at 0x50000a00; + + type CH8_DBG_TCR_t { + CH8_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH8_DBG_TCR_t CH8_DBG_TCR at 0x50000a04; + + type CH9_DBG_CTDREQ_t { + CH9_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH9_DBG_CTDREQ_t CH9_DBG_CTDREQ at 0x50000a40; + + type CH9_DBG_TCR_t { + CH9_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH9_DBG_TCR_t CH9_DBG_TCR at 0x50000a44; + + type CH10_DBG_CTDREQ_t { + CH10_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH10_DBG_CTDREQ_t CH10_DBG_CTDREQ at 0x50000a80; + + type CH10_DBG_TCR_t { + CH10_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH10_DBG_TCR_t CH10_DBG_TCR at 0x50000a84; + + type CH11_DBG_CTDREQ_t { + CH11_DBG_CTDREQ = uint6(0); // + } + + // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + register CH11_DBG_CTDREQ_t CH11_DBG_CTDREQ at 0x50000ac0; + + type CH11_DBG_TCR_t { + CH11_DBG_TCR = uint32(0); // + } + + // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + register CH11_DBG_TCR_t CH11_DBG_TCR at 0x50000ac4; + + +/* Types and registers for TIMER + Controls time and alarms time is a 64 bit value indicating the time in usec since power-on timeh is the top 32 bits of time & timel is the bottom 32 bits to change time write to timelw before timehw to read time read from timelr before timehr An alarm is set by setting alarm_enable and writing to the corresponding alarm register When an alarm is pending, the corresponding alarm_running signal will be high An alarm can be cancelled before it has finished by clearing the alarm_enable When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared To clear the interrupt write a 1 to the corresponding alarm_irq + */ + + type TIMEHW_t { + TIMEHW = uint32(0); // + } + + // Write to bits 63:32 of time always write timelw before timehw + register TIMEHW_t TIMEHW at 0x40054000; + + type TIMELW_t { + TIMELW = uint32(0); // + } + + // Write to bits 31:0 of time writes do not get copied to time until timehw is written + register TIMELW_t TIMELW at 0x40054004; + + type TIMEHR_t { + TIMEHR = uint32(0); // + } + + // Read from bits 63:32 of time always read timelr before timehr + register TIMEHR_t TIMEHR at 0x40054008; + + type TIMELR_t { + TIMELR = uint32(0); // + } + + // Read from bits 31:0 of time + register TIMELR_t TIMELR at 0x4005400c; + + type ALARM0_t { + ALARM0 = uint32(0); // + } + + // Arm alarm 0, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM0 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. + register ALARM0_t ALARM0 at 0x40054010; + + type ALARM1_t { + ALARM1 = uint32(0); // + } + + // Arm alarm 1, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM1 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. + register ALARM1_t ALARM1 at 0x40054014; + + type ALARM2_t { + ALARM2 = uint32(0); // + } + + // Arm alarm 2, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM2 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. + register ALARM2_t ALARM2 at 0x40054018; + + type ALARM3_t { + ALARM3 = uint32(0); // + } + + // Arm alarm 3, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM3 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. + register ALARM3_t ALARM3 at 0x4005401c; + + type ARMED_t { + ARMED = uint4(0); // + } + + // Indicates the armed/disarmed status of each alarm. A write to the corresponding ALARMx register arms the alarm. Alarms automatically disarm upon firing, but writing ones here will disarm immediately without waiting to fire. + register ARMED_t ARMED at 0x40054020; + + type TIMERAWH_t { + TIMERAWH = uint32(0); // + } + + // Raw read from bits 63:32 of time (no side effects) + register TIMERAWH_t TIMERAWH at 0x40054024; + + type TIMERAWL_t { + TIMERAWL = uint32(0); // + } + + // Raw read from bits 31:0 of time (no side effects) + register TIMERAWL_t TIMERAWL at 0x40054028; + + type DBGPAUSE_t { + _res1 = false; // Reserved, 1 bits + DBG0 = false; // Pause when processor 0 is in debug mode + DBG1 = false; // Pause when processor 1 is in debug mode + } + + // Set bits high to enable pause when the corresponding debug ports are active + register DBGPAUSE_t DBGPAUSE at 0x4005402c; + + type PAUSE_t { + PAUSE = false; // + } + + // Set high to pause the timer + register PAUSE_t PAUSE at 0x40054030; + + type TIMER_INTR_t { + ALARM_0 = false; // + ALARM_1 = false; // + ALARM_2 = false; // + ALARM_3 = false; // + } + + // Raw Interrupts + register TIMER_INTR_t TIMER_INTR at 0x40054034; + + type TIMER_INTE_t { + ALARM_0 = false; // + ALARM_1 = false; // + ALARM_2 = false; // + ALARM_3 = false; // + } + + // Interrupt Enable + register TIMER_INTE_t TIMER_INTE at 0x40054038; + + type TIMER_INTF_t { + ALARM_0 = false; // + ALARM_1 = false; // + ALARM_2 = false; // + ALARM_3 = false; // + } + + // Interrupt Force + register TIMER_INTF_t TIMER_INTF at 0x4005403c; + + type TIMER_INTS_t { + ALARM_0 = false; // + ALARM_1 = false; // + ALARM_2 = false; // + ALARM_3 = false; // + } + + // Interrupt status after masking & forcing + register TIMER_INTS_t TIMER_INTS at 0x40054040; + + +/* Types and registers for PWM + Simple PWM + */ + + type CH0_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + } + + // Control and status register + register CH0_CSR_t CH0_CSR at 0x40050000; + + type CH0_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH0_DIV_t CH0_DIV at 0x40050004; + + type CH0_CTR_t { + CH0_CTR = uint16(0); // + } + + // Direct access to the PWM counter + register CH0_CTR_t CH0_CTR at 0x40050008; + + type CH0_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH0_CC_t CH0_CC at 0x4005000c; + + type CH0_TOP_t { + CH0_TOP = uint16(0); // + } + + // Counter wrap value + register CH0_TOP_t CH0_TOP at 0x40050010; + + type CH1_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + } + + // Control and status register + register CH1_CSR_t CH1_CSR at 0x40050014; + + type CH1_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH1_DIV_t CH1_DIV at 0x40050018; + + type CH1_CTR_t { + CH1_CTR = uint16(0); // + } + + // Direct access to the PWM counter + register CH1_CTR_t CH1_CTR at 0x4005001c; + + type CH1_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH1_CC_t CH1_CC at 0x40050020; + + type CH1_TOP_t { + CH1_TOP = uint16(0); // + } + + // Counter wrap value + register CH1_TOP_t CH1_TOP at 0x40050024; + + type CH2_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + } + + // Control and status register + register CH2_CSR_t CH2_CSR at 0x40050028; + + type CH2_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH2_DIV_t CH2_DIV at 0x4005002c; + + type CH2_CTR_t { + CH2_CTR = uint16(0); // + } + + // Direct access to the PWM counter + register CH2_CTR_t CH2_CTR at 0x40050030; + + type CH2_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH2_CC_t CH2_CC at 0x40050034; + + type CH2_TOP_t { + CH2_TOP = uint16(0); // + } + + // Counter wrap value + register CH2_TOP_t CH2_TOP at 0x40050038; + + type CH3_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + } + + // Control and status register + register CH3_CSR_t CH3_CSR at 0x4005003c; + + type CH3_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH3_DIV_t CH3_DIV at 0x40050040; + + type CH3_CTR_t { + CH3_CTR = uint16(0); // + } + + // Direct access to the PWM counter + register CH3_CTR_t CH3_CTR at 0x40050044; + + type CH3_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH3_CC_t CH3_CC at 0x40050048; + + type CH3_TOP_t { + CH3_TOP = uint16(0); // + } + + // Counter wrap value + register CH3_TOP_t CH3_TOP at 0x4005004c; + + type CH4_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + } + + // Control and status register + register CH4_CSR_t CH4_CSR at 0x40050050; + + type CH4_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH4_DIV_t CH4_DIV at 0x40050054; + + type CH4_CTR_t { + CH4_CTR = uint16(0); // + } + + // Direct access to the PWM counter + register CH4_CTR_t CH4_CTR at 0x40050058; + + type CH4_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH4_CC_t CH4_CC at 0x4005005c; + + type CH4_TOP_t { + CH4_TOP = uint16(0); // + } + + // Counter wrap value + register CH4_TOP_t CH4_TOP at 0x40050060; + + type CH5_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + } + + // Control and status register + register CH5_CSR_t CH5_CSR at 0x40050064; + + type CH5_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH5_DIV_t CH5_DIV at 0x40050068; + + type CH5_CTR_t { + CH5_CTR = uint16(0); // + } + + // Direct access to the PWM counter + register CH5_CTR_t CH5_CTR at 0x4005006c; + + type CH5_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH5_CC_t CH5_CC at 0x40050070; + + type CH5_TOP_t { + CH5_TOP = uint16(0); // + } + + // Counter wrap value + register CH5_TOP_t CH5_TOP at 0x40050074; + + type CH6_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + } + + // Control and status register + register CH6_CSR_t CH6_CSR at 0x40050078; + + type CH6_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH6_DIV_t CH6_DIV at 0x4005007c; + + type CH6_CTR_t { + CH6_CTR = uint16(0); // + } + + // Direct access to the PWM counter + register CH6_CTR_t CH6_CTR at 0x40050080; + + type CH6_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH6_CC_t CH6_CC at 0x40050084; + + type CH6_TOP_t { + CH6_TOP = uint16(0); // + } + + // Counter wrap value + register CH6_TOP_t CH6_TOP at 0x40050088; + + type CH7_CSR_t { + EN = false; // Enable the PWM channel. + PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge + A_INV = false; // Invert output A + B_INV = false; // Invert output B + DIVMODE = uint2(0); // + PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. + PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + } + + // Control and status register + register CH7_CSR_t CH7_CSR at 0x4005008c; + + type CH7_DIV_t { + FRAC = uint4(0); // + INT = uint8(0); // + } + + // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. + register CH7_DIV_t CH7_DIV at 0x40050090; + + type CH7_CTR_t { + CH7_CTR = uint16(0); // + } + + // Direct access to the PWM counter + register CH7_CTR_t CH7_CTR at 0x40050094; + + type CH7_CC_t { + A = uint16(0); // + B = uint16(0); // + } + + // Counter compare values + register CH7_CC_t CH7_CC at 0x40050098; + + type CH7_TOP_t { + CH7_TOP = uint16(0); // + } + + // Counter wrap value + register CH7_TOP_t CH7_TOP at 0x4005009c; + + type EN_t { + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + } + + // This register aliases the CSR_EN bits for all channels. Writing to this register allows multiple channels to be enabled or disabled simultaneously, so they can run in perfect sync. For each channel, there is only one physical EN register bit, which can be accessed through here or CHx_CSR. + register EN_t EN at 0x400500a0; + + type PWM_INTR_t { + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + } + + // Raw Interrupts + register PWM_INTR_t PWM_INTR at 0x400500a4; + + type PWM_INTE_t { + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + } + + // Interrupt Enable + register PWM_INTE_t PWM_INTE at 0x400500a8; + + type PWM_INTF_t { + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + } + + // Interrupt Force + register PWM_INTF_t PWM_INTF at 0x400500ac; + + type PWM_INTS_t { + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + } + + // Interrupt status after masking & forcing + register PWM_INTS_t PWM_INTS at 0x400500b0; + + +/* Types and registers for ADC + Control and data interface to SAR ADC + */ + + type ADC_CS_t { + EN = false; // Power on ADC and enable its clock. 1 - enabled. 0 - disabled. + TS_EN = false; // Power on temperature sensor. 1 - enabled. 0 - disabled. + START_ONCE = false; // Start a single conversion. Self-clearing. Ignored if start_many is asserted. + START_MANY = false; // Continuously perform conversions whilst this bit is 1. A new conversion will start immediately after the previous finishes. + _res1 = uint4(0); // Reserved, 4 bits + READY = false; // 1 if the ADC is ready to start a new conversion. Implies any previous conversion has completed. 0 whilst conversion in progress. + ERR = false; // The most recent ADC conversion encountered an error; result is undefined or noisy. + ERR_STICKY = false; // Some past ADC conversion encountered an error. Write 1 to clear. + _res2 = false; // Reserved, 1 bits + AINSEL = uint3(0); // Select analog mux input. Updated automatically in round-robin mode. + _res3 = false; // Reserved, 1 bits + RROBIN = uint5(0); // Round-robin sampling. 1 bit per channel. Set all bits to 0 to disable. Otherwise, the ADC will cycle through each enabled channel in a round-robin fashion. The first channel to be sampled will be the one currently indicated by AINSEL. AINSEL will be updated after each conversion with the newly-selected channel. + } + + // ADC Control and Status + register ADC_CS_t ADC_CS at 0x4004c000; + + type RESULT_t { + RESULT = uint12(0); // + } + + // Result of most recent ADC conversion + register RESULT_t RESULT at 0x4004c004; + + type FCS_t { + EN = false; // If 1: write result to the FIFO after each conversion. + SHIFT = false; // If 1: FIFO results are right-shifted to be one byte in size. Enables DMA to byte buffers. + ERR = false; // If 1: conversion error bit appears in the FIFO alongside the result + DREQ_EN = false; // If 1: assert DMA requests when FIFO contains data + _res1 = uint4(0); // Reserved, 4 bits + EMPTY = false; // + FULL = false; // + UNDER = false; // 1 if the FIFO has been underflowed. Write 1 to clear. + OVER = false; // 1 if the FIFO has been overflowed. Write 1 to clear. + _res2 = uint4(0); // Reserved, 4 bits + LEVEL = uint4(0); // The number of conversion results currently waiting in the FIFO + _res3 = uint4(0); // Reserved, 4 bits + THRESH = uint4(0); // DREQ/IRQ asserted when level >= threshold + } + + // FIFO control and status + register FCS_t FCS at 0x4004c008; + + type FIFO_t { + VAL = uint12(0); // + _res1 = uint3(0); // Reserved, 3 bits + ERR = false; // 1 if this particular sample experienced a conversion error. Remains in the same location if the sample is shifted. + } + + // Conversion result FIFO + register FIFO_t FIFO at 0x4004c00c; + + type ADC_DIV_t { + FRAC = uint8(0); // Fractional part of clock divisor. First-order delta-sigma. + INT = uint16(0); // Integer part of clock divisor. + } + + // Clock divider. If non-zero, CS_START_MANY will start conversions at regular intervals rather than back-to-back. The divider is reset when either of these fields are written. Total period is 1 + INT + FRAC / 256 + register ADC_DIV_t ADC_DIV at 0x4004c010; + + type ADC_INTR_t { + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + } + + // Raw Interrupts + register ADC_INTR_t ADC_INTR at 0x4004c014; + + type ADC_INTE_t { + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + } + + // Interrupt Enable + register ADC_INTE_t ADC_INTE at 0x4004c018; + + type ADC_INTF_t { + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + } + + // Interrupt Force + register ADC_INTF_t ADC_INTF at 0x4004c01c; + + type ADC_INTS_t { + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + } + + // Interrupt status after masking & forcing + register ADC_INTS_t ADC_INTS at 0x4004c020; + + +/* Types and registers for I2C0 + DW_apb_i2c address block List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): IC_ULTRA_FAST_MODE ................ 0x0 IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 IC_UFM_SCL_LOW_COUNT .............. 0x0008 IC_UFM_SCL_HIGH_COUNT ............. 0x0006 IC_TX_TL .......................... 0x0 IC_TX_CMD_BLOCK ................... 0x1 IC_HAS_DMA ........................ 0x1 IC_HAS_ASYNC_FIFO ................. 0x0 IC_SMBUS_ARP ...................... 0x0 IC_FIRST_DATA_BYTE_STATUS ......... 0x1 IC_INTR_IO ........................ 0x1 IC_MASTER_MODE .................... 0x1 IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 IC_INTR_POL ....................... 0x1 IC_OPTIONAL_SAR ................... 0x0 IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 IC_DEFAULT_SLAVE_ADDR ............. 0x055 IC_DEFAULT_HS_SPKLEN .............. 0x1 IC_FS_SCL_HIGH_COUNT .............. 0x0006 IC_HS_SCL_LOW_COUNT ............... 0x0008 IC_DEVICE_ID_VALUE ................ 0x0 IC_10BITADDR_MASTER ............... 0x0 IC_CLK_FREQ_OPTIMIZATION .......... 0x0 IC_DEFAULT_FS_SPKLEN .............. 0x7 IC_ADD_ENCODED_PARAMS ............. 0x0 IC_DEFAULT_SDA_HOLD ............... 0x000001 IC_DEFAULT_SDA_SETUP .............. 0x64 IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 IC_CLOCK_PERIOD ................... 100 IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 IC_RESTART_EN ..................... 0x1 IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 IC_BUS_CLEAR_FEATURE .............. 0x0 IC_CAP_LOADING .................... 100 IC_FS_SCL_LOW_COUNT ............... 0x000d APB_DATA_WIDTH .................... 32 IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff IC_SLV_DATA_NACK_ONLY ............. 0x1 IC_10BITADDR_SLAVE ................ 0x0 IC_CLK_TYPE ....................... 0x0 IC_SMBUS_UDID_MSB ................. 0x0 IC_SMBUS_SUSPEND_ALERT ............ 0x0 IC_HS_SCL_HIGH_COUNT .............. 0x0006 IC_SLV_RESTART_DET_EN ............. 0x1 IC_SMBUS .......................... 0x0 IC_OPTIONAL_SAR_DEFAULT ........... 0x0 IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 IC_USE_COUNTS ..................... 0x0 IC_RX_BUFFER_DEPTH ................ 16 IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff IC_RX_FULL_HLD_BUS_EN ............. 0x1 IC_SLAVE_DISABLE .................. 0x1 IC_RX_TL .......................... 0x0 IC_DEVICE_ID ...................... 0x0 IC_HC_COUNT_VALUES ................ 0x0 I2C_DYNAMIC_TAR_UPDATE ............ 0 IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff IC_HS_MASTER_CODE ................. 0x1 IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff IC_SS_SCL_HIGH_COUNT .............. 0x0028 IC_SS_SCL_LOW_COUNT ............... 0x002f IC_MAX_SPEED_MODE ................. 0x2 IC_STAT_FOR_CLK_STRETCH ........... 0x0 IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 IC_DEFAULT_UFM_SPKLEN ............. 0x1 IC_TX_BUFFER_DEPTH ................ 16 + */ + + type IC_CON_t { + MASTER_MODE = false; // This bit controls whether the DW_apb_i2c master is enabled. NOTE: Software should ensure that if this bit is written with '1' then bit 6 should also be written with a '1'. + SPEED = uint2(0); // These bits control at which speed the DW_apb_i2c operates; its setting is relevant only if one is operating the DW_apb_i2c in master mode. Hardware protects against illegal values being programmed by software. These bits must be programmed appropriately for slave mode also, as it is used to capture correct value of spike filter as per the speed mode. This register should be programmed only with a value in the range of 1 to IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of IC_MAX_SPEED_MODE. 1: standard mode (100 kbit/s) 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s) 3: high speed mode (3.4 Mbit/s) Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 + IC_10BITADDR_SLAVE = false; // When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c responds to only 10-bit addressing transfers that match the full 10 bits of the IC_SAR register. + IC_10BITADDR_MASTER = false; // Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing + IC_RESTART_EN = false; // Determines whether RESTART conditions may be sent when acting as a master. Some older slaves do not support handling RESTART conditions; however, RESTART conditions are used in several DW_apb_i2c operations. When RESTART is disabled, the master is prohibited from performing the following functions: - Sending a START BYTE - Performing any high-speed mode operation - High-speed mode operation - Performing direction changes in combined format mode - Performing a read operation with a 10-bit address By replacing RESTART condition followed by a STOP and a subsequent START condition, split operations are broken down into multiple DW_apb_i2c transfers. If the above operations are performed, it will result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. Reset value: ENABLED + IC_SLAVE_DISABLE = false; // This bit controls whether I2C has its slave disabled, which means once the presetn signal is applied, then this bit is set and the slave is disabled. If this bit is set (slave is disabled), DW_apb_i2c functions only as a master and does not perform any action that requires a slave. NOTE: Software should ensure that if this bit is written with 0, then bit 0 should also be written with a 0. + STOP_DET_IFADDRESSED = false; // In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset value: 0x0 NOTE: During a general call address, this slave does not issue the STOP_DET interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). + TX_EMPTY_CTRL = false; // This bit controls the generation of the TX_EMPTY interrupt, as described in the IC_RAW_INTR_STAT register. Reset value: 0x0. + RX_FIFO_FULL_HLD_CTRL = false; // This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is physically full to its RX_BUFFER_DEPTH, as described in the IC_RX_FULL_HLD_BUS_EN parameter. Reset value: 0x0. + STOP_DET_IF_MASTER_ACTIVE = false; // Master issues the STOP_DET interrupt irrespective of whether master is active or not + } + + // I2C0 I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only. + register IC_CON_t I2C0_IC_CON at 0x40044000; + + type IC_TAR_t { + IC_TAR = uint10(0); // This is the target address for any master transaction. When transmitting a General Call, these bits are ignored. To generate a START BYTE, the CPU needs to write only once into these bits. If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared between master and slave, so full loopback is not feasible. Only one direction loopback mode is supported (simplex), not duplex. A master cannot transmit to itself; it can transmit to only a slave. + GC_OR_START = false; // If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit indicates whether a General Call or START byte command is to be performed by the DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only writes may be performed. Attempting to issue a read command results in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START BYTE Reset value: 0x0 + SPECIAL = false; // This bit indicates whether software performs a Device-ID or General Call or START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: perform special I2C command as specified in Device_ID or GC_OR_START bit Reset value: 0x0 + } + + // I2C0 I2C Target Address Register This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0. Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only. + register IC_TAR_t I2C0_IC_TAR at 0x40044004; + + type IC_SAR_t { + IC_SAR = uint10(0); // The IC_SAR holds the slave address when the I2C is operating as a slave. For 7-bit addressing, only IC_SAR[6:0] is used. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. Note: The default values cannot be any of the reserved address locations: that is, 0x00 to 0x07, or 0x78 to 0x7f. The correct operation of the device is not guaranteed if you program the IC_SAR or IC_TAR to a reserved value. Refer to <> for a complete list of these reserved values. + } + + // I2C0 I2C Slave Address Register + register IC_SAR_t I2C0_IC_SAR at 0x40044008; + + type IC_DATA_CMD_t { + DAT = uint8(0); // This register contains the data to be transmitted or received on the I2C bus. If you are writing to this register and want to perform a read, bits 7:0 (DAT) are ignored by the DW_apb_i2c. However, when you read this register, these bits return the value of data received on the DW_apb_i2c interface. Reset value: 0x0 + CMD = false; // This bit controls whether a read or a write is performed. This bit does not control the direction when the DW_apb_i2con acts as a slave. It controls only the direction when it acts as a master. When a command is entered in the TX FIFO, this bit distinguishes the write and read commands. In slave-receiver mode, this bit is a 'don't care' because writes to this register are not required. In slave-transmitter mode, a '0' indicates that the data in IC_DATA_CMD is to be transmitted. When programming this bit, you should remember the following: attempting to perform a read operation after a General Call command has been sent results in a TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs. Reset value: 0x0 + STOP = false; // This bit controls whether a STOP is issued after the byte is sent or received. - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master immediately tries to start a new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master continues the current transfer by sending/receiving data bytes according to the value of the CMD bit. If the Tx FIFO is empty, the master holds the SCL line low and stalls the bus until a new command is available in the Tx FIFO. Reset value: 0x0 + RESTART = false; // This bit controls whether a RESTART is issued before the byte is sent or received. 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received (according to the value of CMD), regardless of whether or not the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. Reset value: 0x0 + FIRST_DATA_BYTE = false; // Indicates the first data byte received after the address phase for receive transfer in Master receiver or Slave receiver mode. Reset value : 0x0 NOTE: In case of APB_DATA_WIDTH=8, 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status on 11 bit. 2. In order to read the 11 bit, the user has to perform the first data byte read [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in order to know the status of 11 bit (whether the data received in previous read is a first data byte or not). 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] (offset 0x11) if not interested in FIRST_DATA_BYTE status. + } + + // I2C0 I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO. The size of the register changes as follows: Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging. + register IC_DATA_CMD_t I2C0_IC_DATA_CMD at 0x40044010; + + type IC_SS_SCL_HCNT_t { + IC_SS_SCL_HCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration'. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. NOTE: This register must not be programmed to a value higher than 65525, because DW_apb_i2c uses a 16-bit counter to flag an I2C bus idle condition when this counter reaches a value of IC_SS_SCL_HCNT + 10. + } + + // I2C0 Standard Speed I2C Clock SCL High Count Register + register IC_SS_SCL_HCNT_t I2C0_IC_SS_SCL_HCNT at 0x40044014; + + type IC_SS_SCL_LCNT_t { + IC_SS_SCL_LCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration' This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 8; hardware prevents values less than this being written, and if attempted, results in 8 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of DW_apb_i2c. The lower byte must be programmed first, and then the upper byte is programmed. + } + + // I2C0 Standard Speed I2C Clock SCL Low Count Register + register IC_SS_SCL_LCNT_t I2C0_IC_SS_SCL_LCNT at 0x40044018; + + type IC_FS_SCL_HCNT_t { + IC_FS_SCL_HCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for fast mode or fast mode plus. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH == 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. + } + + // I2C0 Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register + register IC_FS_SCL_HCNT_t I2C0_IC_FS_SCL_HCNT at 0x4004401c; + + type IC_FS_SCL_LCNT_t { + IC_FS_SCL_LCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for fast speed. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 8; hardware prevents values less than this being written, and if attempted results in 8 being set. For designs with APB_DATA_WIDTH = 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. If the value is less than 8 then the count value gets changed to 8. + } + + // I2C0 Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register + register IC_FS_SCL_LCNT_t I2C0_IC_FS_SCL_LCNT at 0x40044020; + + type IC_INTR_STAT_t { + R_RX_UNDER = false; // See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit. Reset value: 0x0 + R_RX_OVER = false; // See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit. Reset value: 0x0 + R_RX_FULL = false; // See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit. Reset value: 0x0 + R_TX_OVER = false; // See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit. Reset value: 0x0 + R_TX_EMPTY = false; // See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit. Reset value: 0x0 + R_RD_REQ = false; // See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit. Reset value: 0x0 + R_TX_ABRT = false; // See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit. Reset value: 0x0 + R_RX_DONE = false; // See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit. Reset value: 0x0 + R_ACTIVITY = false; // See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit. Reset value: 0x0 + R_STOP_DET = false; // See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit. Reset value: 0x0 + R_START_DET = false; // See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit. Reset value: 0x0 + R_GEN_CALL = false; // See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit. Reset value: 0x0 + R_RESTART_DET = false; // See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit. Reset value: 0x0 + } + + // I2C0 I2C Interrupt Status Register Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. + register IC_INTR_STAT_t I2C0_IC_INTR_STAT at 0x4004402c; + + type IC_INTR_MASK_t { + M_RX_UNDER = false; // This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RX_OVER = false; // This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RX_FULL = false; // This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_TX_OVER = false; // This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_TX_EMPTY = false; // This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RD_REQ = false; // This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_TX_ABRT = false; // This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RX_DONE = false; // This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_ACTIVITY = false; // This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register. Reset value: 0x0 + M_STOP_DET = false; // This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 + M_START_DET = false; // This bit masks the R_START_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 + M_GEN_CALL = false; // This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RESTART_DET = false; // This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 I2C Interrupt Mask Register. These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. + register IC_INTR_MASK_t I2C0_IC_INTR_MASK at 0x40044030; + + type IC_RAW_INTR_STAT_t { + RX_UNDER = false; // Set if the processor attempts to read the receive buffer when it is empty by reading from the IC_DATA_CMD register. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. Reset value: 0x0 + RX_OVER = false; // Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an additional byte is received from an external I2C device. The DW_apb_i2c acknowledges this, but any data bytes received after the FIFO is full are lost. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never overflows. Reset value: 0x0 + RX_FULL = false; // Set when the receive buffer reaches or goes above the RX_TL threshold in the IC_RX_TL register. It is automatically cleared by hardware when buffer level goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of the activity that continues. Reset value: 0x0 + TX_OVER = false; // Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and the processor attempts to issue another I2C command by writing to the IC_DATA_CMD register. When the module is disabled, this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. Reset value: 0x0 + TX_EMPTY = false; // The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register and the transmission of the address/data from the internal shift register for the most recently popped command is completed. It is automatically cleared by hardware when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no data within it, so this bit is set to 1, provided there is activity in the master or slave state machines. When there is no longer any activity, then with ic_en=0, this bit is set to 0. Reset value: 0x0. + RD_REQ = false; // This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in a wait state (SCL=0) until this interrupt is serviced, which means that the slave has been addressed by a remote master that is asking for data to be transferred. The processor must respond to this interrupt and then write the requested data to the IC_DATA_CMD register. This bit is set to 0 just after the processor reads the IC_CLR_RD_REQ register. Reset value: 0x0 + TX_ABRT = false; // This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete the intended actions on the contents of the transmit FIFO. This situation can occur both as an I2C master or an I2C slave, and is referred to as a 'transmit abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the reason why the transmit abort takes places. Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever there is a transmit abort caused by any of the events tracked by the IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is then ready to accept more data bytes from the APB interface. Reset value: 0x0 + RX_DONE = false; // When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if the master does not acknowledge a transmitted byte. This occurs on the last byte of the transmission, indicating that the transmission is done. Reset value: 0x0 + ACTIVITY = false; // This bit captures DW_apb_i2c activity and stays set until it is cleared. There are four ways to clear it: - Disabling the DW_apb_i2c - Reading the IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once this bit is set, it stays set unless one of the four methods is used to clear it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, indicating that there was activity on the bus. Reset value: 0x0 + STOP_DET = false; // Indicates whether a STOP condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET interrupt will be issued only if slave is addressed. Note: During a general call address, this slave does not issue a STOP_DET interrupt if STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt will be issued irrespective of whether master is active or not. Reset value: 0x0 + START_DET = false; // Indicates whether a START or RESTART condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. Reset value: 0x0 + GEN_CALL = false; // Set only when a General Call address is received and it is acknowledged. It stays set until it is cleared either by disabling DW_apb_i2c or when the CPU reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data in the Rx buffer. Reset value: 0x0 + RESTART_DET = false; // Indicates whether a RESTART condition has occurred on the I2C interface when DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled only when IC_SLV_RESTART_DET_EN=1. Note: However, in high-speed mode or during a START BYTE transfer, the RESTART comes before the address field as per the I2C protocol. In this case, the slave is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does not generate the RESTART_DET interrupt. Reset value: 0x0 + } + + // I2C0 I2C Raw Interrupt Status Register Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c. + register IC_RAW_INTR_STAT_t I2C0_IC_RAW_INTR_STAT at 0x40044034; + + type IC_RX_TL_t { + RX_TL = uint8(0); // Receive FIFO Threshold Level. Controls the level of entries (or above) that triggers the RX_FULL interrupt (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that hardware does not allow this value to be set to a value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. + } + + // I2C0 I2C Receive FIFO Threshold Register + register IC_RX_TL_t I2C0_IC_RX_TL at 0x40044038; + + type IC_TX_TL_t { + TX_TL = uint8(0); // Transmit FIFO Threshold Level. Controls the level of entries (or below) that trigger the TX_EMPTY interrupt (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that it may not be set to value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and a value of 255 sets the threshold for 255 entries. + } + + // I2C0 I2C Transmit FIFO Threshold Register + register IC_TX_TL_t I2C0_IC_TX_TL at 0x4004403c; + + type IC_CLR_INTR_t { + CLR_INTR = false; // Read this register to clear the combined interrupt, all individual interrupts, and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable interrupts but software clearable interrupts. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. Reset value: 0x0 + } + + // I2C0 Clear Combined and Individual Interrupt Register + register IC_CLR_INTR_t I2C0_IC_CLR_INTR at 0x40044040; + + type IC_CLR_RX_UNDER_t { + CLR_RX_UNDER = false; // Read this register to clear the RX_UNDER interrupt (bit 0) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 Clear RX_UNDER Interrupt Register + register IC_CLR_RX_UNDER_t I2C0_IC_CLR_RX_UNDER at 0x40044044; + + type IC_CLR_RX_OVER_t { + CLR_RX_OVER = false; // Read this register to clear the RX_OVER interrupt (bit 1) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 Clear RX_OVER Interrupt Register + register IC_CLR_RX_OVER_t I2C0_IC_CLR_RX_OVER at 0x40044048; + + type IC_CLR_TX_OVER_t { + CLR_TX_OVER = false; // Read this register to clear the TX_OVER interrupt (bit 3) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 Clear TX_OVER Interrupt Register + register IC_CLR_TX_OVER_t I2C0_IC_CLR_TX_OVER at 0x4004404c; + + type IC_CLR_RD_REQ_t { + CLR_RD_REQ = false; // Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 Clear RD_REQ Interrupt Register + register IC_CLR_RD_REQ_t I2C0_IC_CLR_RD_REQ at 0x40044050; + + type IC_CLR_TX_ABRT_t { + CLR_TX_ABRT = false; // Read this register to clear the TX_ABRT interrupt (bit 6) of the IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also releases the TX FIFO from the flushed/reset state, allowing more writes to the TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. Reset value: 0x0 + } + + // I2C0 Clear TX_ABRT Interrupt Register + register IC_CLR_TX_ABRT_t I2C0_IC_CLR_TX_ABRT at 0x40044054; + + type IC_CLR_RX_DONE_t { + CLR_RX_DONE = false; // Read this register to clear the RX_DONE interrupt (bit 7) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 Clear RX_DONE Interrupt Register + register IC_CLR_RX_DONE_t I2C0_IC_CLR_RX_DONE at 0x40044058; + + type IC_CLR_ACTIVITY_t { + CLR_ACTIVITY = false; // Reading this register clears the ACTIVITY interrupt if the I2C is not active anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt bit continues to be set. It is automatically cleared by hardware if the module is disabled and if there is no further activity on the bus. The value read from this register to get status of the ACTIVITY interrupt (bit 8) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 Clear ACTIVITY Interrupt Register + register IC_CLR_ACTIVITY_t I2C0_IC_CLR_ACTIVITY at 0x4004405c; + + type IC_CLR_STOP_DET_t { + CLR_STOP_DET = false; // Read this register to clear the STOP_DET interrupt (bit 9) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 Clear STOP_DET Interrupt Register + register IC_CLR_STOP_DET_t I2C0_IC_CLR_STOP_DET at 0x40044060; + + type IC_CLR_START_DET_t { + CLR_START_DET = false; // Read this register to clear the START_DET interrupt (bit 10) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 Clear START_DET Interrupt Register + register IC_CLR_START_DET_t I2C0_IC_CLR_START_DET at 0x40044064; + + type IC_CLR_GEN_CALL_t { + CLR_GEN_CALL = false; // Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 Clear GEN_CALL Interrupt Register + register IC_CLR_GEN_CALL_t I2C0_IC_CLR_GEN_CALL at 0x40044068; + + type IC_ENABLE_t { + ENABLE = false; // Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable DW_apb_i2c while it is active. However, it is important that care be taken to ensure that DW_apb_i2c is disabled properly. A recommended procedure is described in 'Disabling DW_apb_i2c'. When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get flushed. - Status bits in the IC_INTR_STAT register are still active until DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well as deletes the contents of the transmit buffer after the current transfer is complete. If the module is receiving, the DW_apb_i2c stops the current transfer at the end of the current byte and does not acknowledge the transfer. In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to asynchronous (1), there is a two ic_clk delay when enabling or disabling the DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to 'Disabling DW_apb_i2c' Reset value: 0x0 + ABORT = false; // When set, the controller initiates the transfer abort. - 0: ABORT not initiated or ABORT done - 1: ABORT operation in progress The software can abort the I2C transfer in master mode by setting this bit. The software can set this bit only when ENABLE is already set; otherwise, the controller ignores any write to ABORT bit. The software cannot clear the ABORT bit once set. In response to an ABORT, the controller issues a STOP and flushes the Tx FIFO after completing the current transfer, then sets the TX_ABORT interrupt after the abort operation. The ABORT bit is cleared automatically after the abort operation. For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C Transfers'. Reset value: 0x0 + TX_CMD_BLOCK = false; // In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus automatically, as soon as the first data is available in the Tx FIFO. Note: To block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT + } + + // I2C0 I2C Enable Register + register IC_ENABLE_t I2C0_IC_ENABLE at 0x4004406c; + + type IC_STATUS_t { + ACTIVITY = false; // I2C Activity Status. Reset value: 0x0 + TFNF = false; // Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: Transmit FIFO is not full Reset value: 0x1 + TFE = false; // Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this bit is set. When it contains one or more valid entries, this bit is cleared. This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - 1: Transmit FIFO is empty Reset value: 0x1 + RFNE = false; // Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is empty - 1: Receive FIFO is not empty Reset value: 0x0 + RFF = false; // Receive FIFO Completely Full. When the receive FIFO is completely full, this bit is set. When the receive FIFO contains one or more empty location, this bit is cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: 0x0 + MST_ACTIVITY = false; // Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is the OR of SLV_ACTIVITY and MST_ACTIVITY bits. Reset value: 0x0 + SLV_ACTIVITY = false; // Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the Slave part of DW_apb_i2c is Active Reset value: 0x0 + } + + // I2C0 I2C Status Register This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt. When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 + register IC_STATUS_t I2C0_IC_STATUS at 0x40044070; + + type IC_TXFLR_t { + TXFLR = uint5(0); // Transmit FIFO Level. Contains the number of valid data entries in the transmit FIFO. Reset value: 0x0 + } + + // I2C0 I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO. + register IC_TXFLR_t I2C0_IC_TXFLR at 0x40044074; + + type IC_RXFLR_t { + RXFLR = uint5(0); // Receive FIFO Level. Contains the number of valid data entries in the receive FIFO. Reset value: 0x0 + } + + // I2C0 I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO. + register IC_RXFLR_t I2C0_IC_RXFLR at 0x40044078; + + type IC_SDA_HOLD_t { + IC_SDA_TX_HOLD = uint16(0); // Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a transmitter. Reset value: IC_DEFAULT_SDA_HOLD[15:0]. + IC_SDA_RX_HOLD = uint8(0); // Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a receiver. Reset value: IC_DEFAULT_SDA_HOLD[23:16]. + } + + // I2C0 I2C SDA Hold Time Length Register The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW). The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode. Writes to this register succeed only when IC_ENABLE[0]=0. The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented. The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles. + register IC_SDA_HOLD_t I2C0_IC_SDA_HOLD at 0x4004407c; + + type IC_TX_ABRT_SOURCE_t { + ABRT_7B_ADDR_NOACK = false; // This field indicates that the Master is in 7-bit addressing mode and the address sent was not acknowledged by any slave. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_10ADDR1_NOACK = false; // This field indicates that the Master is in 10-bit address mode and the first 10-bit address byte was not acknowledged by any slave. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_10ADDR2_NOACK = false; // This field indicates that the Master is in 10-bit address mode and that the second address byte of the 10-bit address was not acknowledged by any slave. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_TXDATA_NOACK = false; // This field indicates the master-mode only bit. When the master receives an acknowledgement for the address, but when it sends data byte(s) following the address, it did not receive an acknowledge from the remote slave(s). Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter + ABRT_GCALL_NOACK = false; // This field indicates that DW_apb_i2c in master mode has sent a General Call and no slave on the bus acknowledged the General Call. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter + ABRT_GCALL_READ = false; // This field indicates that DW_apb_i2c in the master mode has sent a General Call but the user programmed the byte following the General Call to be a read from the bus (IC_DATA_CMD[9] is set to 1). Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter + ABRT_HS_ACKDET = false; // This field indicates that the Master is in High Speed mode and the High Speed Master code was acknowledged (wrong behavior). Reset value: 0x0 Role of DW_apb_i2c: Master + ABRT_SBYTE_ACKDET = false; // This field indicates that the Master has sent a START Byte and the START Byte was acknowledged (wrong behavior). Reset value: 0x0 Role of DW_apb_i2c: Master + ABRT_HS_NORSTRT = false; // This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to use the master to transfer data in High Speed mode. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ABRT_SBYTE_NORSTRT = false; // To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 clears for one cycle and then gets reasserted. When this field is set to 1, the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to send a START Byte. Reset value: 0x0 Role of DW_apb_i2c: Master + ABRT_10B_RD_NORSTRT = false; // This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the master sends a read command in 10-bit addressing mode. Reset value: 0x0 Role of DW_apb_i2c: Master-Receiver + ABRT_MASTER_DIS = false; // This field indicates that the User tries to initiate a Master operation with the Master mode disabled. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + ARB_LOST = false; // This field specifies that the Master has lost arbitration, or if IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost arbitration. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + ABRT_SLVFLUSH_TXFIFO = false; // This field specifies that the Slave has received a read command and some data exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data in TX FIFO. Reset value: 0x0 Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLV_ARBLOST = false; // This field indicates that a Slave has lost the bus while transmitting data to a remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though the slave never 'owns' the bus, something could go wrong on the bus. This is a fail safe check. For instance, during a data transmission at the low-to-high transition of SCL, if what is on the data bus is not what is supposed to be transmitted, then DW_apb_i2c no longer own the bus. Reset value: 0x0 Role of DW_apb_i2c: Slave-Transmitter + ABRT_SLVRD_INTX = false; // 1: When the processor side responds to a slave mode request for data to be transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD register. Reset value: 0x0 Role of DW_apb_i2c: Slave-Transmitter + ABRT_USER_ABRT = false; // This is a master-mode-only bit. Master has detected the transfer abort (IC_ENABLE[1]) Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter + _res1 = uint6(0); // Reserved, 6 bits + TX_FLUSH_CNT = uint9(0); // This field indicates the number of Tx FIFO Data Commands which are flushed due to TX_ABRT interrupt. It is cleared whenever I2C is disabled. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + } + + // I2C0 I2C Transmit Abort Source Register This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted. + register IC_TX_ABRT_SOURCE_t I2C0_IC_TX_ABRT_SOURCE at 0x40044080; + + type IC_SLV_DATA_NACK_ONLY_t { + NACK = false; // Generate NACK. This NACK generation only occurs when DW_apb_i2c is a slave-receiver. If this register is set to a value of 1, it can only generate a NACK after a data byte is received; hence, the data transfer is aborted and the data received is not pushed to the receive buffer. When the register is set to a value of 0, it generates NACK/ACK, depending on normal criteria. - 1: generate NACK after data byte received - 0: generate NACK/ACK normally Reset value: 0x0 + } + + // I2C0 Generate Slave Data NACK Register The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect. A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit. + register IC_SLV_DATA_NACK_ONLY_t I2C0_IC_SLV_DATA_NACK_ONLY at 0x40044084; + + type IC_DMA_CR_t { + RDMAE = false; // Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. Reset value: 0x0 + TDMAE = false; // Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. Reset value: 0x0 + } + + // I2C0 DMA Control Register The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE. + register IC_DMA_CR_t I2C0_IC_DMA_CR at 0x40044088; + + type IC_DMA_TDLR_t { + DMATDL = uint4(0); // Transmit Data Level. This bit field controls the level at which a DMA request is made by the transmit logic. It is equal to the watermark level; that is, the dma_tx_req signal is generated when the number of valid data entries in the transmit FIFO is equal to or below this field value, and TDMAE = 1. Reset value: 0x0 + } + + // I2C0 DMA Transmit Data Level Register + register IC_DMA_TDLR_t I2C0_IC_DMA_TDLR at 0x4004408c; + + type IC_DMA_RDLR_t { + DMARDL = uint4(0); // Receive Data Level. This bit field controls the level at which a DMA request is made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req is generated when the number of valid data entries in the receive FIFO is equal to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is 0, then dma_rx_req is asserted when 1 or more data entries are present in the receive FIFO. Reset value: 0x0 + } + + // I2C0 I2C Receive Data Level Register + register IC_DMA_RDLR_t I2C0_IC_DMA_RDLR at 0x40044090; + + type IC_SDA_SETUP_t { + SDA_SETUP = uint8(0); // SDA Setup. It is recommended that if the required delay is 1000ns, then for an ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. IC_SDA_SETUP must be programmed with a minimum value of 2. + } + + // I2C0 I2C SDA Setup Register This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2. Writes to this register succeed only when IC_ENABLE[0] = 0. Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter. + register IC_SDA_SETUP_t I2C0_IC_SDA_SETUP at 0x40044094; + + type IC_ACK_GENERAL_CALL_t { + ACK_GEN_CALL = false; // ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with a NACK (by negating ic_data_oe). + } + + // I2C0 I2C ACK General Call Register The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address. This register is applicable only when the DW_apb_i2c is in slave mode. + register IC_ACK_GENERAL_CALL_t I2C0_IC_ACK_GENERAL_CALL at 0x40044098; + + type IC_ENABLE_STATUS_t { + IC_EN = false; // ic_en Status. This bit always reflects the value driven on the output port ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely read this bit anytime. When this bit is read as 0, the CPU can safely read SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1). Reset value: 0x0 + SLV_DISABLED_WHILE_BUSY = false; // Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential or active Slave operation has been aborted due to the setting bit 0 of the IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the IC_ENABLE register while: (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation from a remote master; OR, (b) address and data bytes of the Slave-Receiver operation from a remote master. When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an I2C transfer, irrespective of whether the I2C address matches the slave address set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before IC_ENABLE is set to 0 but has not taken effect. Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit will also be set to 1. When read as 0, DW_apb_i2c is deemed to have been disabled when there is master activity, or when the I2C bus is idle. Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. Reset value: 0x0 + SLV_RX_DATA_LOST = false; // Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has been aborted with at least one data byte received from an I2C transfer due to the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed to have been actively engaged in an aborted I2C transfer (with matching address) and the data phase of the I2C transfer has been entered, even though a data byte has been responded with a NACK. Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit is also set to 1. When read as 0, DW_apb_i2c is deemed to have been disabled without being actively involved in the data phase of a Slave-Receiver transfer. Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. Reset value: 0x0 + } + + // I2C0 I2C Enable Status Register The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled. If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1. If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'. Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities. + register IC_ENABLE_STATUS_t I2C0_IC_ENABLE_STATUS at 0x4004409c; + + type IC_FS_SPKLEN_t { + IC_FS_SPKLEN = uint8(0); // This register must be set before any I2C bus transaction can take place to ensure stable operation. This register sets the duration, measured in ic_clk cycles, of the longest spike in the SCL or SDA lines that will be filtered out by the spike suppression logic. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 1; hardware prevents values less than this being written, and if attempted results in 1 being set. or more information, refer to 'Spike Suppression'. + } + + // I2C0 I2C SS, FS or FM+ spike suppression limit This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1. + register IC_FS_SPKLEN_t I2C0_IC_FS_SPKLEN at 0x400440a0; + + type IC_CLR_RESTART_DET_t { + CLR_RESTART_DET = false; // Read this register to clear the RESTART_DET interrupt (bit 12) of IC_RAW_INTR_STAT register. Reset value: 0x0 + } + + // I2C0 Clear RESTART_DET Interrupt Register + register IC_CLR_RESTART_DET_t I2C0_IC_CLR_RESTART_DET at 0x400440a8; + + type IC_COMP_PARAM_1_t { + APB_DATA_WIDTH = uint2(0); // APB data bus width is 32 bits + MAX_SPEED_MODE = uint2(0); // MAX SPEED MODE = FAST MODE + HC_COUNT_VALUES = false; // Programmable count values for each mode. + INTR_IO = false; // COMBINED Interrupt outputs + HAS_DMA = false; // DMA handshaking signals are enabled + ADD_ENCODED_PARAMS = false; // Encoded parameters not visible + RX_BUFFER_DEPTH = uint8(0); // RX Buffer Depth = 16 + TX_BUFFER_DEPTH = uint8(0); // TX Buffer Depth = 16 + } + + // I2C0 Component Parameter Register 1 Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters + register IC_COMP_PARAM_1_t I2C0_IC_COMP_PARAM_1 at 0x400440f4; + + type IC_COMP_VERSION_t { + IC_COMP_VERSION = uint32(0); // + } + + // I2C0 I2C Component Version Register + register IC_COMP_VERSION_t I2C0_IC_COMP_VERSION at 0x400440f8; + + type IC_COMP_TYPE_t { + IC_COMP_TYPE = uint32(0); // Designware Component Type number = 0x44_57_01_40. This assigned unique hex value is constant and is derived from the two ASCII letters 'DW' followed by a 16-bit unsigned number. + } + + // I2C0 I2C Component Type Register + register IC_COMP_TYPE_t I2C0_IC_COMP_TYPE at 0x400440fc; + + +/* Types and registers for I2C1 */ + + // I2C1 I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only. + register IC_CON_t I2C1_IC_CON at 0x40048000; + + // I2C1 I2C Target Address Register This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0. Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only. + register IC_TAR_t I2C1_IC_TAR at 0x40048004; + + // I2C1 I2C Slave Address Register + register IC_SAR_t I2C1_IC_SAR at 0x40048008; + + // I2C1 I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO. The size of the register changes as follows: Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging. + register IC_DATA_CMD_t I2C1_IC_DATA_CMD at 0x40048010; + + // I2C1 Standard Speed I2C Clock SCL High Count Register + register IC_SS_SCL_HCNT_t I2C1_IC_SS_SCL_HCNT at 0x40048014; + + // I2C1 Standard Speed I2C Clock SCL Low Count Register + register IC_SS_SCL_LCNT_t I2C1_IC_SS_SCL_LCNT at 0x40048018; + + // I2C1 Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register + register IC_FS_SCL_HCNT_t I2C1_IC_FS_SCL_HCNT at 0x4004801c; + + // I2C1 Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register + register IC_FS_SCL_LCNT_t I2C1_IC_FS_SCL_LCNT at 0x40048020; + + // I2C1 I2C Interrupt Status Register Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. + register IC_INTR_STAT_t I2C1_IC_INTR_STAT at 0x4004802c; + + // I2C1 I2C Interrupt Mask Register. These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. + register IC_INTR_MASK_t I2C1_IC_INTR_MASK at 0x40048030; + + // I2C1 I2C Raw Interrupt Status Register Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c. + register IC_RAW_INTR_STAT_t I2C1_IC_RAW_INTR_STAT at 0x40048034; + + // I2C1 I2C Receive FIFO Threshold Register + register IC_RX_TL_t I2C1_IC_RX_TL at 0x40048038; + + // I2C1 I2C Transmit FIFO Threshold Register + register IC_TX_TL_t I2C1_IC_TX_TL at 0x4004803c; + + // I2C1 Clear Combined and Individual Interrupt Register + register IC_CLR_INTR_t I2C1_IC_CLR_INTR at 0x40048040; + + // I2C1 Clear RX_UNDER Interrupt Register + register IC_CLR_RX_UNDER_t I2C1_IC_CLR_RX_UNDER at 0x40048044; + + // I2C1 Clear RX_OVER Interrupt Register + register IC_CLR_RX_OVER_t I2C1_IC_CLR_RX_OVER at 0x40048048; + + // I2C1 Clear TX_OVER Interrupt Register + register IC_CLR_TX_OVER_t I2C1_IC_CLR_TX_OVER at 0x4004804c; + + // I2C1 Clear RD_REQ Interrupt Register + register IC_CLR_RD_REQ_t I2C1_IC_CLR_RD_REQ at 0x40048050; + + // I2C1 Clear TX_ABRT Interrupt Register + register IC_CLR_TX_ABRT_t I2C1_IC_CLR_TX_ABRT at 0x40048054; + + // I2C1 Clear RX_DONE Interrupt Register + register IC_CLR_RX_DONE_t I2C1_IC_CLR_RX_DONE at 0x40048058; + + // I2C1 Clear ACTIVITY Interrupt Register + register IC_CLR_ACTIVITY_t I2C1_IC_CLR_ACTIVITY at 0x4004805c; + + // I2C1 Clear STOP_DET Interrupt Register + register IC_CLR_STOP_DET_t I2C1_IC_CLR_STOP_DET at 0x40048060; + + // I2C1 Clear START_DET Interrupt Register + register IC_CLR_START_DET_t I2C1_IC_CLR_START_DET at 0x40048064; + + // I2C1 Clear GEN_CALL Interrupt Register + register IC_CLR_GEN_CALL_t I2C1_IC_CLR_GEN_CALL at 0x40048068; + + // I2C1 I2C Enable Register + register IC_ENABLE_t I2C1_IC_ENABLE at 0x4004806c; + + // I2C1 I2C Status Register This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt. When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 + register IC_STATUS_t I2C1_IC_STATUS at 0x40048070; + + // I2C1 I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO. + register IC_TXFLR_t I2C1_IC_TXFLR at 0x40048074; + + // I2C1 I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO. + register IC_RXFLR_t I2C1_IC_RXFLR at 0x40048078; + + // I2C1 I2C SDA Hold Time Length Register The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW). The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode. Writes to this register succeed only when IC_ENABLE[0]=0. The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented. The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles. + register IC_SDA_HOLD_t I2C1_IC_SDA_HOLD at 0x4004807c; + + // I2C1 I2C Transmit Abort Source Register This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted. + register IC_TX_ABRT_SOURCE_t I2C1_IC_TX_ABRT_SOURCE at 0x40048080; + + // I2C1 Generate Slave Data NACK Register The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect. A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit. + register IC_SLV_DATA_NACK_ONLY_t I2C1_IC_SLV_DATA_NACK_ONLY at 0x40048084; + + // I2C1 DMA Control Register The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE. + register IC_DMA_CR_t I2C1_IC_DMA_CR at 0x40048088; + + // I2C1 DMA Transmit Data Level Register + register IC_DMA_TDLR_t I2C1_IC_DMA_TDLR at 0x4004808c; + + // I2C1 I2C Receive Data Level Register + register IC_DMA_RDLR_t I2C1_IC_DMA_RDLR at 0x40048090; + + // I2C1 I2C SDA Setup Register This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2. Writes to this register succeed only when IC_ENABLE[0] = 0. Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter. + register IC_SDA_SETUP_t I2C1_IC_SDA_SETUP at 0x40048094; + + // I2C1 I2C ACK General Call Register The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address. This register is applicable only when the DW_apb_i2c is in slave mode. + register IC_ACK_GENERAL_CALL_t I2C1_IC_ACK_GENERAL_CALL at 0x40048098; + + // I2C1 I2C Enable Status Register The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled. If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1. If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'. Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities. + register IC_ENABLE_STATUS_t I2C1_IC_ENABLE_STATUS at 0x4004809c; + + // I2C1 I2C SS, FS or FM+ spike suppression limit This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1. + register IC_FS_SPKLEN_t I2C1_IC_FS_SPKLEN at 0x400480a0; + + // I2C1 Clear RESTART_DET Interrupt Register + register IC_CLR_RESTART_DET_t I2C1_IC_CLR_RESTART_DET at 0x400480a8; + + // I2C1 Component Parameter Register 1 Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters + register IC_COMP_PARAM_1_t I2C1_IC_COMP_PARAM_1 at 0x400480f4; + + // I2C1 I2C Component Version Register + register IC_COMP_VERSION_t I2C1_IC_COMP_VERSION at 0x400480f8; + + // I2C1 I2C Component Type Register + register IC_COMP_TYPE_t I2C1_IC_COMP_TYPE at 0x400480fc; + + +/* Types and registers for SPI0 */ + + type SSPCR0_t { + DSS = uint4(0); // Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. 1110 15-bit data. 1111 16-bit data. + FRF = uint2(0); // Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame format. 10 National Microwire frame format. 11 Reserved, undefined operation. + SPO = false; // SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + SPH = false; // SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + SCR = uint8(0); // Serial clock rate. The value SCR is used to generate the transmit and receive bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and SCR is a value from 0-255. + } + + // SPI0 Control register 0, SSPCR0 on page 3-4 + register SSPCR0_t SPI0_SSPCR0 at 0x4003c000; + + type SSPCR1_t { + LBM = false; // Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit serial shifter is connected to input of receive serial shifter internally. + SSE = false; // Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation enabled. + MS = false; // Master or slave mode select. This bit can be modified only when the PrimeCell SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device configured as slave. + SOD = false; // Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast a message to all slaves in the system while ensuring that only one slave drives data onto its serial output line. In such systems the RXD lines from multiple slaves could be tied together. To operate in such systems, the SOD bit can be set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD output in slave mode. + } + + // SPI0 Control register 1, SSPCR1 on page 3-5 + register SSPCR1_t SPI0_SSPCR1 at 0x4003c004; + + type SSPDR_t { + DATA = uint16(0); // Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must right-justify data when the PrimeCell SSP is programmed for a data size that is less than 16 bits. Unused bits at the top are ignored by transmit logic. The receive logic automatically right-justifies. + } + + // SPI0 Data register, SSPDR on page 3-6 + register SSPDR_t SPI0_SSPDR at 0x4003c008; + + type SSPSR_t { + TFE = false; // Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. + TNF = false; // Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not full. + RNE = false; // Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not empty. + RFF = false; // Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. + BSY = false; // PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting and/or receiving a frame or the transmit FIFO is not empty. + } + + // SPI0 Status register, SSPSR on page 3-7 + register SSPSR_t SPI0_SSPSR at 0x4003c00c; + + type SSPCPSR_t { + CPSDVSR = uint8(0); // Clock prescale divisor. Must be an even number from 2-254, depending on the frequency of SSPCLK. The least significant bit always returns zero on reads. + } + + // SPI0 Clock prescale register, SSPCPSR on page 3-8 + register SSPCPSR_t SPI0_SSPCPSR at 0x4003c010; + + type SSPIMSC_t { + RORIM = false; // Receive overrun interrupt mask: 0 Receive FIFO written to while full condition interrupt is masked. 1 Receive FIFO written to while full condition interrupt is not masked. + RTIM = false; // Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior to timeout period interrupt is not masked. + RXIM = false; // Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not masked. + TXIM = false; // Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is not masked. + } + + // SPI0 Interrupt mask set or clear register, SSPIMSC on page 3-9 + register SSPIMSC_t SPI0_SSPIMSC at 0x4003c014; + + type SSPRIS_t { + RORRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt + RTRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt + RXRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt + TXRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt + } + + // SPI0 Raw interrupt status register, SSPRIS on page 3-10 + register SSPRIS_t SPI0_SSPRIS at 0x4003c018; + + type SSPMIS_t { + RORMIS = false; // Gives the receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt + RTMIS = false; // Gives the receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt + RXMIS = false; // Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt + TXMIS = false; // Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt + } + + // SPI0 Masked interrupt status register, SSPMIS on page 3-11 + register SSPMIS_t SPI0_SSPMIS at 0x4003c01c; + + type SSPICR_t { + RORIC = false; // Clears the SSPRORINTR interrupt + RTIC = false; // Clears the SSPRTINTR interrupt + } + + // SPI0 Interrupt clear register, SSPICR on page 3-11 + register SSPICR_t SPI0_SSPICR at 0x4003c020; + + type SSPDMACR_t { + RXDMAE = false; // Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is enabled. + TXDMAE = false; // Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + } + + // SPI0 DMA control register, SSPDMACR on page 3-12 + register SSPDMACR_t SPI0_SSPDMACR at 0x4003c024; + + type SSPPERIPHID0_t { + PARTNUMBER0 = uint8(0); // These bits read back as 0x22 + } + + // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID0_t SPI0_SSPPERIPHID0 at 0x4003cfe0; + + type SSPPERIPHID1_t { + PARTNUMBER1 = uint4(0); // These bits read back as 0x0 + DESIGNER0 = uint4(0); // These bits read back as 0x1 + } + + // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID1_t SPI0_SSPPERIPHID1 at 0x4003cfe4; + + type SSPPERIPHID2_t { + DESIGNER1 = uint4(0); // These bits read back as 0x4 + REVISION = uint4(0); // These bits return the peripheral revision + } + + // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID2_t SPI0_SSPPERIPHID2 at 0x4003cfe8; + + type SSPPERIPHID3_t { + CONFIGURATION = uint8(0); // These bits read back as 0x00 + } + + // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID3_t SPI0_SSPPERIPHID3 at 0x4003cfec; + + type SSPPCELLID0_t { + SSPPCELLID0 = uint8(0); // These bits read back as 0x0D + } + + // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID0_t SPI0_SSPPCELLID0 at 0x4003cff0; + + type SSPPCELLID1_t { + SSPPCELLID1 = uint8(0); // These bits read back as 0xF0 + } + + // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID1_t SPI0_SSPPCELLID1 at 0x4003cff4; + + type SSPPCELLID2_t { + SSPPCELLID2 = uint8(0); // These bits read back as 0x05 + } + + // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID2_t SPI0_SSPPCELLID2 at 0x4003cff8; + + type SSPPCELLID3_t { + SSPPCELLID3 = uint8(0); // These bits read back as 0xB1 + } + + // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID3_t SPI0_SSPPCELLID3 at 0x4003cffc; + + +/* Types and registers for SPI1 */ + + // SPI1 Control register 0, SSPCR0 on page 3-4 + register SSPCR0_t SPI1_SSPCR0 at 0x40040000; + + // SPI1 Control register 1, SSPCR1 on page 3-5 + register SSPCR1_t SPI1_SSPCR1 at 0x40040004; + + // SPI1 Data register, SSPDR on page 3-6 + register SSPDR_t SPI1_SSPDR at 0x40040008; + + // SPI1 Status register, SSPSR on page 3-7 + register SSPSR_t SPI1_SSPSR at 0x4004000c; + + // SPI1 Clock prescale register, SSPCPSR on page 3-8 + register SSPCPSR_t SPI1_SSPCPSR at 0x40040010; + + // SPI1 Interrupt mask set or clear register, SSPIMSC on page 3-9 + register SSPIMSC_t SPI1_SSPIMSC at 0x40040014; + + // SPI1 Raw interrupt status register, SSPRIS on page 3-10 + register SSPRIS_t SPI1_SSPRIS at 0x40040018; + + // SPI1 Masked interrupt status register, SSPMIS on page 3-11 + register SSPMIS_t SPI1_SSPMIS at 0x4004001c; + + // SPI1 Interrupt clear register, SSPICR on page 3-11 + register SSPICR_t SPI1_SSPICR at 0x40040020; + + // SPI1 DMA control register, SSPDMACR on page 3-12 + register SSPDMACR_t SPI1_SSPDMACR at 0x40040024; + + // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID0_t SPI1_SSPPERIPHID0 at 0x40040fe0; + + // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID1_t SPI1_SSPPERIPHID1 at 0x40040fe4; + + // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID2_t SPI1_SSPPERIPHID2 at 0x40040fe8; + + // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + register SSPPERIPHID3_t SPI1_SSPPERIPHID3 at 0x40040fec; + + // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID0_t SPI1_SSPPCELLID0 at 0x40040ff0; + + // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID1_t SPI1_SSPPCELLID1 at 0x40040ff4; + + // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID2_t SPI1_SSPPCELLID2 at 0x40040ff8; + + // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + register SSPPCELLID3_t SPI1_SSPPCELLID3 at 0x40040ffc; + + +/* Types and registers for PIO0 + Programmable IO block + */ + + type PIO0_CTRL_t { + SM_ENABLE = uint4(0); // Enable/disable each of the four state machines by writing 1/0 to each of these four bits. When disabled, a state machine will cease executing instructions, except those written directly to SMx_INSTR by the system. Multiple bits can be set/cleared at once to run/halt multiple state machines simultaneously. + SM_RESTART = uint4(0); // Write 1 to instantly clear internal SM state which may be otherwise difficult to access and will affect future execution. Specifically, the following are cleared: input and output shift counters; the contents of the input shift register; the delay counter; the waiting-on-IRQ state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any pin write left asserted due to OUT_STICKY. The program counter, the contents of the output shift register and the X/Y scratch registers are not affected. + CLKDIV_RESTART = uint4(0); // Restart a state machine's clock divider from an initial phase of 0. Clock dividers are free-running, so once started, their output (including fractional jitter) is completely determined by the integer/fractional divisor configured in SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor are restarted simultaneously, by writing multiple 1 bits to this field, the execution clocks of those state machines will run in precise lockstep. Note that setting/clearing SM_ENABLE does not stop the clock divider from running, so once multiple state machines' clocks are synchronised, it is safe to disable/reenable a state machine, whilst keeping the clock dividers in sync. Note also that CLKDIV_RESTART can be written to whilst the state machine is running, and this is useful to resynchronise clock dividers after the divisors (SMx_CLKDIV) have been changed on-the-fly. + } + + // PIO0 PIO control register + register PIO0_CTRL_t PIO0_PIO0_CTRL at 0x50200000; + + type FSTAT_t { + RXFULL = uint4(0); // State machine RX FIFO is full + _res1 = uint4(0); // Reserved, 4 bits + RXEMPTY = uint4(0); // State machine RX FIFO is empty + _res2 = uint4(0); // Reserved, 4 bits + TXFULL = uint4(0); // State machine TX FIFO is full + _res3 = uint4(0); // Reserved, 4 bits + TXEMPTY = uint4(0); // State machine TX FIFO is empty + } + + // PIO0 FIFO status register + register FSTAT_t PIO0_FSTAT at 0x50200004; + + type FDEBUG_t { + RXSTALL = uint4(0); // State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO took place, in which case the state machine has dropped data. Write 1 to clear. + _res1 = uint4(0); // Reserved, 4 bits + RXUNDER = uint4(0); // RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to clear. Note that read-on-empty does not perturb the state of the FIFO in any way, but the data returned by reading from an empty FIFO is undefined, so this flag generally only becomes set due to some kind of software error. + _res2 = uint4(0); // Reserved, 4 bits + TXOVER = uint4(0); // TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to clear. Note that write-on-full does not alter the state or contents of the FIFO in any way, but the data that the system attempted to write is dropped, so if this flag is set, your software has quite likely dropped some data on the floor. + _res3 = uint4(0); // Reserved, 4 bits + TXSTALL = uint4(0); // State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT with autopull enabled. Write 1 to clear. + } + + // PIO0 FIFO debug register + register FDEBUG_t PIO0_FDEBUG at 0x50200008; + + type FLEVEL_t { + TX0 = uint4(0); // + RX0 = uint4(0); // + TX1 = uint4(0); // + RX1 = uint4(0); // + TX2 = uint4(0); // + RX2 = uint4(0); // + TX3 = uint4(0); // + RX3 = uint4(0); // + } + + // PIO0 FIFO levels + register FLEVEL_t PIO0_FLEVEL at 0x5020000c; + + type TXF0_t { + TXF0 = uint32(0); // + } + + // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF0_t PIO0_TXF0 at 0x50200010; + + type TXF1_t { + TXF1 = uint32(0); // + } + + // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF1_t PIO0_TXF1 at 0x50200014; + + type TXF2_t { + TXF2 = uint32(0); // + } + + // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF2_t PIO0_TXF2 at 0x50200018; + + type TXF3_t { + TXF3 = uint32(0); // + } + + // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF3_t PIO0_TXF3 at 0x5020001c; + + type RXF0_t { + RXF0 = uint32(0); // + } + + // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF0_t PIO0_RXF0 at 0x50200020; + + type RXF1_t { + RXF1 = uint32(0); // + } + + // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF1_t PIO0_RXF1 at 0x50200024; + + type RXF2_t { + RXF2 = uint32(0); // + } + + // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF2_t PIO0_RXF2 at 0x50200028; + + type RXF3_t { + RXF3 = uint32(0); // + } + + // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF3_t PIO0_RXF3 at 0x5020002c; + + type IRQ_t { + IRQ = uint8(0); // + } + + // PIO0 State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag. Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE. + register IRQ_t PIO0_IRQ at 0x50200030; + + type IRQ_FORCE_t { + IRQ_FORCE = uint8(0); // + } + + // PIO0 Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. + register IRQ_FORCE_t PIO0_IRQ_FORCE at 0x50200034; + + type INPUT_SYNC_BYPASS_t { + INPUT_SYNC_BYPASS = uint32(0); // + } + + // PIO0 There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. 0 -> input is synchronized (default) 1 -> synchronizer is bypassed If in doubt, leave this register as all zeroes. + register INPUT_SYNC_BYPASS_t PIO0_INPUT_SYNC_BYPASS at 0x50200038; + + type DBG_PADOUT_t { + DBG_PADOUT = uint32(0); // + } + + // PIO0 Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + register DBG_PADOUT_t PIO0_DBG_PADOUT at 0x5020003c; + + type DBG_PADOE_t { + DBG_PADOE = uint32(0); // + } + + // PIO0 Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + register DBG_PADOE_t PIO0_DBG_PADOE at 0x50200040; + + type DBG_CFGINFO_t { + FIFO_DEPTH = uint6(0); // The depth of the state machine TX/RX FIFOs, measured in words. Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double this depth. + _res1 = uint2(0); // Reserved, 2 bits + SM_COUNT = uint4(0); // The number of state machines this PIO instance is equipped with. + _res2 = uint4(0); // Reserved, 4 bits + IMEM_SIZE = uint6(0); // The size of the instruction memory, measured in units of one instruction + } + + // PIO0 The PIO hardware has some free parameters that may vary between chip products. These should be provided in the chip datasheet, but are also exposed here. + register DBG_CFGINFO_t PIO0_DBG_CFGINFO at 0x50200044; + + type INSTR_MEM0_t { + INSTR_MEM0 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 0 + register INSTR_MEM0_t PIO0_INSTR_MEM0 at 0x50200048; + + type INSTR_MEM1_t { + INSTR_MEM1 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 1 + register INSTR_MEM1_t PIO0_INSTR_MEM1 at 0x5020004c; + + type INSTR_MEM2_t { + INSTR_MEM2 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 2 + register INSTR_MEM2_t PIO0_INSTR_MEM2 at 0x50200050; + + type INSTR_MEM3_t { + INSTR_MEM3 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 3 + register INSTR_MEM3_t PIO0_INSTR_MEM3 at 0x50200054; + + type INSTR_MEM4_t { + INSTR_MEM4 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 4 + register INSTR_MEM4_t PIO0_INSTR_MEM4 at 0x50200058; + + type INSTR_MEM5_t { + INSTR_MEM5 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 5 + register INSTR_MEM5_t PIO0_INSTR_MEM5 at 0x5020005c; + + type INSTR_MEM6_t { + INSTR_MEM6 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 6 + register INSTR_MEM6_t PIO0_INSTR_MEM6 at 0x50200060; + + type INSTR_MEM7_t { + INSTR_MEM7 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 7 + register INSTR_MEM7_t PIO0_INSTR_MEM7 at 0x50200064; + + type INSTR_MEM8_t { + INSTR_MEM8 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 8 + register INSTR_MEM8_t PIO0_INSTR_MEM8 at 0x50200068; + + type INSTR_MEM9_t { + INSTR_MEM9 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 9 + register INSTR_MEM9_t PIO0_INSTR_MEM9 at 0x5020006c; + + type INSTR_MEM10_t { + INSTR_MEM10 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 10 + register INSTR_MEM10_t PIO0_INSTR_MEM10 at 0x50200070; + + type INSTR_MEM11_t { + INSTR_MEM11 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 11 + register INSTR_MEM11_t PIO0_INSTR_MEM11 at 0x50200074; + + type INSTR_MEM12_t { + INSTR_MEM12 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 12 + register INSTR_MEM12_t PIO0_INSTR_MEM12 at 0x50200078; + + type INSTR_MEM13_t { + INSTR_MEM13 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 13 + register INSTR_MEM13_t PIO0_INSTR_MEM13 at 0x5020007c; + + type INSTR_MEM14_t { + INSTR_MEM14 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 14 + register INSTR_MEM14_t PIO0_INSTR_MEM14 at 0x50200080; + + type INSTR_MEM15_t { + INSTR_MEM15 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 15 + register INSTR_MEM15_t PIO0_INSTR_MEM15 at 0x50200084; + + type INSTR_MEM16_t { + INSTR_MEM16 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 16 + register INSTR_MEM16_t PIO0_INSTR_MEM16 at 0x50200088; + + type INSTR_MEM17_t { + INSTR_MEM17 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 17 + register INSTR_MEM17_t PIO0_INSTR_MEM17 at 0x5020008c; + + type INSTR_MEM18_t { + INSTR_MEM18 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 18 + register INSTR_MEM18_t PIO0_INSTR_MEM18 at 0x50200090; + + type INSTR_MEM19_t { + INSTR_MEM19 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 19 + register INSTR_MEM19_t PIO0_INSTR_MEM19 at 0x50200094; + + type INSTR_MEM20_t { + INSTR_MEM20 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 20 + register INSTR_MEM20_t PIO0_INSTR_MEM20 at 0x50200098; + + type INSTR_MEM21_t { + INSTR_MEM21 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 21 + register INSTR_MEM21_t PIO0_INSTR_MEM21 at 0x5020009c; + + type INSTR_MEM22_t { + INSTR_MEM22 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 22 + register INSTR_MEM22_t PIO0_INSTR_MEM22 at 0x502000a0; + + type INSTR_MEM23_t { + INSTR_MEM23 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 23 + register INSTR_MEM23_t PIO0_INSTR_MEM23 at 0x502000a4; + + type INSTR_MEM24_t { + INSTR_MEM24 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 24 + register INSTR_MEM24_t PIO0_INSTR_MEM24 at 0x502000a8; + + type INSTR_MEM25_t { + INSTR_MEM25 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 25 + register INSTR_MEM25_t PIO0_INSTR_MEM25 at 0x502000ac; + + type INSTR_MEM26_t { + INSTR_MEM26 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 26 + register INSTR_MEM26_t PIO0_INSTR_MEM26 at 0x502000b0; + + type INSTR_MEM27_t { + INSTR_MEM27 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 27 + register INSTR_MEM27_t PIO0_INSTR_MEM27 at 0x502000b4; + + type INSTR_MEM28_t { + INSTR_MEM28 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 28 + register INSTR_MEM28_t PIO0_INSTR_MEM28 at 0x502000b8; + + type INSTR_MEM29_t { + INSTR_MEM29 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 29 + register INSTR_MEM29_t PIO0_INSTR_MEM29 at 0x502000bc; + + type INSTR_MEM30_t { + INSTR_MEM30 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 30 + register INSTR_MEM30_t PIO0_INSTR_MEM30 at 0x502000c0; + + type INSTR_MEM31_t { + INSTR_MEM31 = uint16(0); // + } + + // PIO0 Write-only access to instruction memory location 31 + register INSTR_MEM31_t PIO0_INSTR_MEM31 at 0x502000c4; + + type SM0_CLKDIV_t { + _res1 = uint8(0); // Reserved, 8 bits + FRAC = uint8(0); // Fractional part of clock divisor + INT = uint16(0); // Effective frequency is sysclk/(int + frac/256). Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + } + + // PIO0 Clock divisor register for state machine 0 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM0_CLKDIV_t PIO0_SM0_CLKDIV at 0x502000c8; + + type SM0_EXECCTRL_t { + STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction + STATUS_SEL = false; // Comparison used for the MOV x, STATUS instruction. + _res1 = uint2(0); // Reserved, 2 bits + WRAP_BOTTOM = uint5(0); // After reaching wrap_top, execution is wrapped to this address. + WRAP_TOP = uint5(0); // After reaching this address, execution is wrapped to wrap_bottom. If the instruction is a jump, and the jump condition is true, the jump takes priority. + OUT_STICKY = false; // Continuously assert the most recent OUT/SET to the pins + INLINE_OUT_EN = false; // If 1, use a bit of OUT data as an auxiliary write enable When used in conjunction with OUT_STICKY, writes with an enable of 0 will deassert the latest pin write. This can create useful masking/override behaviour due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + OUT_EN_SEL = uint5(0); // Which data bit to use for inline OUT enable + JMP_PIN = uint5(0); // The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + SIDE_PINDIR = false; // If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_EN = false; // If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + EXEC_STALLED = false; // If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + } + + // PIO0 Execution/behavioural settings for state machine 0 + register SM0_EXECCTRL_t PIO0_SM0_EXECCTRL at 0x502000cc; + + type SM0_SHIFTCTRL_t { + _res1 = uint16(0); // Reserved, 16 bits + AUTOPUSH = false; // Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPULL = false; // Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + IN_SHIFTDIR = false; // 1 = shift input shift register to right (data enters from left). 0 = to left. + OUT_SHIFTDIR = false; // 1 = shift out of output shift register to right. 0 = to left. + PUSH_THRESH = uint5(0); // Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. Write 0 for value of 32. + PULL_THRESH = uint5(0); // Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. Write 0 for value of 32. + FJOIN_TX = false; // When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. RX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + FJOIN_RX = false; // When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. TX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + } + + // PIO0 Control behaviour of the input/output shift registers for state machine 0 + register SM0_SHIFTCTRL_t PIO0_SM0_SHIFTCTRL at 0x502000d0; + + type SM0_ADDR_t { + SM0_ADDR = uint5(0); // + } + + // PIO0 Current instruction address of state machine 0 + register SM0_ADDR_t PIO0_SM0_ADDR at 0x502000d4; + + type SM0_INSTR_t { + SM0_INSTR = uint16(0); // + } + + // PIO0 Read to see the instruction currently addressed by state machine 0's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM0_INSTR_t PIO0_SM0_INSTR at 0x502000d8; + + type SM0_PINCTRL_t { + OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + SET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SIDESET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + IN_BASE = uint5(0); // The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + OUT_COUNT = uint6(0); // The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + SET_COUNT = uint3(0); // The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SIDESET_COUNT = uint3(0); // The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + } + + // PIO0 State machine pin control + register SM0_PINCTRL_t PIO0_SM0_PINCTRL at 0x502000dc; + + type SM1_CLKDIV_t { + _res1 = uint8(0); // Reserved, 8 bits + FRAC = uint8(0); // Fractional part of clock divisor + INT = uint16(0); // Effective frequency is sysclk/(int + frac/256). Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + } + + // PIO0 Clock divisor register for state machine 1 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM1_CLKDIV_t PIO0_SM1_CLKDIV at 0x502000e0; + + type SM1_EXECCTRL_t { + STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction + STATUS_SEL = false; // Comparison used for the MOV x, STATUS instruction. + _res1 = uint2(0); // Reserved, 2 bits + WRAP_BOTTOM = uint5(0); // After reaching wrap_top, execution is wrapped to this address. + WRAP_TOP = uint5(0); // After reaching this address, execution is wrapped to wrap_bottom. If the instruction is a jump, and the jump condition is true, the jump takes priority. + OUT_STICKY = false; // Continuously assert the most recent OUT/SET to the pins + INLINE_OUT_EN = false; // If 1, use a bit of OUT data as an auxiliary write enable When used in conjunction with OUT_STICKY, writes with an enable of 0 will deassert the latest pin write. This can create useful masking/override behaviour due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + OUT_EN_SEL = uint5(0); // Which data bit to use for inline OUT enable + JMP_PIN = uint5(0); // The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + SIDE_PINDIR = false; // If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_EN = false; // If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + EXEC_STALLED = false; // If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + } + + // PIO0 Execution/behavioural settings for state machine 1 + register SM1_EXECCTRL_t PIO0_SM1_EXECCTRL at 0x502000e4; + + type SM1_SHIFTCTRL_t { + _res1 = uint16(0); // Reserved, 16 bits + AUTOPUSH = false; // Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPULL = false; // Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + IN_SHIFTDIR = false; // 1 = shift input shift register to right (data enters from left). 0 = to left. + OUT_SHIFTDIR = false; // 1 = shift out of output shift register to right. 0 = to left. + PUSH_THRESH = uint5(0); // Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. Write 0 for value of 32. + PULL_THRESH = uint5(0); // Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. Write 0 for value of 32. + FJOIN_TX = false; // When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. RX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + FJOIN_RX = false; // When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. TX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + } + + // PIO0 Control behaviour of the input/output shift registers for state machine 1 + register SM1_SHIFTCTRL_t PIO0_SM1_SHIFTCTRL at 0x502000e8; + + type SM1_ADDR_t { + SM1_ADDR = uint5(0); // + } + + // PIO0 Current instruction address of state machine 1 + register SM1_ADDR_t PIO0_SM1_ADDR at 0x502000ec; + + type SM1_INSTR_t { + SM1_INSTR = uint16(0); // + } + + // PIO0 Read to see the instruction currently addressed by state machine 1's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM1_INSTR_t PIO0_SM1_INSTR at 0x502000f0; + + type SM1_PINCTRL_t { + OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + SET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SIDESET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + IN_BASE = uint5(0); // The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + OUT_COUNT = uint6(0); // The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + SET_COUNT = uint3(0); // The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SIDESET_COUNT = uint3(0); // The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + } + + // PIO0 State machine pin control + register SM1_PINCTRL_t PIO0_SM1_PINCTRL at 0x502000f4; + + type SM2_CLKDIV_t { + _res1 = uint8(0); // Reserved, 8 bits + FRAC = uint8(0); // Fractional part of clock divisor + INT = uint16(0); // Effective frequency is sysclk/(int + frac/256). Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + } + + // PIO0 Clock divisor register for state machine 2 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM2_CLKDIV_t PIO0_SM2_CLKDIV at 0x502000f8; + + type SM2_EXECCTRL_t { + STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction + STATUS_SEL = false; // Comparison used for the MOV x, STATUS instruction. + _res1 = uint2(0); // Reserved, 2 bits + WRAP_BOTTOM = uint5(0); // After reaching wrap_top, execution is wrapped to this address. + WRAP_TOP = uint5(0); // After reaching this address, execution is wrapped to wrap_bottom. If the instruction is a jump, and the jump condition is true, the jump takes priority. + OUT_STICKY = false; // Continuously assert the most recent OUT/SET to the pins + INLINE_OUT_EN = false; // If 1, use a bit of OUT data as an auxiliary write enable When used in conjunction with OUT_STICKY, writes with an enable of 0 will deassert the latest pin write. This can create useful masking/override behaviour due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + OUT_EN_SEL = uint5(0); // Which data bit to use for inline OUT enable + JMP_PIN = uint5(0); // The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + SIDE_PINDIR = false; // If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_EN = false; // If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + EXEC_STALLED = false; // If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + } + + // PIO0 Execution/behavioural settings for state machine 2 + register SM2_EXECCTRL_t PIO0_SM2_EXECCTRL at 0x502000fc; + + type SM2_SHIFTCTRL_t { + _res1 = uint16(0); // Reserved, 16 bits + AUTOPUSH = false; // Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPULL = false; // Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + IN_SHIFTDIR = false; // 1 = shift input shift register to right (data enters from left). 0 = to left. + OUT_SHIFTDIR = false; // 1 = shift out of output shift register to right. 0 = to left. + PUSH_THRESH = uint5(0); // Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. Write 0 for value of 32. + PULL_THRESH = uint5(0); // Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. Write 0 for value of 32. + FJOIN_TX = false; // When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. RX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + FJOIN_RX = false; // When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. TX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + } + + // PIO0 Control behaviour of the input/output shift registers for state machine 2 + register SM2_SHIFTCTRL_t PIO0_SM2_SHIFTCTRL at 0x50200100; + + type SM2_ADDR_t { + SM2_ADDR = uint5(0); // + } + + // PIO0 Current instruction address of state machine 2 + register SM2_ADDR_t PIO0_SM2_ADDR at 0x50200104; + + type SM2_INSTR_t { + SM2_INSTR = uint16(0); // + } + + // PIO0 Read to see the instruction currently addressed by state machine 2's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM2_INSTR_t PIO0_SM2_INSTR at 0x50200108; + + type SM2_PINCTRL_t { + OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + SET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SIDESET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + IN_BASE = uint5(0); // The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + OUT_COUNT = uint6(0); // The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + SET_COUNT = uint3(0); // The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SIDESET_COUNT = uint3(0); // The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + } + + // PIO0 State machine pin control + register SM2_PINCTRL_t PIO0_SM2_PINCTRL at 0x5020010c; + + type SM3_CLKDIV_t { + _res1 = uint8(0); // Reserved, 8 bits + FRAC = uint8(0); // Fractional part of clock divisor + INT = uint16(0); // Effective frequency is sysclk/(int + frac/256). Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + } + + // PIO0 Clock divisor register for state machine 3 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM3_CLKDIV_t PIO0_SM3_CLKDIV at 0x50200110; + + type SM3_EXECCTRL_t { + STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction + STATUS_SEL = false; // Comparison used for the MOV x, STATUS instruction. + _res1 = uint2(0); // Reserved, 2 bits + WRAP_BOTTOM = uint5(0); // After reaching wrap_top, execution is wrapped to this address. + WRAP_TOP = uint5(0); // After reaching this address, execution is wrapped to wrap_bottom. If the instruction is a jump, and the jump condition is true, the jump takes priority. + OUT_STICKY = false; // Continuously assert the most recent OUT/SET to the pins + INLINE_OUT_EN = false; // If 1, use a bit of OUT data as an auxiliary write enable When used in conjunction with OUT_STICKY, writes with an enable of 0 will deassert the latest pin write. This can create useful masking/override behaviour due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + OUT_EN_SEL = uint5(0); // Which data bit to use for inline OUT enable + JMP_PIN = uint5(0); // The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + SIDE_PINDIR = false; // If 1, side-set data is asserted to pin directions, instead of pin values + SIDE_EN = false; // If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + EXEC_STALLED = false; // If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + } + + // PIO0 Execution/behavioural settings for state machine 3 + register SM3_EXECCTRL_t PIO0_SM3_EXECCTRL at 0x50200114; + + type SM3_SHIFTCTRL_t { + _res1 = uint16(0); // Reserved, 16 bits + AUTOPUSH = false; // Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + AUTOPULL = false; // Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + IN_SHIFTDIR = false; // 1 = shift input shift register to right (data enters from left). 0 = to left. + OUT_SHIFTDIR = false; // 1 = shift out of output shift register to right. 0 = to left. + PUSH_THRESH = uint5(0); // Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. Write 0 for value of 32. + PULL_THRESH = uint5(0); // Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. Write 0 for value of 32. + FJOIN_TX = false; // When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. RX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + FJOIN_RX = false; // When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. TX FIFO is disabled as a result (always reads as both full and empty). FIFOs are flushed when this bit is changed. + } + + // PIO0 Control behaviour of the input/output shift registers for state machine 3 + register SM3_SHIFTCTRL_t PIO0_SM3_SHIFTCTRL at 0x50200118; + + type SM3_ADDR_t { + SM3_ADDR = uint5(0); // + } + + // PIO0 Current instruction address of state machine 3 + register SM3_ADDR_t PIO0_SM3_ADDR at 0x5020011c; + + type SM3_INSTR_t { + SM3_INSTR = uint16(0); // + } + + // PIO0 Read to see the instruction currently addressed by state machine 3's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM3_INSTR_t PIO0_SM3_INSTR at 0x50200120; + + type SM3_PINCTRL_t { + OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + SET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + SIDESET_BASE = uint5(0); // The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + IN_BASE = uint5(0); // The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + OUT_COUNT = uint6(0); // The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + SET_COUNT = uint3(0); // The number of pins asserted by a SET. In the range 0 to 5 inclusive. + SIDESET_COUNT = uint3(0); // The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + } + + // PIO0 State machine pin control + register SM3_PINCTRL_t PIO0_SM3_PINCTRL at 0x50200124; + + type PIO0_INTR_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + } + + // PIO0 Raw Interrupts + register PIO0_INTR_t PIO0_PIO0_INTR at 0x50200128; + + type IRQ0_INTE_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + } + + // PIO0 Interrupt Enable for irq0 + register IRQ0_INTE_t PIO0_IRQ0_INTE at 0x5020012c; + + type IRQ0_INTF_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + } + + // PIO0 Interrupt Force for irq0 + register IRQ0_INTF_t PIO0_IRQ0_INTF at 0x50200130; + + type IRQ0_INTS_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + } + + // PIO0 Interrupt status after masking & forcing for irq0 + register IRQ0_INTS_t PIO0_IRQ0_INTS at 0x50200134; + + type IRQ1_INTE_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + } + + // PIO0 Interrupt Enable for irq1 + register IRQ1_INTE_t PIO0_IRQ1_INTE at 0x50200138; + + type IRQ1_INTF_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + } + + // PIO0 Interrupt Force for irq1 + register IRQ1_INTF_t PIO0_IRQ1_INTF at 0x5020013c; + + type IRQ1_INTS_t { + SM0_RXNEMPTY = false; // + SM1_RXNEMPTY = false; // + SM2_RXNEMPTY = false; // + SM3_RXNEMPTY = false; // + SM0_TXNFULL = false; // + SM1_TXNFULL = false; // + SM2_TXNFULL = false; // + SM3_TXNFULL = false; // + SM0 = false; // + SM1 = false; // + SM2 = false; // + SM3 = false; // + } + + // PIO0 Interrupt status after masking & forcing for irq1 + register IRQ1_INTS_t PIO0_IRQ1_INTS at 0x50200140; + + +/* Types and registers for PIO1 */ + + // PIO1 PIO control register + register PIO0_CTRL_t PIO1_CTRL at 0x50300000; + + // PIO1 FIFO status register + register FSTAT_t PIO1_FSTAT at 0x50300004; + + // PIO1 FIFO debug register + register FDEBUG_t PIO1_FDEBUG at 0x50300008; + + // PIO1 FIFO levels + register FLEVEL_t PIO1_FLEVEL at 0x5030000c; + + // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF0_t PIO1_TXF0 at 0x50300010; + + // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF1_t PIO1_TXF1 at 0x50300014; + + // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF2_t PIO1_TXF2 at 0x50300018; + + // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + register TXF3_t PIO1_TXF3 at 0x5030001c; + + // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF0_t PIO1_RXF0 at 0x50300020; + + // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF1_t PIO1_RXF1 at 0x50300024; + + // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF2_t PIO1_RXF2 at 0x50300028; + + // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + register RXF3_t PIO1_RXF3 at 0x5030002c; + + // PIO1 State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag. Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE. + register IRQ_t PIO1_IRQ at 0x50300030; + + // PIO1 Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. + register IRQ_FORCE_t PIO1_IRQ_FORCE at 0x50300034; + + // PIO1 There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. 0 -> input is synchronized (default) 1 -> synchronizer is bypassed If in doubt, leave this register as all zeroes. + register INPUT_SYNC_BYPASS_t PIO1_INPUT_SYNC_BYPASS at 0x50300038; + + // PIO1 Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + register DBG_PADOUT_t PIO1_DBG_PADOUT at 0x5030003c; + + // PIO1 Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + register DBG_PADOE_t PIO1_DBG_PADOE at 0x50300040; + + // PIO1 The PIO hardware has some free parameters that may vary between chip products. These should be provided in the chip datasheet, but are also exposed here. + register DBG_CFGINFO_t PIO1_DBG_CFGINFO at 0x50300044; + + // PIO1 Write-only access to instruction memory location 0 + register INSTR_MEM0_t PIO1_INSTR_MEM0 at 0x50300048; + + // PIO1 Write-only access to instruction memory location 1 + register INSTR_MEM1_t PIO1_INSTR_MEM1 at 0x5030004c; + + // PIO1 Write-only access to instruction memory location 2 + register INSTR_MEM2_t PIO1_INSTR_MEM2 at 0x50300050; + + // PIO1 Write-only access to instruction memory location 3 + register INSTR_MEM3_t PIO1_INSTR_MEM3 at 0x50300054; + + // PIO1 Write-only access to instruction memory location 4 + register INSTR_MEM4_t PIO1_INSTR_MEM4 at 0x50300058; + + // PIO1 Write-only access to instruction memory location 5 + register INSTR_MEM5_t PIO1_INSTR_MEM5 at 0x5030005c; + + // PIO1 Write-only access to instruction memory location 6 + register INSTR_MEM6_t PIO1_INSTR_MEM6 at 0x50300060; + + // PIO1 Write-only access to instruction memory location 7 + register INSTR_MEM7_t PIO1_INSTR_MEM7 at 0x50300064; + + // PIO1 Write-only access to instruction memory location 8 + register INSTR_MEM8_t PIO1_INSTR_MEM8 at 0x50300068; + + // PIO1 Write-only access to instruction memory location 9 + register INSTR_MEM9_t PIO1_INSTR_MEM9 at 0x5030006c; + + // PIO1 Write-only access to instruction memory location 10 + register INSTR_MEM10_t PIO1_INSTR_MEM10 at 0x50300070; + + // PIO1 Write-only access to instruction memory location 11 + register INSTR_MEM11_t PIO1_INSTR_MEM11 at 0x50300074; + + // PIO1 Write-only access to instruction memory location 12 + register INSTR_MEM12_t PIO1_INSTR_MEM12 at 0x50300078; + + // PIO1 Write-only access to instruction memory location 13 + register INSTR_MEM13_t PIO1_INSTR_MEM13 at 0x5030007c; + + // PIO1 Write-only access to instruction memory location 14 + register INSTR_MEM14_t PIO1_INSTR_MEM14 at 0x50300080; + + // PIO1 Write-only access to instruction memory location 15 + register INSTR_MEM15_t PIO1_INSTR_MEM15 at 0x50300084; + + // PIO1 Write-only access to instruction memory location 16 + register INSTR_MEM16_t PIO1_INSTR_MEM16 at 0x50300088; + + // PIO1 Write-only access to instruction memory location 17 + register INSTR_MEM17_t PIO1_INSTR_MEM17 at 0x5030008c; + + // PIO1 Write-only access to instruction memory location 18 + register INSTR_MEM18_t PIO1_INSTR_MEM18 at 0x50300090; + + // PIO1 Write-only access to instruction memory location 19 + register INSTR_MEM19_t PIO1_INSTR_MEM19 at 0x50300094; + + // PIO1 Write-only access to instruction memory location 20 + register INSTR_MEM20_t PIO1_INSTR_MEM20 at 0x50300098; + + // PIO1 Write-only access to instruction memory location 21 + register INSTR_MEM21_t PIO1_INSTR_MEM21 at 0x5030009c; + + // PIO1 Write-only access to instruction memory location 22 + register INSTR_MEM22_t PIO1_INSTR_MEM22 at 0x503000a0; + + // PIO1 Write-only access to instruction memory location 23 + register INSTR_MEM23_t PIO1_INSTR_MEM23 at 0x503000a4; + + // PIO1 Write-only access to instruction memory location 24 + register INSTR_MEM24_t PIO1_INSTR_MEM24 at 0x503000a8; + + // PIO1 Write-only access to instruction memory location 25 + register INSTR_MEM25_t PIO1_INSTR_MEM25 at 0x503000ac; + + // PIO1 Write-only access to instruction memory location 26 + register INSTR_MEM26_t PIO1_INSTR_MEM26 at 0x503000b0; + + // PIO1 Write-only access to instruction memory location 27 + register INSTR_MEM27_t PIO1_INSTR_MEM27 at 0x503000b4; + + // PIO1 Write-only access to instruction memory location 28 + register INSTR_MEM28_t PIO1_INSTR_MEM28 at 0x503000b8; + + // PIO1 Write-only access to instruction memory location 29 + register INSTR_MEM29_t PIO1_INSTR_MEM29 at 0x503000bc; + + // PIO1 Write-only access to instruction memory location 30 + register INSTR_MEM30_t PIO1_INSTR_MEM30 at 0x503000c0; + + // PIO1 Write-only access to instruction memory location 31 + register INSTR_MEM31_t PIO1_INSTR_MEM31 at 0x503000c4; + + // PIO1 Clock divisor register for state machine 0 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM0_CLKDIV_t PIO1_SM0_CLKDIV at 0x503000c8; + + // PIO1 Execution/behavioural settings for state machine 0 + register SM0_EXECCTRL_t PIO1_SM0_EXECCTRL at 0x503000cc; + + // PIO1 Control behaviour of the input/output shift registers for state machine 0 + register SM0_SHIFTCTRL_t PIO1_SM0_SHIFTCTRL at 0x503000d0; + + // PIO1 Current instruction address of state machine 0 + register SM0_ADDR_t PIO1_SM0_ADDR at 0x503000d4; + + // PIO1 Read to see the instruction currently addressed by state machine 0's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM0_INSTR_t PIO1_SM0_INSTR at 0x503000d8; + + // PIO1 State machine pin control + register SM0_PINCTRL_t PIO1_SM0_PINCTRL at 0x503000dc; + + // PIO1 Clock divisor register for state machine 1 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM1_CLKDIV_t PIO1_SM1_CLKDIV at 0x503000e0; + + // PIO1 Execution/behavioural settings for state machine 1 + register SM1_EXECCTRL_t PIO1_SM1_EXECCTRL at 0x503000e4; + + // PIO1 Control behaviour of the input/output shift registers for state machine 1 + register SM1_SHIFTCTRL_t PIO1_SM1_SHIFTCTRL at 0x503000e8; + + // PIO1 Current instruction address of state machine 1 + register SM1_ADDR_t PIO1_SM1_ADDR at 0x503000ec; + + // PIO1 Read to see the instruction currently addressed by state machine 1's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM1_INSTR_t PIO1_SM1_INSTR at 0x503000f0; + + // PIO1 State machine pin control + register SM1_PINCTRL_t PIO1_SM1_PINCTRL at 0x503000f4; + + // PIO1 Clock divisor register for state machine 2 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM2_CLKDIV_t PIO1_SM2_CLKDIV at 0x503000f8; + + // PIO1 Execution/behavioural settings for state machine 2 + register SM2_EXECCTRL_t PIO1_SM2_EXECCTRL at 0x503000fc; + + // PIO1 Control behaviour of the input/output shift registers for state machine 2 + register SM2_SHIFTCTRL_t PIO1_SM2_SHIFTCTRL at 0x50300100; + + // PIO1 Current instruction address of state machine 2 + register SM2_ADDR_t PIO1_SM2_ADDR at 0x50300104; + + // PIO1 Read to see the instruction currently addressed by state machine 2's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM2_INSTR_t PIO1_SM2_INSTR at 0x50300108; + + // PIO1 State machine pin control + register SM2_PINCTRL_t PIO1_SM2_PINCTRL at 0x5030010c; + + // PIO1 Clock divisor register for state machine 3 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + register SM3_CLKDIV_t PIO1_SM3_CLKDIV at 0x50300110; + + // PIO1 Execution/behavioural settings for state machine 3 + register SM3_EXECCTRL_t PIO1_SM3_EXECCTRL at 0x50300114; + + // PIO1 Control behaviour of the input/output shift registers for state machine 3 + register SM3_SHIFTCTRL_t PIO1_SM3_SHIFTCTRL at 0x50300118; + + // PIO1 Current instruction address of state machine 3 + register SM3_ADDR_t PIO1_SM3_ADDR at 0x5030011c; + + // PIO1 Read to see the instruction currently addressed by state machine 3's program counter Write to execute an instruction immediately (including jumps) and then resume execution. + register SM3_INSTR_t PIO1_SM3_INSTR at 0x50300120; + + // PIO1 State machine pin control + register SM3_PINCTRL_t PIO1_SM3_PINCTRL at 0x50300124; + + // PIO1 Raw Interrupts + register PIO0_INTR_t PIO1_INTR at 0x50300128; + + // PIO1 Interrupt Enable for irq0 + register IRQ0_INTE_t PIO1_IRQ0_INTE at 0x5030012c; + + // PIO1 Interrupt Force for irq0 + register IRQ0_INTF_t PIO1_IRQ0_INTF at 0x50300130; + + // PIO1 Interrupt status after masking & forcing for irq0 + register IRQ0_INTS_t PIO1_IRQ0_INTS at 0x50300134; + + // PIO1 Interrupt Enable for irq1 + register IRQ1_INTE_t PIO1_IRQ1_INTE at 0x50300138; + + // PIO1 Interrupt Force for irq1 + register IRQ1_INTF_t PIO1_IRQ1_INTF at 0x5030013c; + + // PIO1 Interrupt status after masking & forcing for irq1 + register IRQ1_INTS_t PIO1_IRQ1_INTS at 0x50300140; + + +/* Types and registers for BUSCTRL + Register block for busfabric control signals and performance counters + */ + + type BUS_PRIORITY_t { + PROC0 = false; // 0 - low priority, 1 - high priority + _res1 = uint3(0); // Reserved, 3 bits + PROC1 = false; // 0 - low priority, 1 - high priority + _res2 = uint3(0); // Reserved, 3 bits + DMA_R = false; // 0 - low priority, 1 - high priority + _res3 = uint3(0); // Reserved, 3 bits + DMA_W = false; // 0 - low priority, 1 - high priority + } + + // Set the priority of each master for bus arbitration. + register BUS_PRIORITY_t BUS_PRIORITY at 0x40030000; + + type BUS_PRIORITY_ACK_t { + BUS_PRIORITY_ACK = false; // Goes to 1 once all arbiters have registered the new global priority levels. Arbiters update their local priority when servicing a new nonsequential access. In normal circumstances this will happen almost immediately. + } + + // Bus priority acknowledge + register BUS_PRIORITY_ACK_t BUS_PRIORITY_ACK at 0x40030004; + + type PERFCTR0_t { + PERFCTR0 = uint24(0); // Busfabric saturating performance counter 0 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL0 + } + + // Bus fabric performance counter 0 + register PERFCTR0_t PERFCTR0 at 0x40030008; + + type PERFSEL0_t { + PERFSEL0 = uint5(0); // Select an event for PERFCTR0. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + } + + // Bus fabric performance event select for PERFCTR0 + register PERFSEL0_t PERFSEL0 at 0x4003000c; + + type PERFCTR1_t { + PERFCTR1 = uint24(0); // Busfabric saturating performance counter 1 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL1 + } + + // Bus fabric performance counter 1 + register PERFCTR1_t PERFCTR1 at 0x40030010; + + type PERFSEL1_t { + PERFSEL1 = uint5(0); // Select an event for PERFCTR1. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + } + + // Bus fabric performance event select for PERFCTR1 + register PERFSEL1_t PERFSEL1 at 0x40030014; + + type PERFCTR2_t { + PERFCTR2 = uint24(0); // Busfabric saturating performance counter 2 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL2 + } + + // Bus fabric performance counter 2 + register PERFCTR2_t PERFCTR2 at 0x40030018; + + type PERFSEL2_t { + PERFSEL2 = uint5(0); // Select an event for PERFCTR2. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + } + + // Bus fabric performance event select for PERFCTR2 + register PERFSEL2_t PERFSEL2 at 0x4003001c; + + type PERFCTR3_t { + PERFCTR3 = uint24(0); // Busfabric saturating performance counter 3 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL3 + } + + // Bus fabric performance counter 3 + register PERFCTR3_t PERFCTR3 at 0x40030020; + + type PERFSEL3_t { + PERFSEL3 = uint5(0); // Select an event for PERFCTR3. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + } + + // Bus fabric performance event select for PERFCTR3 + register PERFSEL3_t PERFSEL3 at 0x40030024; + + +/* Types and registers for SIO + Single-cycle IO block Provides core-local and inter-core hardware for the two processors, with single-cycle access. + */ + + type SIO_CPUID_t { + CPUID = uint32(0); // Value is 0 when read from processor core 0, and 1 when read from processor core 1. + } + + // Processor core identifier + register SIO_CPUID_t SIO_CPUID at 0xd0000000; + + type GPIO_IN_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // Input value for GPIO pins + register GPIO_IN_t GPIO_IN at 0xd0000004; + + type GPIO_HI_IN_t { + GPIO_HI_IN = uint6(0); // Input value on QSPI IO in order 0..5: SCLK, SSn, SD0, SD1, SD2, SD3 + } + + // Input value for QSPI pins + register GPIO_HI_IN_t GPIO_HI_IN at 0xd0000008; + + type GPIO_OUT_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output value: Set output level (1/0 -> high/low) for GPIO0...29. Reading back gives the last value written, NOT the input value from the pins. If core 0 and core 1 both write to GPIO_OUT simultaneously (or to a SET/CLR/XOR alias), the result is as though the write from core 0 took place first, and the write from core 1 was then applied to that intermediate result. + register GPIO_OUT_t GPIO_OUT at 0xd0000010; + + type GPIO_OUT_SET_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output value set: Perform an atomic bit-set on GPIO_OUT, i.e. `GPIO_OUT |= wdata` + register GPIO_OUT_SET_t GPIO_OUT_SET at 0xd0000014; + + type GPIO_OUT_CLR_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output value clear + register GPIO_OUT_CLR_t GPIO_OUT_CLR at 0xd0000018; + + type GPIO_OUT_XOR_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output value XOR + register GPIO_OUT_XOR_t GPIO_OUT_XOR at 0xd000001c; + + type GPIO_OE_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output enable: Set output enable (1/0 -> output/input) for GPIO0...29. + register GPIO_OE_t GPIO_OE at 0xd0000020; + + type GPIO_OE_SET_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output enable set: Perform an atomic bit-set on GPIO_OE, i.e. `GPIO_OE |= wdata` + register GPIO_OE_SET_t GPIO_OE_SET at 0xd0000024; + + type GPIO_OE_CLR_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output enable clear: Perform an atomic bit-clear on GPIO_OE, i.e. `GPIO_OE &= ~wdata` + register GPIO_OE_CLR_t GPIO_OE_CLR at 0xd0000028; + + type GPIO_OE_XOR_t { + IO0 = false; // + IO1 = false; // + IO2 = false; // + IO3 = false; // + IO4 = false; // + IO5 = false; // + IO6 = false; // + IO7 = false; // + IO8 = false; // + IO9 = false; // + IO10 = false; // + IO11 = false; // + IO12 = false; // + IO13 = false; // + IO14 = false; // + IO15 = false; // + IO16 = false; // + IO17 = false; // + IO18 = false; // + IO19 = false; // + IO20 = false; // + IO21 = false; // + IO22 = false; // + IO23 = false; // + IO24 = false; // + IO25 = false; // + IO26 = false; // + IO27 = false; // + IO28 = false; // + IO29 = false; // + _reserved = uint2(0); // + } + + // GPIO output enable XOR: Perform an atomic bitwise XOR on GPIO_OE, i.e. `GPIO_OE ^= wdata` + register GPIO_OE_XOR_t GPIO_OE_XOR at 0xd000002c; + + type GPIO_HI_OUT_t { + GPIO_HI_OUT = uint6(0); // Set output level (1/0 -> high/low) for QSPI IO0...5. Reading back gives the last value written, NOT the input value from the pins. If core 0 and core 1 both write to GPIO_HI_OUT simultaneously (or to a SET/CLR/XOR alias), the result is as though the write from core 0 took place first, and the write from core 1 was then applied to that intermediate result. + } + + // QSPI output value + register GPIO_HI_OUT_t GPIO_HI_OUT at 0xd0000030; + + type GPIO_HI_OUT_SET_t { + GPIO_HI_OUT_SET = uint6(0); // Perform an atomic bit-set on GPIO_HI_OUT, i.e. `GPIO_HI_OUT |= wdata` + } + + // QSPI output value set + register GPIO_HI_OUT_SET_t GPIO_HI_OUT_SET at 0xd0000034; + + type GPIO_HI_OUT_CLR_t { + GPIO_HI_OUT_CLR = uint6(0); // Perform an atomic bit-clear on GPIO_HI_OUT, i.e. `GPIO_HI_OUT &= ~wdata` + } + + // QSPI output value clear + register GPIO_HI_OUT_CLR_t GPIO_HI_OUT_CLR at 0xd0000038; + + type GPIO_HI_OUT_XOR_t { + GPIO_HI_OUT_XOR = uint6(0); // Perform an atomic bitwise XOR on GPIO_HI_OUT, i.e. `GPIO_HI_OUT ^= wdata` + } + + // QSPI output value XOR + register GPIO_HI_OUT_XOR_t GPIO_HI_OUT_XOR at 0xd000003c; + + type GPIO_HI_OE_t { + GPIO_HI_OE = uint6(0); // Set output enable (1/0 -> output/input) for QSPI IO0...5. Reading back gives the last value written. If core 0 and core 1 both write to GPIO_HI_OE simultaneously (or to a SET/CLR/XOR alias), the result is as though the write from core 0 took place first, and the write from core 1 was then applied to that intermediate result. + } + + // QSPI output enable + register GPIO_HI_OE_t GPIO_HI_OE at 0xd0000040; + + type GPIO_HI_OE_SET_t { + GPIO_HI_OE_SET = uint6(0); // Perform an atomic bit-set on GPIO_HI_OE, i.e. `GPIO_HI_OE |= wdata` + } + + // QSPI output enable set + register GPIO_HI_OE_SET_t GPIO_HI_OE_SET at 0xd0000044; + + type GPIO_HI_OE_CLR_t { + GPIO_HI_OE_CLR = uint6(0); // Perform an atomic bit-clear on GPIO_HI_OE, i.e. `GPIO_HI_OE &= ~wdata` + } + + // QSPI output enable clear + register GPIO_HI_OE_CLR_t GPIO_HI_OE_CLR at 0xd0000048; + + type GPIO_HI_OE_XOR_t { + GPIO_HI_OE_XOR = uint6(0); // Perform an atomic bitwise XOR on GPIO_HI_OE, i.e. `GPIO_HI_OE ^= wdata` + } + + // QSPI output enable XOR + register GPIO_HI_OE_XOR_t GPIO_HI_OE_XOR at 0xd000004c; + + type FIFO_ST_t { + VLD = false; // Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid) + RDY = false; // Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more data) + WOF = false; // Sticky flag indicating the TX FIFO was written when full. This write was ignored by the FIFO. + ROE = false; // Sticky flag indicating the RX FIFO was read when empty. This read was ignored by the FIFO. + } + + // Status register for inter-core FIFOs (mailboxes). There is one FIFO in the core 0 -> core 1 direction, and one core 1 -> core 0. Both are 32 bits wide and 8 words deep. Core 0 can see the read side of the 1->0 FIFO (RX), and the write side of 0->1 FIFO (TX). Core 1 can see the read side of the 0->1 FIFO (RX), and the write side of 1->0 FIFO (TX). The SIO IRQ for each core is the logical OR of the VLD, WOF and ROE fields of its FIFO_ST register. + register FIFO_ST_t FIFO_ST at 0xd0000050; + + type FIFO_WR_t { + FIFO_WR = uint32(0); // + } + + // Write access to this core's TX FIFO + register FIFO_WR_t FIFO_WR at 0xd0000054; + + type FIFO_RD_t { + FIFO_RD = uint32(0); // + } + + // Read access to this core's RX FIFO + register FIFO_RD_t FIFO_RD at 0xd0000058; + + type SPINLOCK_ST_t { + SPINLOCK_ST = uint32(0); // + } + + // Spinlock state A bitmap containing the state of all 32 spinlocks (1=locked). Mainly intended for debugging. + register SPINLOCK_ST_t SPINLOCK_ST at 0xd000005c; + + type DIV_UDIVIDEND_t { + DIV_UDIVIDEND = uint32(0); // + } + + // Divider unsigned dividend Write to the DIVIDEND operand of the divider, i.e. the p in `p / q`. Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias starts an unsigned calculation, and the S alias starts a signed calculation. + register DIV_UDIVIDEND_t DIV_UDIVIDEND at 0xd0000060; + + type DIV_UDIVISOR_t { + DIV_UDIVISOR = uint32(0); // + } + + // Divider unsigned divisor Write to the DIVISOR operand of the divider, i.e. the q in `p / q`. Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. UDIVISOR/SDIVISOR are aliases of the same internal register. The U alias starts an unsigned calculation, and the S alias starts a signed calculation. + register DIV_UDIVISOR_t DIV_UDIVISOR at 0xd0000064; + + type DIV_SDIVIDEND_t { + DIV_SDIVIDEND = uint32(0); // + } + + // Divider signed dividend The same as UDIVIDEND, but starts a signed calculation, rather than unsigned. + register DIV_SDIVIDEND_t DIV_SDIVIDEND at 0xd0000068; + + type DIV_SDIVISOR_t { + DIV_SDIVISOR = uint32(0); // + } + + // Divider signed divisor The same as UDIVISOR, but starts a signed calculation, rather than unsigned. + register DIV_SDIVISOR_t DIV_SDIVISOR at 0xd000006c; + + type DIV_QUOTIENT_t { + DIV_QUOTIENT = uint32(0); // + } + + // Divider result quotient The result of `DIVIDEND / DIVISOR` (division). Contents undefined while CSR_READY is low. For signed calculations, QUOTIENT is negative when the signs of DIVIDEND and DIVISOR differ. This register can be written to directly, for context save/restore purposes. This halts any in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. Reading from QUOTIENT clears the CSR_DIRTY flag, so should read results in the order REMAINDER, QUOTIENT if CSR_DIRTY is used. + register DIV_QUOTIENT_t DIV_QUOTIENT at 0xd0000070; + + type DIV_REMAINDER_t { + DIV_REMAINDER = uint32(0); // + } + + // Divider result remainder The result of `DIVIDEND % DIVISOR` (modulo). Contents undefined while CSR_READY is low. For signed calculations, REMAINDER is negative only when DIVIDEND is negative. This register can be written to directly, for context save/restore purposes. This halts any in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. + register DIV_REMAINDER_t DIV_REMAINDER at 0xd0000074; + + type DIV_CSR_t { + READY = false; // Reads as 0 when a calculation is in progress, 1 otherwise. Writing an operand (xDIVIDEND, xDIVISOR) will immediately start a new calculation, no matter if one is already in progress. Writing to a result register will immediately terminate any in-progress calculation and set the READY and DIRTY flags. + DIRTY = false; // Changes to 1 when any register is written, and back to 0 when QUOTIENT is read. Software can use this flag to make save/restore more efficient (skip if not DIRTY). If the flag is used in this way, it's recommended to either read QUOTIENT only, or REMAINDER and then QUOTIENT, to prevent data loss on context switch. + } + + // Control and status register for divider. + register DIV_CSR_t DIV_CSR at 0xd0000078; + + type INTERP0_ACCUM0_t { + INTERP0_ACCUM0 = uint32(0); // + } + + // Read/write access to accumulator 0 + register INTERP0_ACCUM0_t INTERP0_ACCUM0 at 0xd0000080; + + type INTERP0_ACCUM1_t { + INTERP0_ACCUM1 = uint32(0); // + } + + // Read/write access to accumulator 1 + register INTERP0_ACCUM1_t INTERP0_ACCUM1 at 0xd0000084; + + type INTERP0_BASE0_t { + INTERP0_BASE0 = uint32(0); // + } + + // Read/write access to BASE0 register. + register INTERP0_BASE0_t INTERP0_BASE0 at 0xd0000088; + + type INTERP0_BASE1_t { + INTERP0_BASE1 = uint32(0); // + } + + // Read/write access to BASE1 register. + register INTERP0_BASE1_t INTERP0_BASE1 at 0xd000008c; + + type INTERP0_BASE2_t { + INTERP0_BASE2 = uint32(0); // + } + + // Read/write access to BASE2 register. + register INTERP0_BASE2_t INTERP0_BASE2 at 0xd0000090; + + type INTERP0_POP_LANE0_t { + INTERP0_POP_LANE0 = uint32(0); // + } + + // Read LANE0 result, and simultaneously write lane results to both accumulators (POP). + register INTERP0_POP_LANE0_t INTERP0_POP_LANE0 at 0xd0000094; + + type INTERP0_POP_LANE1_t { + INTERP0_POP_LANE1 = uint32(0); // + } + + // Read LANE1 result, and simultaneously write lane results to both accumulators (POP). + register INTERP0_POP_LANE1_t INTERP0_POP_LANE1 at 0xd0000098; + + type INTERP0_POP_FULL_t { + INTERP0_POP_FULL = uint32(0); // + } + + // Read FULL result, and simultaneously write lane results to both accumulators (POP). + register INTERP0_POP_FULL_t INTERP0_POP_FULL at 0xd000009c; + + type INTERP0_PEEK_LANE0_t { + INTERP0_PEEK_LANE0 = uint32(0); // + } + + // Read LANE0 result, without altering any internal state (PEEK). + register INTERP0_PEEK_LANE0_t INTERP0_PEEK_LANE0 at 0xd00000a0; + + type INTERP0_PEEK_LANE1_t { + INTERP0_PEEK_LANE1 = uint32(0); // + } + + // Read LANE1 result, without altering any internal state (PEEK). + register INTERP0_PEEK_LANE1_t INTERP0_PEEK_LANE1 at 0xd00000a4; + + type INTERP0_PEEK_FULL_t { + INTERP0_PEEK_FULL = uint32(0); // + } + + // Read FULL result, without altering any internal state (PEEK). + register INTERP0_PEEK_FULL_t INTERP0_PEEK_FULL at 0xd00000a8; + + type INTERP0_CTRL_LANE0_t { + SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking + MASK_LSB = uint5(0); // The least-significant bit allowed to pass by the mask (inclusive) + MASK_MSB = uint5(0); // The most-significant bit allowed to pass by the mask (inclusive) Setting MSB < LSB may cause chip to turn inside-out + SIGNED = false; // If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. + CROSS_INPUT = false; // If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_RESULT = false; // If 1, feed the opposite lane's result into this lane's accumulator on POP. + ADD_RAW = false; // If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. + FORCE_MSB = uint2(0); // ORed into bits 29:28 of the lane result presented to the processor on the bus. No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence of pointers into flash or SRAM. + BLEND = false; // Only present on INTERP0 on each core. If BLEND mode is enabled: - LANE1 result is a linear interpolation between BASE0 and BASE1, controlled by the 8 LSBs of lane 1 shift and mask value (a fractional number between 0 and 255/256ths) - LANE0 result does not have BASE0 added (yields only the 8 LSBs of lane 1 shift+mask value) - FULL result does not have lane 1 shift+mask value added (BASE2 + lane 0 shift+mask) LANE1 SIGNED flag controls whether the interpolation is signed or unsigned. + _res1 = false; // Reserved, 1 bits + OVERF0 = false; // Indicates if any masked-off MSBs in ACCUM0 are set. + OVERF1 = false; // Indicates if any masked-off MSBs in ACCUM1 are set. + OVERF = false; // Set if either OVERF0 or OVERF1 is set. + } + + // Control register for lane 0 + register INTERP0_CTRL_LANE0_t INTERP0_CTRL_LANE0 at 0xd00000ac; + + type INTERP0_CTRL_LANE1_t { + SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking + MASK_LSB = uint5(0); // The least-significant bit allowed to pass by the mask (inclusive) + MASK_MSB = uint5(0); // The most-significant bit allowed to pass by the mask (inclusive) Setting MSB < LSB may cause chip to turn inside-out + SIGNED = false; // If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. + CROSS_INPUT = false; // If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_RESULT = false; // If 1, feed the opposite lane's result into this lane's accumulator on POP. + ADD_RAW = false; // If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. + FORCE_MSB = uint2(0); // ORed into bits 29:28 of the lane result presented to the processor on the bus. No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence of pointers into flash or SRAM. + } + + // Control register for lane 1 + register INTERP0_CTRL_LANE1_t INTERP0_CTRL_LANE1 at 0xd00000b0; + + type INTERP0_ACCUM0_ADD_t { + INTERP0_ACCUM0_ADD = uint24(0); // + } + + // Values written here are atomically added to ACCUM0 Reading yields lane 0's raw shift and mask value (BASE0 not added). + register INTERP0_ACCUM0_ADD_t INTERP0_ACCUM0_ADD at 0xd00000b4; + + type INTERP0_ACCUM1_ADD_t { + INTERP0_ACCUM1_ADD = uint24(0); // + } + + // Values written here are atomically added to ACCUM1 Reading yields lane 1's raw shift and mask value (BASE1 not added). + register INTERP0_ACCUM1_ADD_t INTERP0_ACCUM1_ADD at 0xd00000b8; + + type INTERP0_BASE_1AND0_t { + INTERP0_BASE_1AND0 = uint32(0); // + } + + // On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + register INTERP0_BASE_1AND0_t INTERP0_BASE_1AND0 at 0xd00000bc; + + type INTERP1_ACCUM0_t { + INTERP1_ACCUM0 = uint32(0); // + } + + // Read/write access to accumulator 0 + register INTERP1_ACCUM0_t INTERP1_ACCUM0 at 0xd00000c0; + + type INTERP1_ACCUM1_t { + INTERP1_ACCUM1 = uint32(0); // + } + + // Read/write access to accumulator 1 + register INTERP1_ACCUM1_t INTERP1_ACCUM1 at 0xd00000c4; + + type INTERP1_BASE0_t { + INTERP1_BASE0 = uint32(0); // + } + + // Read/write access to BASE0 register. + register INTERP1_BASE0_t INTERP1_BASE0 at 0xd00000c8; + + type INTERP1_BASE1_t { + INTERP1_BASE1 = uint32(0); // + } + + // Read/write access to BASE1 register. + register INTERP1_BASE1_t INTERP1_BASE1 at 0xd00000cc; + + type INTERP1_BASE2_t { + INTERP1_BASE2 = uint32(0); // + } + + // Read/write access to BASE2 register. + register INTERP1_BASE2_t INTERP1_BASE2 at 0xd00000d0; + + type INTERP1_POP_LANE0_t { + INTERP1_POP_LANE0 = uint32(0); // + } + + // Read LANE0 result, and simultaneously write lane results to both accumulators (POP). + register INTERP1_POP_LANE0_t INTERP1_POP_LANE0 at 0xd00000d4; + + type INTERP1_POP_LANE1_t { + INTERP1_POP_LANE1 = uint32(0); // + } + + // Read LANE1 result, and simultaneously write lane results to both accumulators (POP). + register INTERP1_POP_LANE1_t INTERP1_POP_LANE1 at 0xd00000d8; + + type INTERP1_POP_FULL_t { + INTERP1_POP_FULL = uint32(0); // + } + + // Read FULL result, and simultaneously write lane results to both accumulators (POP). + register INTERP1_POP_FULL_t INTERP1_POP_FULL at 0xd00000dc; + + type INTERP1_PEEK_LANE0_t { + INTERP1_PEEK_LANE0 = uint32(0); // + } + + // Read LANE0 result, without altering any internal state (PEEK). + register INTERP1_PEEK_LANE0_t INTERP1_PEEK_LANE0 at 0xd00000e0; + + type INTERP1_PEEK_LANE1_t { + INTERP1_PEEK_LANE1 = uint32(0); // + } + + // Read LANE1 result, without altering any internal state (PEEK). + register INTERP1_PEEK_LANE1_t INTERP1_PEEK_LANE1 at 0xd00000e4; + + type INTERP1_PEEK_FULL_t { + INTERP1_PEEK_FULL = uint32(0); // + } + + // Read FULL result, without altering any internal state (PEEK). + register INTERP1_PEEK_FULL_t INTERP1_PEEK_FULL at 0xd00000e8; + + type INTERP1_CTRL_LANE0_t { + SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking + MASK_LSB = uint5(0); // The least-significant bit allowed to pass by the mask (inclusive) + MASK_MSB = uint5(0); // The most-significant bit allowed to pass by the mask (inclusive) Setting MSB < LSB may cause chip to turn inside-out + SIGNED = false; // If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. + CROSS_INPUT = false; // If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_RESULT = false; // If 1, feed the opposite lane's result into this lane's accumulator on POP. + ADD_RAW = false; // If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. + FORCE_MSB = uint2(0); // ORed into bits 29:28 of the lane result presented to the processor on the bus. No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence of pointers into flash or SRAM. + _res1 = false; // Reserved, 1 bits + CLAMP = false; // Only present on INTERP1 on each core. If CLAMP mode is enabled: - LANE0 result is shifted and masked ACCUM0, clamped by a lower bound of BASE0 and an upper bound of BASE1. - Signedness of these comparisons is determined by LANE0_CTRL_SIGNED + OVERF0 = false; // Indicates if any masked-off MSBs in ACCUM0 are set. + OVERF1 = false; // Indicates if any masked-off MSBs in ACCUM1 are set. + OVERF = false; // Set if either OVERF0 or OVERF1 is set. + } + + // Control register for lane 0 + register INTERP1_CTRL_LANE0_t INTERP1_CTRL_LANE0 at 0xd00000ec; + + type INTERP1_CTRL_LANE1_t { + SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking + MASK_LSB = uint5(0); // The least-significant bit allowed to pass by the mask (inclusive) + MASK_MSB = uint5(0); // The most-significant bit allowed to pass by the mask (inclusive) Setting MSB < LSB may cause chip to turn inside-out + SIGNED = false; // If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. + CROSS_INPUT = false; // If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + CROSS_RESULT = false; // If 1, feed the opposite lane's result into this lane's accumulator on POP. + ADD_RAW = false; // If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. + FORCE_MSB = uint2(0); // ORed into bits 29:28 of the lane result presented to the processor on the bus. No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence of pointers into flash or SRAM. + } + + // Control register for lane 1 + register INTERP1_CTRL_LANE1_t INTERP1_CTRL_LANE1 at 0xd00000f0; + + type INTERP1_ACCUM0_ADD_t { + INTERP1_ACCUM0_ADD = uint24(0); // + } + + // Values written here are atomically added to ACCUM0 Reading yields lane 0's raw shift and mask value (BASE0 not added). + register INTERP1_ACCUM0_ADD_t INTERP1_ACCUM0_ADD at 0xd00000f4; + + type INTERP1_ACCUM1_ADD_t { + INTERP1_ACCUM1_ADD = uint24(0); // + } + + // Values written here are atomically added to ACCUM1 Reading yields lane 1's raw shift and mask value (BASE1 not added). + register INTERP1_ACCUM1_ADD_t INTERP1_ACCUM1_ADD at 0xd00000f8; + + type INTERP1_BASE_1AND0_t { + INTERP1_BASE_1AND0 = uint32(0); // + } + + // On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + register INTERP1_BASE_1AND0_t INTERP1_BASE_1AND0 at 0xd00000fc; + + type SPINLOCK0_t { + SPINLOCK0 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK0_t SPINLOCK0 at 0xd0000100; + + type SPINLOCK1_t { + SPINLOCK1 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK1_t SPINLOCK1 at 0xd0000104; + + type SPINLOCK2_t { + SPINLOCK2 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK2_t SPINLOCK2 at 0xd0000108; + + type SPINLOCK3_t { + SPINLOCK3 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK3_t SPINLOCK3 at 0xd000010c; + + type SPINLOCK4_t { + SPINLOCK4 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK4_t SPINLOCK4 at 0xd0000110; + + type SPINLOCK5_t { + SPINLOCK5 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK5_t SPINLOCK5 at 0xd0000114; + + type SPINLOCK6_t { + SPINLOCK6 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK6_t SPINLOCK6 at 0xd0000118; + + type SPINLOCK7_t { + SPINLOCK7 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK7_t SPINLOCK7 at 0xd000011c; + + type SPINLOCK8_t { + SPINLOCK8 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK8_t SPINLOCK8 at 0xd0000120; + + type SPINLOCK9_t { + SPINLOCK9 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK9_t SPINLOCK9 at 0xd0000124; + + type SPINLOCK10_t { + SPINLOCK10 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK10_t SPINLOCK10 at 0xd0000128; + + type SPINLOCK11_t { + SPINLOCK11 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK11_t SPINLOCK11 at 0xd000012c; + + type SPINLOCK12_t { + SPINLOCK12 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK12_t SPINLOCK12 at 0xd0000130; + + type SPINLOCK13_t { + SPINLOCK13 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK13_t SPINLOCK13 at 0xd0000134; + + type SPINLOCK14_t { + SPINLOCK14 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK14_t SPINLOCK14 at 0xd0000138; + + type SPINLOCK15_t { + SPINLOCK15 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK15_t SPINLOCK15 at 0xd000013c; + + type SPINLOCK16_t { + SPINLOCK16 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK16_t SPINLOCK16 at 0xd0000140; + + type SPINLOCK17_t { + SPINLOCK17 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK17_t SPINLOCK17 at 0xd0000144; + + type SPINLOCK18_t { + SPINLOCK18 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK18_t SPINLOCK18 at 0xd0000148; + + type SPINLOCK19_t { + SPINLOCK19 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK19_t SPINLOCK19 at 0xd000014c; + + type SPINLOCK20_t { + SPINLOCK20 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK20_t SPINLOCK20 at 0xd0000150; + + type SPINLOCK21_t { + SPINLOCK21 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK21_t SPINLOCK21 at 0xd0000154; + + type SPINLOCK22_t { + SPINLOCK22 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK22_t SPINLOCK22 at 0xd0000158; + + type SPINLOCK23_t { + SPINLOCK23 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK23_t SPINLOCK23 at 0xd000015c; + + type SPINLOCK24_t { + SPINLOCK24 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK24_t SPINLOCK24 at 0xd0000160; + + type SPINLOCK25_t { + SPINLOCK25 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK25_t SPINLOCK25 at 0xd0000164; + + type SPINLOCK26_t { + SPINLOCK26 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK26_t SPINLOCK26 at 0xd0000168; + + type SPINLOCK27_t { + SPINLOCK27 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK27_t SPINLOCK27 at 0xd000016c; + + type SPINLOCK28_t { + SPINLOCK28 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK28_t SPINLOCK28 at 0xd0000170; + + type SPINLOCK29_t { + SPINLOCK29 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK29_t SPINLOCK29 at 0xd0000174; + + type SPINLOCK30_t { + SPINLOCK30 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK30_t SPINLOCK30 at 0xd0000178; + + type SPINLOCK31_t { + SPINLOCK31 = uint32(0); // + } + + // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. + register SPINLOCK31_t SPINLOCK31 at 0xd000017c; + + +/* Types and registers for USB + USB FS/LS controller device registers + */ + + type ADDR_ENDP_t { + ADDRESS = uint7(0); // In device mode, the address that the device should respond to. Set in response to a SET_ADDR setup packet from the host. In host mode set to the address of the device to communicate with. + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Device endpoint to send data to. Only valid for HOST mode. + } + + // Device address and endpoint control + register ADDR_ENDP_t ADDR_ENDP at 0x50110000; + + type ADDR_ENDP1_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 1. Only valid for HOST mode. + register ADDR_ENDP1_t ADDR_ENDP1 at 0x50110004; + + type ADDR_ENDP2_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 2. Only valid for HOST mode. + register ADDR_ENDP2_t ADDR_ENDP2 at 0x50110008; + + type ADDR_ENDP3_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 3. Only valid for HOST mode. + register ADDR_ENDP3_t ADDR_ENDP3 at 0x5011000c; + + type ADDR_ENDP4_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 4. Only valid for HOST mode. + register ADDR_ENDP4_t ADDR_ENDP4 at 0x50110010; + + type ADDR_ENDP5_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 5. Only valid for HOST mode. + register ADDR_ENDP5_t ADDR_ENDP5 at 0x50110014; + + type ADDR_ENDP6_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 6. Only valid for HOST mode. + register ADDR_ENDP6_t ADDR_ENDP6 at 0x50110018; + + type ADDR_ENDP7_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 7. Only valid for HOST mode. + register ADDR_ENDP7_t ADDR_ENDP7 at 0x5011001c; + + type ADDR_ENDP8_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 8. Only valid for HOST mode. + register ADDR_ENDP8_t ADDR_ENDP8 at 0x50110020; + + type ADDR_ENDP9_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 9. Only valid for HOST mode. + register ADDR_ENDP9_t ADDR_ENDP9 at 0x50110024; + + type ADDR_ENDP10_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 10. Only valid for HOST mode. + register ADDR_ENDP10_t ADDR_ENDP10 at 0x50110028; + + type ADDR_ENDP11_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 11. Only valid for HOST mode. + register ADDR_ENDP11_t ADDR_ENDP11 at 0x5011002c; + + type ADDR_ENDP12_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 12. Only valid for HOST mode. + register ADDR_ENDP12_t ADDR_ENDP12 at 0x50110030; + + type ADDR_ENDP13_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 13. Only valid for HOST mode. + register ADDR_ENDP13_t ADDR_ENDP13 at 0x50110034; + + type ADDR_ENDP14_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 14. Only valid for HOST mode. + register ADDR_ENDP14_t ADDR_ENDP14 at 0x50110038; + + type ADDR_ENDP15_t { + ADDRESS = uint7(0); // Device address + _res1 = uint8(0); // Reserved, 9 bits + _res2 = false; // + ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint + _res3 = uint5(0); // Reserved, 5 bits + INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 + INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + } + + // Interrupt endpoint 15. Only valid for HOST mode. + register ADDR_ENDP15_t ADDR_ENDP15 at 0x5011003c; + + type MAIN_CTRL_t { + CONTROLLER_EN = false; // Enable controller + HOST_NDEVICE = false; // Device mode = 0, Host mode = 1 + _res1 = uint16(0); // Reserved, 29 bits + _res2 = uint8(0); // + _res3 = uint5(0); // + SIM_TIMING = false; // Reduced timings for simulation + } + + // Main control register + register MAIN_CTRL_t MAIN_CTRL at 0x50110040; + + type SOF_WR_t { + COUNT = uint11(0); // + } + + // Set the SOF (Start of Frame) frame number in the host controller. The SOF packet is sent every 1ms and the host will increment the frame number by 1 each time. + register SOF_WR_t SOF_WR at 0x50110044; + + type SOF_RD_t { + COUNT = uint11(0); // + } + + // Read the last SOF (Start of Frame) frame number seen. In device mode the last SOF received from the host. In host mode the last SOF sent by the host. + register SOF_RD_t SOF_RD at 0x50110048; + + type SIE_CTRL_t { + START_TRANS = false; // Host: Start transaction + SEND_SETUP = false; // Host: Send Setup packet + SEND_DATA = false; // Host: Send transaction (OUT from host) + RECEIVE_DATA = false; // Host: Receive transaction (IN to host) + STOP_TRANS = false; // Host: Stop transaction + _res1 = false; // Reserved, 1 bits + PREAMBLE_EN = false; // Host: Preable enable for LS device on FS hub + _res2 = false; // Reserved, 1 bits + SOF_SYNC = false; // Host: Delay packet(s) until after SOF + SOF_EN = false; // Host: Enable SOF generation (for full speed bus) + KEEP_ALIVE_EN = false; // Host: Enable keep alive packet (for low speed bus) + VBUS_EN = false; // Host: Enable VBUS + RESUME = false; // Device: Remote wakeup. Device can initiate its own resume after suspend. + RESET_BUS = false; // Host: Reset bus + _res3 = false; // Reserved, 1 bits + PULLDOWN_EN = false; // Host: Enable pull down resistors + PULLUP_EN = false; // Device: Enable pull up resistor + RPU_OPT = false; // Device: Pull-up strength (0=1K2, 1=2k3) + TRANSCEIVER_PD = false; // Power down bus transceiver + _res4 = uint5(0); // Reserved, 5 bits + DIRECT_DM = false; // Direct control of DM + DIRECT_DP = false; // Direct control of DP + DIRECT_EN = false; // Direct bus drive enable + EP0_INT_NAK = false; // Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a NAK + EP0_INT_2BUF = false; // Device: Set bit in BUFF_STATUS for every 2 buffers completed on EP0 + EP0_INT_1BUF = false; // Device: Set bit in BUFF_STATUS for every buffer completed on EP0 + EP0_DOUBLE_BUF = false; // Device: EP0 single buffered = 0, double buffered = 1 + EP0_INT_STALL = false; // Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a STALL + } + + // SIE control register + register SIE_CTRL_t SIE_CTRL at 0x5011004c; + + type SIE_STATUS_t { + VBUS_DETECTED = false; // Device: VBUS Detected + _res1 = false; // Reserved, 1 bits + LINE_STATE = uint2(0); // USB bus line state + SUSPENDED = false; // Bus in suspended state. Valid for device and host. Host and device will go into suspend if neither Keep Alive / SOF frames are enabled. + _res2 = uint3(0); // Reserved, 3 bits + SPEED = uint2(0); // Host: device speed. Disconnected = 00, LS = 01, FS = 10 + VBUS_OVER_CURR = false; // VBUS over current detected + RESUME = false; // Host: Device has initiated a remote resume. Device: host has initiated a resume. + _res3 = uint4(0); // Reserved, 4 bits + CONNECTED = false; // Device: connected + SETUP_REC = false; // Device: Setup packet received + TRANS_COMPLETE = false; // Transaction complete. Raised by device if: * An IN or OUT packet is sent with the `LAST_BUFF` bit set in the buffer control register Raised by host if: * A setup packet is sent when no data in or data out transaction follows * An IN packet is received and the `LAST_BUFF` bit is set in the buffer control register * An IN packet is received with zero length * An OUT packet is sent and the `LAST_BUFF` bit is set + BUS_RESET = false; // Device: bus reset received + _res4 = uint4(0); // Reserved, 4 bits + CRC_ERROR = false; // CRC Error. Raised by the Serial RX engine. + BIT_STUFF_ERROR = false; // Bit Stuff Error. Raised by the Serial RX engine. + RX_OVERFLOW = false; // RX overflow is raised by the Serial RX engine if the incoming data is too fast. + RX_TIMEOUT = false; // RX timeout is raised by both the host and device if an ACK is not received in the maximum time specified by the USB spec. + NAK_REC = false; // Host: NAK received + STALL_REC = false; // Host: STALL received + ACK_REC = false; // ACK received. Raised by both host and device. + DATA_SEQ_ERROR = false; // Data Sequence Error. The device can raise a sequence error in the following conditions: * A SETUP packet is received followed by a DATA1 packet (data phase should always be DATA0) * An OUT packet is received from the host but doesn't match the data pid in the buffer control register read from DPSRAM The host can raise a data sequence error in the following conditions: * An IN packet from the device has the wrong data PID + } + + // SIE status register + register SIE_STATUS_t SIE_STATUS at 0x50110050; + + type INT_EP_CTRL_t { + _res1 = false; // Reserved, 1 bits + INT_EP_ACTIVE = uint15(0); // Host: Enable interrupt endpoint 1 => 15 + } + + // interrupt endpoint control register + register INT_EP_CTRL_t INT_EP_CTRL at 0x50110054; + + type BUFF_STATUS_t { + EP0_IN = false; // + EP0_OUT = false; // + EP1_IN = false; // + EP1_OUT = false; // + EP2_IN = false; // + EP2_OUT = false; // + EP3_IN = false; // + EP3_OUT = false; // + EP4_IN = false; // + EP4_OUT = false; // + EP5_IN = false; // + EP5_OUT = false; // + EP6_IN = false; // + EP6_OUT = false; // + EP7_IN = false; // + EP7_OUT = false; // + EP8_IN = false; // + EP8_OUT = false; // + EP9_IN = false; // + EP9_OUT = false; // + EP10_IN = false; // + EP10_OUT = false; // + EP11_IN = false; // + EP11_OUT = false; // + EP12_IN = false; // + EP12_OUT = false; // + EP13_IN = false; // + EP13_OUT = false; // + EP14_IN = false; // + EP14_OUT = false; // + EP15_IN = false; // + EP15_OUT = false; // + } + + // Buffer status register. A bit set here indicates that a buffer has completed on the endpoint (if the buffer interrupt is enabled). It is possible for 2 buffers to be completed, so clearing the buffer status bit may instantly re set it on the next clock cycle. + register BUFF_STATUS_t BUFF_STATUS at 0x50110058; + + type BUFF_CPU_SHOULD_HANDLE_t { + EP0_IN = false; // + EP0_OUT = false; // + EP1_IN = false; // + EP1_OUT = false; // + EP2_IN = false; // + EP2_OUT = false; // + EP3_IN = false; // + EP3_OUT = false; // + EP4_IN = false; // + EP4_OUT = false; // + EP5_IN = false; // + EP5_OUT = false; // + EP6_IN = false; // + EP6_OUT = false; // + EP7_IN = false; // + EP7_OUT = false; // + EP8_IN = false; // + EP8_OUT = false; // + EP9_IN = false; // + EP9_OUT = false; // + EP10_IN = false; // + EP10_OUT = false; // + EP11_IN = false; // + EP11_OUT = false; // + EP12_IN = false; // + EP12_OUT = false; // + EP13_IN = false; // + EP13_OUT = false; // + EP14_IN = false; // + EP14_OUT = false; // + EP15_IN = false; // + EP15_OUT = false; // + } + + // Which of the double buffers should be handled. Only valid if using an interrupt per buffer (i.e. not per 2 buffers). Not valid for host interrupt endpoint polling because they are only single buffered. + register BUFF_CPU_SHOULD_HANDLE_t BUFF_CPU_SHOULD_HANDLE at 0x5011005c; + + type EP_ABORT_t { + EP0_IN = false; // + EP0_OUT = false; // + EP1_IN = false; // + EP1_OUT = false; // + EP2_IN = false; // + EP2_OUT = false; // + EP3_IN = false; // + EP3_OUT = false; // + EP4_IN = false; // + EP4_OUT = false; // + EP5_IN = false; // + EP5_OUT = false; // + EP6_IN = false; // + EP6_OUT = false; // + EP7_IN = false; // + EP7_OUT = false; // + EP8_IN = false; // + EP8_OUT = false; // + EP9_IN = false; // + EP9_OUT = false; // + EP10_IN = false; // + EP10_OUT = false; // + EP11_IN = false; // + EP11_OUT = false; // + EP12_IN = false; // + EP12_OUT = false; // + EP13_IN = false; // + EP13_OUT = false; // + EP14_IN = false; // + EP14_OUT = false; // + EP15_IN = false; // + EP15_OUT = false; // + } + + // Device only: Can be set to ignore the buffer control register for this endpoint in case you would like to revoke a buffer. A NAK will be sent for every access to the endpoint until this bit is cleared. A corresponding bit in `EP_ABORT_DONE` is set when it is safe to modify the buffer control register. + register EP_ABORT_t EP_ABORT at 0x50110060; + + type EP_ABORT_DONE_t { + EP0_IN = false; // + EP0_OUT = false; // + EP1_IN = false; // + EP1_OUT = false; // + EP2_IN = false; // + EP2_OUT = false; // + EP3_IN = false; // + EP3_OUT = false; // + EP4_IN = false; // + EP4_OUT = false; // + EP5_IN = false; // + EP5_OUT = false; // + EP6_IN = false; // + EP6_OUT = false; // + EP7_IN = false; // + EP7_OUT = false; // + EP8_IN = false; // + EP8_OUT = false; // + EP9_IN = false; // + EP9_OUT = false; // + EP10_IN = false; // + EP10_OUT = false; // + EP11_IN = false; // + EP11_OUT = false; // + EP12_IN = false; // + EP12_OUT = false; // + EP13_IN = false; // + EP13_OUT = false; // + EP14_IN = false; // + EP14_OUT = false; // + EP15_IN = false; // + EP15_OUT = false; // + } + + // Device only: Used in conjunction with `EP_ABORT`. Set once an endpoint is idle so the programmer knows it is safe to modify the buffer control register. + register EP_ABORT_DONE_t EP_ABORT_DONE at 0x50110064; + + type EP_STALL_ARM_t { + EP0_IN = false; // + EP0_OUT = false; // + } + + // Device: this bit must be set in conjunction with the `STALL` bit in the buffer control register to send a STALL on EP0. The device controller clears these bits when a SETUP packet is received because the USB spec requires that a STALL condition is cleared when a SETUP packet is received. + register EP_STALL_ARM_t EP_STALL_ARM at 0x50110068; + + type NAK_POLL_t { + DELAY_LS = uint10(0); // NAK polling interval for a low speed device + _res1 = uint6(0); // Reserved, 6 bits + DELAY_FS = uint10(0); // NAK polling interval for a full speed device + } + + // Used by the host controller. Sets the wait time in microseconds before trying again if the device replies with a NAK. + register NAK_POLL_t NAK_POLL at 0x5011006c; + + type EP_STATUS_STALL_NAK_t { + EP0_IN = false; // + EP0_OUT = false; // + EP1_IN = false; // + EP1_OUT = false; // + EP2_IN = false; // + EP2_OUT = false; // + EP3_IN = false; // + EP3_OUT = false; // + EP4_IN = false; // + EP4_OUT = false; // + EP5_IN = false; // + EP5_OUT = false; // + EP6_IN = false; // + EP6_OUT = false; // + EP7_IN = false; // + EP7_OUT = false; // + EP8_IN = false; // + EP8_OUT = false; // + EP9_IN = false; // + EP9_OUT = false; // + EP10_IN = false; // + EP10_OUT = false; // + EP11_IN = false; // + EP11_OUT = false; // + EP12_IN = false; // + EP12_OUT = false; // + EP13_IN = false; // + EP13_OUT = false; // + EP14_IN = false; // + EP14_OUT = false; // + EP15_IN = false; // + EP15_OUT = false; // + } + + // Device: bits are set when the `IRQ_ON_NAK` or `IRQ_ON_STALL` bits are set. For EP0 this comes from `SIE_CTRL`. For all other endpoints it comes from the endpoint control register. + register EP_STATUS_STALL_NAK_t EP_STATUS_STALL_NAK at 0x50110070; + + type USB_MUXING_t { + TO_PHY = false; // + TO_EXTPHY = false; // + TO_DIGITAL_PAD = false; // + SOFTCON = false; // + } + + // Where to connect the USB controller. Should be to_phy by default. + register USB_MUXING_t USB_MUXING at 0x50110074; + + type USB_PWR_t { + VBUS_EN = false; // + VBUS_EN_OVERRIDE_EN = false; // + VBUS_DETECT = false; // + VBUS_DETECT_OVERRIDE_EN = false; // + OVERCURR_DETECT = false; // + OVERCURR_DETECT_EN = false; // + } + + // Overrides for the power signals in the event that the VBUS signals are not hooked up to GPIO. Set the value of the override and then the override enable so switch over to the override value. + register USB_PWR_t USB_PWR at 0x50110078; + + type USBPHY_DIRECT_t { + DP_PULLUP_HISEL = false; // when dp_pullup_en is set high, this enables second resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + DP_PULLUP_EN = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + DP_PULLDN_EN = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller 1 - Enable Rpd on DPP + _res1 = false; // Reserved, 1 bits + DM_PULLUP_HISEL = false; // when dm_pullup_en is set high, this enables second resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + DM_PULLUP_EN = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller 1 - Enable Rpu on DPM + DM_PULLDN_EN = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller 1 - Enable Rpd on DPM + _res2 = false; // Reserved, 1 bits + TX_DP_OE = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller TX_SEMODE=0, OE for DPP/DPM diff pair. 0 - DPP/DPM in Hi-Z state; 1 - DPP/DPM driving TX_SEMODE=1, OE for DPP only. 0 - DPP in Hi-Z state; 1 - DPP driving + TX_DM_OE = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller TX_SEMODE=0, Ignored. TX_SEMODE=1, OE for DPM only. 0 - DPM in Hi-Z state; 1 - DPM driving + TX_DP = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller TX_SEMODE=0, Drives DPP/DPM diff pair. TX_DP_OE=1 to enable drive. DPP=TX_DP, DPM=~TX_DP TX_SEMODE=1, Drives DPP only. TX_DP_OE=1 to enable drive. DPP=TX_DP + TX_DM = false; // Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller TX_SEMODE=0, Ignored TX_SEMODE=1, Drives DPM only. TX_DM_OE=1 to enable drive. DPM=TX_DM + RX_PD = false; // + TX_PD = false; // + TX_FSSLEW = false; // + TX_DIFFMODE = false; // + RX_DD = false; // Status bit from USB PHY RX Diff data + RX_DP = false; // Status bit from USB PHY DPP pin state + RX_DM = false; // Status bit from USB PHY DPM pin state + DP_OVCN = false; // Status bit from USB PHY + DM_OVCN = false; // Status bit from USB PHY + DP_OVV = false; // Status bit from USB PHY + DM_OVV = false; // Status bit from USB PHY + } + + // Note that most functions are driven directly from usb_fsls controller. This register allows more detailed control/status from the USB PHY. Useful for debug but not expected to be used in normal operation Use in conjunction with usbphy_direct_override register + register USBPHY_DIRECT_t USBPHY_DIRECT at 0x5011007c; + + type USBPHY_DIRECT_OVERRIDE_t { + DP_PULLUP_HISEL_OVERRIDE_EN = false; // + DM_PULLUP_HISEL_OVERRIDE_EN = false; // + DP_PULLUP_EN_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + DP_PULLDN_EN_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + DM_PULLDN_EN_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + TX_DP_OE_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + TX_DM_OE_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + TX_DP_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + TX_DM_OVERRIDE_EN = false; // Override default value or value driven from USB Controller to PHY + RX_PD_OVERRIDE_EN = false; // + TX_PD_OVERRIDE_EN = false; // + TX_FSSLEW_OVERRIDE_EN = false; // + DM_PULLUP_OVERRIDE_EN = false; // + _res1 = uint2(0); // Reserved, 2 bits + TX_DIFFMODE_OVERRIDE_EN = false; // + } + + // + register USBPHY_DIRECT_OVERRIDE_t USBPHY_DIRECT_OVERRIDE at 0x50110080; + + type USBPHY_TRIM_t { + DP_PULLDN_TRIM = uint5(0); // Value to drive to USB PHY DP pulldown resistor trim control Experimental data suggests that the reset value will work, but this register allows adjustment if required + _res1 = uint3(0); // Reserved, 3 bits + DM_PULLDN_TRIM = uint5(0); // Value to drive to USB PHY DM pulldown resistor trim control Experimental data suggests that the reset value will work, but this register allows adjustment if required + } + + // Note that most functions are driven directly from usb_fsls controller. This register allows more detailed control/status from the USB PHY. Useful for debug but not expected to be used in normal operation + register USBPHY_TRIM_t USBPHY_TRIM at 0x50110084; + + type USB_INTR_t { + HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_RESUME = false; // Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + HOST_SOF = false; // Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + TRANS_COMPLETE = false; // Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + BUFF_STATUS = false; // Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + ERROR_DATA_SEQ = false; // Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_RX_TIMEOUT = false; // Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_OVERFLOW = false; // Source: SIE_STATUS.RX_OVERFLOW + ERROR_BIT_STUFF = false; // Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_CRC = false; // Source: SIE_STATUS.CRC_ERROR + STALL = false; // Source: SIE_STATUS.STALL_REC + VBUS_DETECT = false; // Source: SIE_STATUS.VBUS_DETECT + BUS_RESET = false; // Source: SIE_STATUS.BUS_RESET + DEV_CONN_DIS = false; // Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_SUSPEND = false; // Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_RESUME_FROM_HOST = false; // Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + SETUP_REQ = false; // Device. Source: SIE_STATUS.SETUP_REC + DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + } + + // Raw Interrupts + register USB_INTR_t USB_INTR at 0x5011008c; + + type USB_INTE_t { + HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_RESUME = false; // Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + HOST_SOF = false; // Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + TRANS_COMPLETE = false; // Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + BUFF_STATUS = false; // Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + ERROR_DATA_SEQ = false; // Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_RX_TIMEOUT = false; // Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_OVERFLOW = false; // Source: SIE_STATUS.RX_OVERFLOW + ERROR_BIT_STUFF = false; // Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_CRC = false; // Source: SIE_STATUS.CRC_ERROR + STALL = false; // Source: SIE_STATUS.STALL_REC + VBUS_DETECT = false; // Source: SIE_STATUS.VBUS_DETECT + BUS_RESET = false; // Source: SIE_STATUS.BUS_RESET + DEV_CONN_DIS = false; // Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_SUSPEND = false; // Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_RESUME_FROM_HOST = false; // Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + SETUP_REQ = false; // Device. Source: SIE_STATUS.SETUP_REC + DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + } + + // Interrupt Enable + register USB_INTE_t USB_INTE at 0x50110090; + + type USB_INTF_t { + HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_RESUME = false; // Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + HOST_SOF = false; // Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + TRANS_COMPLETE = false; // Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + BUFF_STATUS = false; // Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + ERROR_DATA_SEQ = false; // Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_RX_TIMEOUT = false; // Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_OVERFLOW = false; // Source: SIE_STATUS.RX_OVERFLOW + ERROR_BIT_STUFF = false; // Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_CRC = false; // Source: SIE_STATUS.CRC_ERROR + STALL = false; // Source: SIE_STATUS.STALL_REC + VBUS_DETECT = false; // Source: SIE_STATUS.VBUS_DETECT + BUS_RESET = false; // Source: SIE_STATUS.BUS_RESET + DEV_CONN_DIS = false; // Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_SUSPEND = false; // Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_RESUME_FROM_HOST = false; // Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + SETUP_REQ = false; // Device. Source: SIE_STATUS.SETUP_REC + DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + } + + // Interrupt Force + register USB_INTF_t USB_INTF at 0x50110094; + + type USB_INTS_t { + HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + HOST_RESUME = false; // Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + HOST_SOF = false; // Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + TRANS_COMPLETE = false; // Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + BUFF_STATUS = false; // Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + ERROR_DATA_SEQ = false; // Source: SIE_STATUS.DATA_SEQ_ERROR + ERROR_RX_TIMEOUT = false; // Source: SIE_STATUS.RX_TIMEOUT + ERROR_RX_OVERFLOW = false; // Source: SIE_STATUS.RX_OVERFLOW + ERROR_BIT_STUFF = false; // Source: SIE_STATUS.BIT_STUFF_ERROR + ERROR_CRC = false; // Source: SIE_STATUS.CRC_ERROR + STALL = false; // Source: SIE_STATUS.STALL_REC + VBUS_DETECT = false; // Source: SIE_STATUS.VBUS_DETECT + BUS_RESET = false; // Source: SIE_STATUS.BUS_RESET + DEV_CONN_DIS = false; // Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + DEV_SUSPEND = false; // Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + DEV_RESUME_FROM_HOST = false; // Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + SETUP_REQ = false; // Device. Source: SIE_STATUS.SETUP_REC + DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + } + + // Interrupt status after masking & forcing + register USB_INTS_t USB_INTS at 0x50110098; + + +/* Types and registers for USB_DPRAM + DPRAM layout for USB device. + */ + + type SETUP_PACKET_LOW_t { + BMREQUESTTYPE = uint8(0); // + BREQUEST = uint8(0); // + WVALUE = uint16(0); // + } + + // Bytes 0-3 of the SETUP packet from the host. + register SETUP_PACKET_LOW_t SETUP_PACKET_LOW at 0x50100000; + + type SETUP_PACKET_HIGH_t { + WINDEX = uint16(0); // + WLENGTH = uint16(0); // + } + + // Bytes 4-7 of the setup packet from the host. + register SETUP_PACKET_HIGH_t SETUP_PACKET_HIGH at 0x50100004; + + type EP1_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP1_IN_CONTROL_t EP1_IN_CONTROL at 0x50100008; + + type EP1_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP1_OUT_CONTROL_t EP1_OUT_CONTROL at 0x5010000c; + + type EP2_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP2_IN_CONTROL_t EP2_IN_CONTROL at 0x50100010; + + type EP2_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP2_OUT_CONTROL_t EP2_OUT_CONTROL at 0x50100014; + + type EP3_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP3_IN_CONTROL_t EP3_IN_CONTROL at 0x50100018; + + type EP3_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP3_OUT_CONTROL_t EP3_OUT_CONTROL at 0x5010001c; + + type EP4_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP4_IN_CONTROL_t EP4_IN_CONTROL at 0x50100020; + + type EP4_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP4_OUT_CONTROL_t EP4_OUT_CONTROL at 0x50100024; + + type EP5_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP5_IN_CONTROL_t EP5_IN_CONTROL at 0x50100028; + + type EP5_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP5_OUT_CONTROL_t EP5_OUT_CONTROL at 0x5010002c; + + type EP6_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP6_IN_CONTROL_t EP6_IN_CONTROL at 0x50100030; + + type EP6_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP6_OUT_CONTROL_t EP6_OUT_CONTROL at 0x50100034; + + type EP7_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP7_IN_CONTROL_t EP7_IN_CONTROL at 0x50100038; + + type EP7_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP7_OUT_CONTROL_t EP7_OUT_CONTROL at 0x5010003c; + + type EP8_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP8_IN_CONTROL_t EP8_IN_CONTROL at 0x50100040; + + type EP8_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP8_OUT_CONTROL_t EP8_OUT_CONTROL at 0x50100044; + + type EP9_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP9_IN_CONTROL_t EP9_IN_CONTROL at 0x50100048; + + type EP9_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP9_OUT_CONTROL_t EP9_OUT_CONTROL at 0x5010004c; + + type EP10_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP10_IN_CONTROL_t EP10_IN_CONTROL at 0x50100050; + + type EP10_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP10_OUT_CONTROL_t EP10_OUT_CONTROL at 0x50100054; + + type EP11_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP11_IN_CONTROL_t EP11_IN_CONTROL at 0x50100058; + + type EP11_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP11_OUT_CONTROL_t EP11_OUT_CONTROL at 0x5010005c; + + type EP12_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP12_IN_CONTROL_t EP12_IN_CONTROL at 0x50100060; + + type EP12_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP12_OUT_CONTROL_t EP12_OUT_CONTROL at 0x50100064; + + type EP13_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP13_IN_CONTROL_t EP13_IN_CONTROL at 0x50100068; + + type EP13_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP13_OUT_CONTROL_t EP13_OUT_CONTROL at 0x5010006c; + + type EP14_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP14_IN_CONTROL_t EP14_IN_CONTROL at 0x50100070; + + type EP14_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP14_OUT_CONTROL_t EP14_OUT_CONTROL at 0x50100074; + + type EP15_IN_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP15_IN_CONTROL_t EP15_IN_CONTROL at 0x50100078; + + type EP15_OUT_CONTROL_t { + BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + INTERRUPT_ON_NAK = false; // Trigger an interrupt if a NAK is sent. Intended for debug only. + INTERRUPT_ON_STALL = false; // Trigger an interrupt if a STALL is sent. Intended for debug only. + _res1 = uint8(0); // Reserved, 8 bits + ENDPOINT_TYPE = uint2(0); // + INTERRUPT_PER_DOUBLE_BUFF = false; // Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + INTERRUPT_PER_BUFF = false; // Trigger an interrupt each time a buffer is done. + DOUBLE_BUFFERED = false; // This endpoint is double buffered. + ENABLE = false; // Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + } + + // + register EP15_OUT_CONTROL_t EP15_OUT_CONTROL at 0x5010007c; + + type EP0_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP0_IN_BUFFER_CONTROL_t EP0_IN_BUFFER_CONTROL at 0x50100080; + + type EP0_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP0_OUT_BUFFER_CONTROL_t EP0_OUT_BUFFER_CONTROL at 0x50100084; + + type EP1_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP1_IN_BUFFER_CONTROL_t EP1_IN_BUFFER_CONTROL at 0x50100088; + + type EP1_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP1_OUT_BUFFER_CONTROL_t EP1_OUT_BUFFER_CONTROL at 0x5010008c; + + type EP2_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP2_IN_BUFFER_CONTROL_t EP2_IN_BUFFER_CONTROL at 0x50100090; + + type EP2_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP2_OUT_BUFFER_CONTROL_t EP2_OUT_BUFFER_CONTROL at 0x50100094; + + type EP3_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP3_IN_BUFFER_CONTROL_t EP3_IN_BUFFER_CONTROL at 0x50100098; + + type EP3_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP3_OUT_BUFFER_CONTROL_t EP3_OUT_BUFFER_CONTROL at 0x5010009c; + + type EP4_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP4_IN_BUFFER_CONTROL_t EP4_IN_BUFFER_CONTROL at 0x501000a0; + + type EP4_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP4_OUT_BUFFER_CONTROL_t EP4_OUT_BUFFER_CONTROL at 0x501000a4; + + type EP5_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP5_IN_BUFFER_CONTROL_t EP5_IN_BUFFER_CONTROL at 0x501000a8; + + type EP5_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP5_OUT_BUFFER_CONTROL_t EP5_OUT_BUFFER_CONTROL at 0x501000ac; + + type EP6_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP6_IN_BUFFER_CONTROL_t EP6_IN_BUFFER_CONTROL at 0x501000b0; + + type EP6_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP6_OUT_BUFFER_CONTROL_t EP6_OUT_BUFFER_CONTROL at 0x501000b4; + + type EP7_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP7_IN_BUFFER_CONTROL_t EP7_IN_BUFFER_CONTROL at 0x501000b8; + + type EP7_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP7_OUT_BUFFER_CONTROL_t EP7_OUT_BUFFER_CONTROL at 0x501000bc; + + type EP8_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP8_IN_BUFFER_CONTROL_t EP8_IN_BUFFER_CONTROL at 0x501000c0; + + type EP8_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP8_OUT_BUFFER_CONTROL_t EP8_OUT_BUFFER_CONTROL at 0x501000c4; + + type EP9_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP9_IN_BUFFER_CONTROL_t EP9_IN_BUFFER_CONTROL at 0x501000c8; + + type EP9_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP9_OUT_BUFFER_CONTROL_t EP9_OUT_BUFFER_CONTROL at 0x501000cc; + + type EP10_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP10_IN_BUFFER_CONTROL_t EP10_IN_BUFFER_CONTROL at 0x501000d0; + + type EP10_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP10_OUT_BUFFER_CONTROL_t EP10_OUT_BUFFER_CONTROL at 0x501000d4; + + type EP11_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP11_IN_BUFFER_CONTROL_t EP11_IN_BUFFER_CONTROL at 0x501000d8; + + type EP11_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP11_OUT_BUFFER_CONTROL_t EP11_OUT_BUFFER_CONTROL at 0x501000dc; + + type EP12_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP12_IN_BUFFER_CONTROL_t EP12_IN_BUFFER_CONTROL at 0x501000e0; + + type EP12_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP12_OUT_BUFFER_CONTROL_t EP12_OUT_BUFFER_CONTROL at 0x501000e4; + + type EP13_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP13_IN_BUFFER_CONTROL_t EP13_IN_BUFFER_CONTROL at 0x501000e8; + + type EP13_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP13_OUT_BUFFER_CONTROL_t EP13_OUT_BUFFER_CONTROL at 0x501000ec; + + type EP14_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP14_IN_BUFFER_CONTROL_t EP14_IN_BUFFER_CONTROL at 0x501000f0; + + type EP14_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP14_OUT_BUFFER_CONTROL_t EP14_OUT_BUFFER_CONTROL at 0x501000f4; + + type EP15_IN_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP15_IN_BUFFER_CONTROL_t EP15_IN_BUFFER_CONTROL at 0x501000f8; + + type EP15_OUT_BUFFER_CONTROL_t { + LENGTH_0 = uint10(0); // The length of the data in buffer 0. + AVAILABLE_0 = false; // Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + STALL = false; // Reply with a stall (valid for both buffers). + RESET = false; // Reset the buffer selector to buffer 0. + PID_0 = false; // The data pid of buffer 0. + LAST_0 = false; // Buffer 0 is the last buffer of the transfer. + FULL_0 = false; // Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + LENGTH_1 = uint10(0); // The length of the data in buffer 1. + AVAILABLE_1 = false; // Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + DOUBLE_BUFFER_ISO_OFFSET = uint2(0); // The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. For a non Isochronous endpoint the offset is always 64 bytes. + PID_1 = false; // The data pid of buffer 1. + LAST_1 = false; // Buffer 1 is the last buffer of the transfer. + FULL_1 = false; // Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + } + + // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + register EP15_OUT_BUFFER_CONTROL_t EP15_OUT_BUFFER_CONTROL at 0x501000fc; + + +/* Types and registers for TBMAN + Testbench manager. Allows the programmer to know what platform their software is running on. + */ + + type TBMAN_PLATFORM_t { + ASIC = false; // Indicates the platform is an ASIC + FPGA = false; // Indicates the platform is an FPGA + } + + // Indicates the type of platform in use + register TBMAN_PLATFORM_t TBMAN_PLATFORM at 0x4006c000; + + +/* Types and registers for VREG_AND_CHIP_RESET + control and status for on-chip voltage regulator and chip level reset subsystem + */ + + type VREG_t { + EN = false; // enable 0=not enabled, 1=enabled + HIZ = false; // high impedance mode select 0=not in high impedance mode, 1=in high impedance mode + _res1 = uint2(0); // Reserved, 2 bits + VSEL = uint4(0); // output voltage select 0000 to 0101 - 0.80V 0110 - 0.85V 0111 - 0.90V 1000 - 0.95V 1001 - 1.00V 1010 - 1.05V 1011 - 1.10V (default) 1100 - 1.15V 1101 - 1.20V 1110 - 1.25V 1111 - 1.30V + _res2 = uint4(0); // Reserved, 4 bits + ROK = false; // regulation status 0=not in regulation, 1=in regulation + } + + // Voltage regulator control and status + register VREG_t VREG at 0x40064000; + + type BOD_t { + EN = false; // enable 0=not enabled, 1=enabled + _res1 = uint3(0); // Reserved, 3 bits + VSEL = uint4(0); // threshold select 0000 - 0.473V 0001 - 0.516V 0010 - 0.559V 0011 - 0.602V 0100 - 0.645V 0101 - 0.688V 0110 - 0.731V 0111 - 0.774V 1000 - 0.817V 1001 - 0.860V (default) 1010 - 0.903V 1011 - 0.946V 1100 - 0.989V 1101 - 1.032V 1110 - 1.075V 1111 - 1.118V + } + + // brown-out detection control + register BOD_t BOD at 0x40064004; + + type CHIP_RESET_t { + _res1 = uint8(0); // Reserved, 8 bits + HAD_POR = false; // Last reset was from the power-on reset or brown-out detection blocks + _res2 = uint7(0); // Reserved, 7 bits + HAD_RUN = false; // Last reset was from the RUN pin + _res3 = uint3(0); // Reserved, 3 bits + HAD_PSM_RESTART = false; // Last reset was from the debug port + _res4 = uint3(0); // Reserved, 3 bits + PSM_RESTART_FLAG = false; // This is set by psm_restart from the debugger. Its purpose is to branch bootcode to a safe mode when the debugger has issued a psm_restart in order to recover from a boot lock-up. In the safe mode the debugger can repair the boot code, clear this flag then reboot the processor. + } + + // Chip reset control and status + register CHIP_RESET_t CHIP_RESET at 0x40064008; + + +/* Types and registers for RTC + Register block to control RTC + */ + + type CLKDIV_M1_t { + CLKDIV_M1 = uint16(0); // + } + + // Divider minus 1 for the 1 second counter. Safe to change the value when RTC is not enabled. + register CLKDIV_M1_t CLKDIV_M1 at 0x4005c000; + + type SETUP_0_t { + DAY = uint5(0); // Day of the month (1..31) + _res1 = uint3(0); // Reserved, 3 bits + MONTH = uint4(0); // Month (1..12) + YEAR = uint12(0); // Year + } + + // RTC setup register 0 + register SETUP_0_t SETUP_0 at 0x4005c004; + + type SETUP_1_t { + SEC = uint6(0); // Seconds + _res1 = uint2(0); // Reserved, 2 bits + MIN = uint6(0); // Minutes + _res2 = uint2(0); // Reserved, 2 bits + HOUR = uint5(0); // Hours + _res3 = uint3(0); // Reserved, 3 bits + DOTW = uint3(0); // Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7 + } + + // RTC setup register 1 + register SETUP_1_t SETUP_1 at 0x4005c008; + + type RTC_CTRL_t { + RTC_ENABLE = false; // Enable RTC + RTC_ACTIVE = false; // RTC enabled (running) + _res1 = uint2(0); // Reserved, 2 bits + LOAD = false; // Load RTC + _res2 = uint3(0); // Reserved, 3 bits + FORCE_NOTLEAPYEAR = false; // If set, leapyear is forced off. Useful for years divisible by 100 but not by 400 + } + + // RTC Control and status + register RTC_CTRL_t RTC_CTRL at 0x4005c00c; + + type IRQ_SETUP_0_t { + DAY = uint5(0); // Day of the month (1..31) + _res1 = uint3(0); // Reserved, 3 bits + MONTH = uint4(0); // Month (1..12) + YEAR = uint12(0); // Year + DAY_ENA = false; // Enable day matching + MONTH_ENA = false; // Enable month matching + YEAR_ENA = false; // Enable year matching + _res2 = false; // Reserved, 1 bits + MATCH_ENA = false; // Global match enable. Don't change any other value while this one is enabled + MATCH_ACTIVE = false; // + } + + // Interrupt setup register 0 + register IRQ_SETUP_0_t IRQ_SETUP_0 at 0x4005c010; + + type IRQ_SETUP_1_t { + SEC = uint6(0); // Seconds + _res1 = uint2(0); // Reserved, 2 bits + MIN = uint6(0); // Minutes + _res2 = uint2(0); // Reserved, 2 bits + HOUR = uint5(0); // Hours + _res3 = uint3(0); // Reserved, 3 bits + DOTW = uint3(0); // Day of the week + _res4 = false; // Reserved, 1 bits + SEC_ENA = false; // Enable second matching + MIN_ENA = false; // Enable minute matching + HOUR_ENA = false; // Enable hour matching + DOTW_ENA = false; // Enable day of the week matching + } + + // Interrupt setup register 1 + register IRQ_SETUP_1_t IRQ_SETUP_1 at 0x4005c014; + + type RTC_1_t { + DAY = uint5(0); // Day of the month (1..31) + _res1 = uint3(0); // Reserved, 3 bits + MONTH = uint4(0); // Month (1..12) + YEAR = uint12(0); // Year + } + + // RTC register 1. + register RTC_1_t RTC_1 at 0x4005c018; + + type RTC_0_t { + SEC = uint6(0); // Seconds + _res1 = uint2(0); // Reserved, 2 bits + MIN = uint6(0); // Minutes + _res2 = uint2(0); // Reserved, 2 bits + HOUR = uint5(0); // Hours + _res3 = uint3(0); // Reserved, 3 bits + DOTW = uint3(0); // Day of the week + } + + // RTC register 0 Read this before RTC 1! + register RTC_0_t RTC_0 at 0x4005c01c; + + type RTC_INTR_t { + RTC = false; // + } + + // Raw Interrupts + register RTC_INTR_t RTC_INTR at 0x4005c020; + + type RTC_INTE_t { + RTC = false; // + } + + // Interrupt Enable + register RTC_INTE_t RTC_INTE at 0x4005c024; + + type RTC_INTF_t { + RTC = false; // + } + + // Interrupt Force + register RTC_INTF_t RTC_INTF at 0x4005c028; + + type RTC_INTS_t { + RTC = false; // + } + + // Interrupt status after masking & forcing + register RTC_INTS_t RTC_INTS at 0x4005c02c; + diff --git a/lib/arch/rp/rp2040/rp2040.ld b/lib/arch/rp/rp2040/rp2040.ld new file mode 100644 index 0000000..f0e1dea --- /dev/null +++ b/lib/arch/rp/rp2040/rp2040.ld @@ -0,0 +1,87 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 2M + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 264K + /*qemu + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 2M + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 2K + */ +} + +__reset_stack_pointer = ORIGIN(RAM) + LENGTH(RAM); + +SECTIONS +{ + .boot2 : { + __boot2_start__ = .; + KEEP (*(.boot2)) + __boot2_end__ = .; + } > FLASH + + ASSERT(__boot2_end__ - __boot2_start__ == 256, + "ERROR: Pico second stage bootloader must be 256 bytes in size") + + .isr_vector : { + __isr_start = .; + LONG(__reset_stack_pointer); + LONG(__isr_reset | 1); + LONG(__error_handler | 1); /*isr nmi */ + LONG(__error_handler | 1); /*HardFault_Handler*/ + LONG(0); + LONG(0); + LONG(0); + LONG(0); + LONG(0); + LONG(__error_handler | 1); /*SVCall_Handler*/ + LONG(0); + LONG(0); + LONG(__error_handler | 1); /*PendSV_Handler*/ + LONG(__error_handler | 1); /*SysTick_Handler*/ + + /* The interrupt table is 192 bytes long. Advance to that position. */ + . = __isr_start + 192; + } > FLASH + + + .text : { + . = ALIGN(4); + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + . = ALIGN(4); + } > FLASH + + /* Machine inspectable binary information */ + . = ALIGN(4); + __binary_info_start = .; + .binary_info : + { + KEEP(*(.binary_info.keep.*)) + *(.binary_info.*) + } > RAM + __binary_info_end = .; + . = ALIGN(4); + + __data_init = LOADADDR(.data); + + .data : { + __data_start = .; + *(.data) + *(.data.*) + . = ALIGN(4); + __data_end = .; + } > RAM AT> FLASH + + .bss : + { + __bss_start = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + } > RAM + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/lib/arch/rp/rp2040/rp2040.svd b/lib/arch/rp/rp2040/rp2040.svd new file mode 100644 index 0000000..b372675 --- /dev/null +++ b/lib/arch/rp/rp2040/rp2040.svd @@ -0,0 +1,51245 @@ + + + + Raspberry Pi + RP2040 + RP + 0.1 + + Dual-core Arm Cortex-M0+ processor, flexible clock running up to 133 MHz + 264KB on-chip SRAM + 2 x UART, 2 x SPI controllers, 2 x I2C controllers, 16 x PWM channels + 1 x USB 1.1 controller and PHY, with host and device support + 8 x Programmable I/O (PIO) state machines for custom peripheral support + Supported input power 1.8-5.5V DC + Operating temperature -20C to +85C + Drag-and-drop programming using mass storage over USB + Low-power sleep and dormant modes + Accurate on-chip clock + Temperature sensor + Accelerated integer and floating-point libraries on-chip + + 32 + 32 + 0xffffffff + 0x00000000 + read-write + + Copyright (c) 2024 Raspberry Pi Ltd. + + SPDX-License-Identifier: BSD-3-Clause + + + CM0PLUS + r0p1 + little + true + false + 1 + 2 + false + 26 + + 8 + + + RESETS + 0x4000c000 + + 0 + 12 + registers + + + + RESET + 0x00000000 + Reset control. If a bit is set it means the peripheral is in reset. 0 means the peripheral's reset is deasserted. + 0x01ffffff + + + USBCTRL + [24:24] + read-write + + + UART1 + [23:23] + read-write + + + UART0 + [22:22] + read-write + + + TIMER + [21:21] + read-write + + + TBMAN + [20:20] + read-write + + + SYSINFO + [19:19] + read-write + + + SYSCFG + [18:18] + read-write + + + SPI1 + [17:17] + read-write + + + SPI0 + [16:16] + read-write + + + RTC + [15:15] + read-write + + + PWM + [14:14] + read-write + + + PLL_USB + [13:13] + read-write + + + PLL_SYS + [12:12] + read-write + + + PIO1 + [11:11] + read-write + + + PIO0 + [10:10] + read-write + + + PADS_QSPI + [9:9] + read-write + + + PADS_BANK0 + [8:8] + read-write + + + JTAG + [7:7] + read-write + + + IO_QSPI + [6:6] + read-write + + + IO_BANK0 + [5:5] + read-write + + + I2C1 + [4:4] + read-write + + + I2C0 + [3:3] + read-write + + + DMA + [2:2] + read-write + + + BUSCTRL + [1:1] + read-write + + + ADC + [0:0] + read-write + + + + + WDSEL + 0x00000004 + Watchdog select. If a bit is set then the watchdog will reset this peripheral when the watchdog fires. + 0x00000000 + + + USBCTRL + [24:24] + read-write + + + UART1 + [23:23] + read-write + + + UART0 + [22:22] + read-write + + + TIMER + [21:21] + read-write + + + TBMAN + [20:20] + read-write + + + SYSINFO + [19:19] + read-write + + + SYSCFG + [18:18] + read-write + + + SPI1 + [17:17] + read-write + + + SPI0 + [16:16] + read-write + + + RTC + [15:15] + read-write + + + PWM + [14:14] + read-write + + + PLL_USB + [13:13] + read-write + + + PLL_SYS + [12:12] + read-write + + + PIO1 + [11:11] + read-write + + + PIO0 + [10:10] + read-write + + + PADS_QSPI + [9:9] + read-write + + + PADS_BANK0 + [8:8] + read-write + + + JTAG + [7:7] + read-write + + + IO_QSPI + [6:6] + read-write + + + IO_BANK0 + [5:5] + read-write + + + I2C1 + [4:4] + read-write + + + I2C0 + [3:3] + read-write + + + DMA + [2:2] + read-write + + + BUSCTRL + [1:1] + read-write + + + ADC + [0:0] + read-write + + + + + RESET_DONE + 0x00000008 + Reset done. If a bit is set then a reset done signal has been returned by the peripheral. This indicates that the peripheral's registers are ready to be accessed. + 0x00000000 + + + USBCTRL + [24:24] + read-only + + + UART1 + [23:23] + read-only + + + UART0 + [22:22] + read-only + + + TIMER + [21:21] + read-only + + + TBMAN + [20:20] + read-only + + + SYSINFO + [19:19] + read-only + + + SYSCFG + [18:18] + read-only + + + SPI1 + [17:17] + read-only + + + SPI0 + [16:16] + read-only + + + RTC + [15:15] + read-only + + + PWM + [14:14] + read-only + + + PLL_USB + [13:13] + read-only + + + PLL_SYS + [12:12] + read-only + + + PIO1 + [11:11] + read-only + + + PIO0 + [10:10] + read-only + + + PADS_QSPI + [9:9] + read-only + + + PADS_BANK0 + [8:8] + read-only + + + JTAG + [7:7] + read-only + + + IO_QSPI + [6:6] + read-only + + + IO_BANK0 + [5:5] + read-only + + + I2C1 + [4:4] + read-only + + + I2C0 + [3:3] + read-only + + + DMA + [2:2] + read-only + + + BUSCTRL + [1:1] + read-only + + + ADC + [0:0] + read-only + + + + + + + PSM + 0x40010000 + + 0 + 16 + registers + + + + FRCE_ON + 0x00000000 + Force block out of reset (i.e. power it on) + 0x00000000 + + + PROC1 + [16:16] + read-write + + + PROC0 + [15:15] + read-write + + + SIO + [14:14] + read-write + + + VREG_AND_CHIP_RESET + [13:13] + read-write + + + XIP + [12:12] + read-write + + + SRAM5 + [11:11] + read-write + + + SRAM4 + [10:10] + read-write + + + SRAM3 + [9:9] + read-write + + + SRAM2 + [8:8] + read-write + + + SRAM1 + [7:7] + read-write + + + SRAM0 + [6:6] + read-write + + + ROM + [5:5] + read-write + + + BUSFABRIC + [4:4] + read-write + + + RESETS + [3:3] + read-write + + + CLOCKS + [2:2] + read-write + + + XOSC + [1:1] + read-write + + + ROSC + [0:0] + read-write + + + + + FRCE_OFF + 0x00000004 + Force into reset (i.e. power it off) + 0x00000000 + + + PROC1 + [16:16] + read-write + + + PROC0 + [15:15] + read-write + + + SIO + [14:14] + read-write + + + VREG_AND_CHIP_RESET + [13:13] + read-write + + + XIP + [12:12] + read-write + + + SRAM5 + [11:11] + read-write + + + SRAM4 + [10:10] + read-write + + + SRAM3 + [9:9] + read-write + + + SRAM2 + [8:8] + read-write + + + SRAM1 + [7:7] + read-write + + + SRAM0 + [6:6] + read-write + + + ROM + [5:5] + read-write + + + BUSFABRIC + [4:4] + read-write + + + RESETS + [3:3] + read-write + + + CLOCKS + [2:2] + read-write + + + XOSC + [1:1] + read-write + + + ROSC + [0:0] + read-write + + + + + WDSEL + 0x00000008 + Set to 1 if this peripheral should be reset when the watchdog fires. + 0x00000000 + + + PROC1 + [16:16] + read-write + + + PROC0 + [15:15] + read-write + + + SIO + [14:14] + read-write + + + VREG_AND_CHIP_RESET + [13:13] + read-write + + + XIP + [12:12] + read-write + + + SRAM5 + [11:11] + read-write + + + SRAM4 + [10:10] + read-write + + + SRAM3 + [9:9] + read-write + + + SRAM2 + [8:8] + read-write + + + SRAM1 + [7:7] + read-write + + + SRAM0 + [6:6] + read-write + + + ROM + [5:5] + read-write + + + BUSFABRIC + [4:4] + read-write + + + RESETS + [3:3] + read-write + + + CLOCKS + [2:2] + read-write + + + XOSC + [1:1] + read-write + + + ROSC + [0:0] + read-write + + + + + DONE + 0x0000000c + Indicates the peripheral's registers are ready to access. + 0x00000000 + + + PROC1 + [16:16] + read-only + + + PROC0 + [15:15] + read-only + + + SIO + [14:14] + read-only + + + VREG_AND_CHIP_RESET + [13:13] + read-only + + + XIP + [12:12] + read-only + + + SRAM5 + [11:11] + read-only + + + SRAM4 + [10:10] + read-only + + + SRAM3 + [9:9] + read-only + + + SRAM2 + [8:8] + read-only + + + SRAM1 + [7:7] + read-only + + + SRAM0 + [6:6] + read-only + + + ROM + [5:5] + read-only + + + BUSFABRIC + [4:4] + read-only + + + RESETS + [3:3] + read-only + + + CLOCKS + [2:2] + read-only + + + XOSC + [1:1] + read-only + + + ROSC + [0:0] + read-only + + + + + + + CLOCKS + 0x40008000 + + 0 + 200 + registers + + + CLOCKS_IRQ + 17 + + + + CLK_GPOUT0_CTRL + 0x00000000 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + DC50 + Enables duty cycle correction for odd divisors + [12:12] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [8:5] + read-write + + + clksrc_pll_sys + 0 + + + clksrc_gpin0 + 1 + + + clksrc_gpin1 + 2 + + + clksrc_pll_usb + 3 + + + rosc_clksrc + 4 + + + xosc_clksrc + 5 + + + clk_sys + 6 + + + clk_usb + 7 + + + clk_adc + 8 + + + clk_rtc + 9 + + + clk_ref + 10 + + + + + + + CLK_GPOUT0_DIV + 0x00000004 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_GPOUT0_SELECTED + 0x00000008 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_GPOUT0_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_GPOUT1_CTRL + 0x0000000c + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + DC50 + Enables duty cycle correction for odd divisors + [12:12] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [8:5] + read-write + + + clksrc_pll_sys + 0 + + + clksrc_gpin0 + 1 + + + clksrc_gpin1 + 2 + + + clksrc_pll_usb + 3 + + + rosc_clksrc + 4 + + + xosc_clksrc + 5 + + + clk_sys + 6 + + + clk_usb + 7 + + + clk_adc + 8 + + + clk_rtc + 9 + + + clk_ref + 10 + + + + + + + CLK_GPOUT1_DIV + 0x00000010 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_GPOUT1_SELECTED + 0x00000014 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_GPOUT1_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_GPOUT2_CTRL + 0x00000018 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + DC50 + Enables duty cycle correction for odd divisors + [12:12] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [8:5] + read-write + + + clksrc_pll_sys + 0 + + + clksrc_gpin0 + 1 + + + clksrc_gpin1 + 2 + + + clksrc_pll_usb + 3 + + + rosc_clksrc_ph + 4 + + + xosc_clksrc + 5 + + + clk_sys + 6 + + + clk_usb + 7 + + + clk_adc + 8 + + + clk_rtc + 9 + + + clk_ref + 10 + + + + + + + CLK_GPOUT2_DIV + 0x0000001c + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_GPOUT2_SELECTED + 0x00000020 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_GPOUT2_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_GPOUT3_CTRL + 0x00000024 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + DC50 + Enables duty cycle correction for odd divisors + [12:12] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [8:5] + read-write + + + clksrc_pll_sys + 0 + + + clksrc_gpin0 + 1 + + + clksrc_gpin1 + 2 + + + clksrc_pll_usb + 3 + + + rosc_clksrc_ph + 4 + + + xosc_clksrc + 5 + + + clk_sys + 6 + + + clk_usb + 7 + + + clk_adc + 8 + + + clk_rtc + 9 + + + clk_ref + 10 + + + + + + + CLK_GPOUT3_DIV + 0x00000028 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_GPOUT3_SELECTED + 0x0000002c + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_GPOUT3_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_REF_CTRL + 0x00000030 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [6:5] + read-write + + + clksrc_pll_usb + 0 + + + clksrc_gpin0 + 1 + + + clksrc_gpin1 + 2 + + + + + SRC + Selects the clock source glitchlessly, can be changed on-the-fly + [1:0] + read-write + + + rosc_clksrc_ph + 0 + + + clksrc_clk_ref_aux + 1 + + + xosc_clksrc + 2 + + + + + + + CLK_REF_DIV + 0x00000034 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [9:8] + read-write + + + + + CLK_REF_SELECTED + 0x00000038 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_REF_SELECTED + The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. + [31:0] + read-only + + + + + CLK_SYS_CTRL + 0x0000003c + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [7:5] + read-write + + + clksrc_pll_sys + 0 + + + clksrc_pll_usb + 1 + + + rosc_clksrc + 2 + + + xosc_clksrc + 3 + + + clksrc_gpin0 + 4 + + + clksrc_gpin1 + 5 + + + + + SRC + Selects the clock source glitchlessly, can be changed on-the-fly + [0:0] + read-write + + + clk_ref + 0 + + + clksrc_clk_sys_aux + 1 + + + + + + + CLK_SYS_DIV + 0x00000040 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_SYS_SELECTED + 0x00000044 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_SYS_SELECTED + The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. + [31:0] + read-only + + + + + CLK_PERI_CTRL + 0x00000048 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [7:5] + read-write + + + clk_sys + 0 + + + clksrc_pll_sys + 1 + + + clksrc_pll_usb + 2 + + + rosc_clksrc_ph + 3 + + + xosc_clksrc + 4 + + + clksrc_gpin0 + 5 + + + clksrc_gpin1 + 6 + + + + + + + CLK_PERI_DIV + 0x0000004c + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_PERI_SELECTED + 0x00000050 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_PERI_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_USB_CTRL + 0x00000054 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [7:5] + read-write + + + clksrc_pll_usb + 0 + + + clksrc_pll_sys + 1 + + + rosc_clksrc_ph + 2 + + + xosc_clksrc + 3 + + + clksrc_gpin0 + 4 + + + clksrc_gpin1 + 5 + + + + + + + CLK_USB_DIV + 0x00000058 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [9:8] + read-write + + + + + CLK_USB_SELECTED + 0x0000005c + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_USB_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_ADC_CTRL + 0x00000060 + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [7:5] + read-write + + + clksrc_pll_usb + 0 + + + clksrc_pll_sys + 1 + + + rosc_clksrc_ph + 2 + + + xosc_clksrc + 3 + + + clksrc_gpin0 + 4 + + + clksrc_gpin1 + 5 + + + + + + + CLK_ADC_DIV + 0x00000064 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [9:8] + read-write + + + + + CLK_ADC_SELECTED + 0x00000068 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_ADC_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_RTC_CTRL + 0x0000006c + Clock control, can be changed on-the-fly (except for auxsrc) + 0x00000000 + + + NUDGE + An edge on this signal shifts the phase of the output by 1 cycle of the input clock + This can be done at any time + [20:20] + read-write + + + PHASE + This delays the enable signal by up to 3 cycles of the input clock + This must be set before the clock is enabled to have any effect + [17:16] + read-write + + + ENABLE + Starts and stops the clock generator cleanly + [11:11] + read-write + + + KILL + Asynchronously kills the clock generator + [10:10] + read-write + + + AUXSRC + Selects the auxiliary clock source, will glitch when switching + [7:5] + read-write + + + clksrc_pll_usb + 0 + + + clksrc_pll_sys + 1 + + + rosc_clksrc_ph + 2 + + + xosc_clksrc + 3 + + + clksrc_gpin0 + 4 + + + clksrc_gpin1 + 5 + + + + + + + CLK_RTC_DIV + 0x00000070 + Clock divisor, can be changed on-the-fly + 0x00000100 + + + INT + Integer component of the divisor, 0 -> divide by 2^16 + [31:8] + read-write + + + FRAC + Fractional component of the divisor + [7:0] + read-write + + + + + CLK_RTC_SELECTED + 0x00000074 + Indicates which SRC is currently selected by the glitchless mux (one-hot). + 0x00000001 + + + CLK_RTC_SELECTED + This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. + [31:0] + read-only + + + + + CLK_SYS_RESUS_CTRL + 0x00000078 + 0x000000ff + + + CLEAR + For clearing the resus after the fault that triggered it has been corrected + [16:16] + read-write + + + FRCE + Force a resus, for test purposes only + [12:12] + read-write + + + ENABLE + Enable resus + [8:8] + read-write + + + TIMEOUT + This is expressed as a number of clk_ref cycles + and must be >= 2x clk_ref_freq/min_clk_tst_freq + [7:0] + read-write + + + + + CLK_SYS_RESUS_STATUS + 0x0000007c + 0x00000000 + + + RESUSSED + Clock has been resuscitated, correct the error then send ctrl_clear=1 + [0:0] + read-only + + + + + FC0_REF_KHZ + 0x00000080 + Reference clock frequency in kHz + 0x00000000 + + + FC0_REF_KHZ + [19:0] + read-write + + + + + FC0_MIN_KHZ + 0x00000084 + Minimum pass frequency in kHz. This is optional. Set to 0 if you are not using the pass/fail flags + 0x00000000 + + + FC0_MIN_KHZ + [24:0] + read-write + + + + + FC0_MAX_KHZ + 0x00000088 + Maximum pass frequency in kHz. This is optional. Set to 0x1ffffff if you are not using the pass/fail flags + 0x01ffffff + + + FC0_MAX_KHZ + [24:0] + read-write + + + + + FC0_DELAY + 0x0000008c + Delays the start of frequency counting to allow the mux to settle + Delay is measured in multiples of the reference clock period + 0x00000001 + + + FC0_DELAY + [2:0] + read-write + + + + + FC0_INTERVAL + 0x00000090 + The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval + The default gives a test interval of 250us + 0x00000008 + + + FC0_INTERVAL + [3:0] + read-write + + + + + FC0_SRC + 0x00000094 + Clock sent to frequency counter, set to 0 when not required + Writing to this register initiates the frequency count + 0x00000000 + + + FC0_SRC + [7:0] + read-write + + + NULL + 0 + + + pll_sys_clksrc_primary + 1 + + + pll_usb_clksrc_primary + 2 + + + rosc_clksrc + 3 + + + rosc_clksrc_ph + 4 + + + xosc_clksrc + 5 + + + clksrc_gpin0 + 6 + + + clksrc_gpin1 + 7 + + + clk_ref + 8 + + + clk_sys + 9 + + + clk_peri + 10 + + + clk_usb + 11 + + + clk_adc + 12 + + + clk_rtc + 13 + + + + + + + FC0_STATUS + 0x00000098 + Frequency counter status + 0x00000000 + + + DIED + Test clock stopped during test + [28:28] + read-only + + + FAST + Test clock faster than expected, only valid when status_done=1 + [24:24] + read-only + + + SLOW + Test clock slower than expected, only valid when status_done=1 + [20:20] + read-only + + + FAIL + Test failed + [16:16] + read-only + + + WAITING + Waiting for test clock to start + [12:12] + read-only + + + RUNNING + Test running + [8:8] + read-only + + + DONE + Test complete + [4:4] + read-only + + + PASS + Test passed + [0:0] + read-only + + + + + FC0_RESULT + 0x0000009c + Result of frequency measurement, only valid when status_done=1 + 0x00000000 + + + KHZ + [29:5] + read-only + + + FRAC + [4:0] + read-only + + + + + WAKE_EN0 + 0x000000a0 + enable clock in wake mode + 0xffffffff + + + CLK_SYS_SRAM3 + [31:31] + read-write + + + CLK_SYS_SRAM2 + [30:30] + read-write + + + CLK_SYS_SRAM1 + [29:29] + read-write + + + CLK_SYS_SRAM0 + [28:28] + read-write + + + CLK_SYS_SPI1 + [27:27] + read-write + + + CLK_PERI_SPI1 + [26:26] + read-write + + + CLK_SYS_SPI0 + [25:25] + read-write + + + CLK_PERI_SPI0 + [24:24] + read-write + + + CLK_SYS_SIO + [23:23] + read-write + + + CLK_SYS_RTC + [22:22] + read-write + + + CLK_RTC_RTC + [21:21] + read-write + + + CLK_SYS_ROSC + [20:20] + read-write + + + CLK_SYS_ROM + [19:19] + read-write + + + CLK_SYS_RESETS + [18:18] + read-write + + + CLK_SYS_PWM + [17:17] + read-write + + + CLK_SYS_PSM + [16:16] + read-write + + + CLK_SYS_PLL_USB + [15:15] + read-write + + + CLK_SYS_PLL_SYS + [14:14] + read-write + + + CLK_SYS_PIO1 + [13:13] + read-write + + + CLK_SYS_PIO0 + [12:12] + read-write + + + CLK_SYS_PADS + [11:11] + read-write + + + CLK_SYS_VREG_AND_CHIP_RESET + [10:10] + read-write + + + CLK_SYS_JTAG + [9:9] + read-write + + + CLK_SYS_IO + [8:8] + read-write + + + CLK_SYS_I2C1 + [7:7] + read-write + + + CLK_SYS_I2C0 + [6:6] + read-write + + + CLK_SYS_DMA + [5:5] + read-write + + + CLK_SYS_BUSFABRIC + [4:4] + read-write + + + CLK_SYS_BUSCTRL + [3:3] + read-write + + + CLK_SYS_ADC + [2:2] + read-write + + + CLK_ADC_ADC + [1:1] + read-write + + + CLK_SYS_CLOCKS + [0:0] + read-write + + + + + WAKE_EN1 + 0x000000a4 + enable clock in wake mode + 0x00007fff + + + CLK_SYS_XOSC + [14:14] + read-write + + + CLK_SYS_XIP + [13:13] + read-write + + + CLK_SYS_WATCHDOG + [12:12] + read-write + + + CLK_USB_USBCTRL + [11:11] + read-write + + + CLK_SYS_USBCTRL + [10:10] + read-write + + + CLK_SYS_UART1 + [9:9] + read-write + + + CLK_PERI_UART1 + [8:8] + read-write + + + CLK_SYS_UART0 + [7:7] + read-write + + + CLK_PERI_UART0 + [6:6] + read-write + + + CLK_SYS_TIMER + [5:5] + read-write + + + CLK_SYS_TBMAN + [4:4] + read-write + + + CLK_SYS_SYSINFO + [3:3] + read-write + + + CLK_SYS_SYSCFG + [2:2] + read-write + + + CLK_SYS_SRAM5 + [1:1] + read-write + + + CLK_SYS_SRAM4 + [0:0] + read-write + + + + + SLEEP_EN0 + 0x000000a8 + enable clock in sleep mode + 0xffffffff + + + CLK_SYS_SRAM3 + [31:31] + read-write + + + CLK_SYS_SRAM2 + [30:30] + read-write + + + CLK_SYS_SRAM1 + [29:29] + read-write + + + CLK_SYS_SRAM0 + [28:28] + read-write + + + CLK_SYS_SPI1 + [27:27] + read-write + + + CLK_PERI_SPI1 + [26:26] + read-write + + + CLK_SYS_SPI0 + [25:25] + read-write + + + CLK_PERI_SPI0 + [24:24] + read-write + + + CLK_SYS_SIO + [23:23] + read-write + + + CLK_SYS_RTC + [22:22] + read-write + + + CLK_RTC_RTC + [21:21] + read-write + + + CLK_SYS_ROSC + [20:20] + read-write + + + CLK_SYS_ROM + [19:19] + read-write + + + CLK_SYS_RESETS + [18:18] + read-write + + + CLK_SYS_PWM + [17:17] + read-write + + + CLK_SYS_PSM + [16:16] + read-write + + + CLK_SYS_PLL_USB + [15:15] + read-write + + + CLK_SYS_PLL_SYS + [14:14] + read-write + + + CLK_SYS_PIO1 + [13:13] + read-write + + + CLK_SYS_PIO0 + [12:12] + read-write + + + CLK_SYS_PADS + [11:11] + read-write + + + CLK_SYS_VREG_AND_CHIP_RESET + [10:10] + read-write + + + CLK_SYS_JTAG + [9:9] + read-write + + + CLK_SYS_IO + [8:8] + read-write + + + CLK_SYS_I2C1 + [7:7] + read-write + + + CLK_SYS_I2C0 + [6:6] + read-write + + + CLK_SYS_DMA + [5:5] + read-write + + + CLK_SYS_BUSFABRIC + [4:4] + read-write + + + CLK_SYS_BUSCTRL + [3:3] + read-write + + + CLK_SYS_ADC + [2:2] + read-write + + + CLK_ADC_ADC + [1:1] + read-write + + + CLK_SYS_CLOCKS + [0:0] + read-write + + + + + SLEEP_EN1 + 0x000000ac + enable clock in sleep mode + 0x00007fff + + + CLK_SYS_XOSC + [14:14] + read-write + + + CLK_SYS_XIP + [13:13] + read-write + + + CLK_SYS_WATCHDOG + [12:12] + read-write + + + CLK_USB_USBCTRL + [11:11] + read-write + + + CLK_SYS_USBCTRL + [10:10] + read-write + + + CLK_SYS_UART1 + [9:9] + read-write + + + CLK_PERI_UART1 + [8:8] + read-write + + + CLK_SYS_UART0 + [7:7] + read-write + + + CLK_PERI_UART0 + [6:6] + read-write + + + CLK_SYS_TIMER + [5:5] + read-write + + + CLK_SYS_TBMAN + [4:4] + read-write + + + CLK_SYS_SYSINFO + [3:3] + read-write + + + CLK_SYS_SYSCFG + [2:2] + read-write + + + CLK_SYS_SRAM5 + [1:1] + read-write + + + CLK_SYS_SRAM4 + [0:0] + read-write + + + + + ENABLED0 + 0x000000b0 + indicates the state of the clock enable + 0x00000000 + + + CLK_SYS_SRAM3 + [31:31] + read-only + + + CLK_SYS_SRAM2 + [30:30] + read-only + + + CLK_SYS_SRAM1 + [29:29] + read-only + + + CLK_SYS_SRAM0 + [28:28] + read-only + + + CLK_SYS_SPI1 + [27:27] + read-only + + + CLK_PERI_SPI1 + [26:26] + read-only + + + CLK_SYS_SPI0 + [25:25] + read-only + + + CLK_PERI_SPI0 + [24:24] + read-only + + + CLK_SYS_SIO + [23:23] + read-only + + + CLK_SYS_RTC + [22:22] + read-only + + + CLK_RTC_RTC + [21:21] + read-only + + + CLK_SYS_ROSC + [20:20] + read-only + + + CLK_SYS_ROM + [19:19] + read-only + + + CLK_SYS_RESETS + [18:18] + read-only + + + CLK_SYS_PWM + [17:17] + read-only + + + CLK_SYS_PSM + [16:16] + read-only + + + CLK_SYS_PLL_USB + [15:15] + read-only + + + CLK_SYS_PLL_SYS + [14:14] + read-only + + + CLK_SYS_PIO1 + [13:13] + read-only + + + CLK_SYS_PIO0 + [12:12] + read-only + + + CLK_SYS_PADS + [11:11] + read-only + + + CLK_SYS_VREG_AND_CHIP_RESET + [10:10] + read-only + + + CLK_SYS_JTAG + [9:9] + read-only + + + CLK_SYS_IO + [8:8] + read-only + + + CLK_SYS_I2C1 + [7:7] + read-only + + + CLK_SYS_I2C0 + [6:6] + read-only + + + CLK_SYS_DMA + [5:5] + read-only + + + CLK_SYS_BUSFABRIC + [4:4] + read-only + + + CLK_SYS_BUSCTRL + [3:3] + read-only + + + CLK_SYS_ADC + [2:2] + read-only + + + CLK_ADC_ADC + [1:1] + read-only + + + CLK_SYS_CLOCKS + [0:0] + read-only + + + + + ENABLED1 + 0x000000b4 + indicates the state of the clock enable + 0x00000000 + + + CLK_SYS_XOSC + [14:14] + read-only + + + CLK_SYS_XIP + [13:13] + read-only + + + CLK_SYS_WATCHDOG + [12:12] + read-only + + + CLK_USB_USBCTRL + [11:11] + read-only + + + CLK_SYS_USBCTRL + [10:10] + read-only + + + CLK_SYS_UART1 + [9:9] + read-only + + + CLK_PERI_UART1 + [8:8] + read-only + + + CLK_SYS_UART0 + [7:7] + read-only + + + CLK_PERI_UART0 + [6:6] + read-only + + + CLK_SYS_TIMER + [5:5] + read-only + + + CLK_SYS_TBMAN + [4:4] + read-only + + + CLK_SYS_SYSINFO + [3:3] + read-only + + + CLK_SYS_SYSCFG + [2:2] + read-only + + + CLK_SYS_SRAM5 + [1:1] + read-only + + + CLK_SYS_SRAM4 + [0:0] + read-only + + + + + INTR + 0x000000b8 + Raw Interrupts + 0x00000000 + + + CLK_SYS_RESUS + [0:0] + read-only + + + + + INTE + 0x000000bc + Interrupt Enable + 0x00000000 + + + CLK_SYS_RESUS + [0:0] + read-write + + + + + INTF + 0x000000c0 + Interrupt Force + 0x00000000 + + + CLK_SYS_RESUS + [0:0] + read-write + + + + + INTS + 0x000000c4 + Interrupt status after masking & forcing + 0x00000000 + + + CLK_SYS_RESUS + [0:0] + read-only + + + + + + + PADS_BANK0 + 0x4001c000 + + 0 + 132 + registers + + + + VOLTAGE_SELECT + 0x00000000 + Voltage select. Per bank control + 0x00000000 + + + VOLTAGE_SELECT + [0:0] + read-write + + + 3v3 + 0 + Set voltage to 3.3V (DVDD >= 2V5) + + + 1v8 + 1 + Set voltage to 1.8V (DVDD <= 1V8) + + + + + + + GPIO0 + 0x00000004 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO1 + 0x00000008 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO2 + 0x0000000c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO3 + 0x00000010 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO4 + 0x00000014 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO5 + 0x00000018 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO6 + 0x0000001c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO7 + 0x00000020 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO8 + 0x00000024 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO9 + 0x00000028 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO10 + 0x0000002c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO11 + 0x00000030 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO12 + 0x00000034 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO13 + 0x00000038 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO14 + 0x0000003c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO15 + 0x00000040 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO16 + 0x00000044 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO17 + 0x00000048 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO18 + 0x0000004c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO19 + 0x00000050 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO20 + 0x00000054 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO21 + 0x00000058 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO22 + 0x0000005c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO23 + 0x00000060 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO24 + 0x00000064 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO25 + 0x00000068 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO26 + 0x0000006c + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO27 + 0x00000070 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO28 + 0x00000074 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO29 + 0x00000078 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + SWCLK + 0x0000007c + Pad control register + 0x000000da + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + SWD + 0x00000080 + Pad control register + 0x0000005a + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + + + PADS_QSPI + 0x40020000 + + 0 + 28 + registers + + + + VOLTAGE_SELECT + 0x00000000 + Voltage select. Per bank control + 0x00000000 + + + VOLTAGE_SELECT + [0:0] + read-write + + + 3v3 + 0 + Set voltage to 3.3V (DVDD >= 2V5) + + + 1v8 + 1 + Set voltage to 1.8V (DVDD <= 1V8) + + + + + + + GPIO_QSPI_SCLK + 0x00000004 + Pad control register + 0x00000056 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO_QSPI_SD0 + 0x00000008 + Pad control register + 0x00000052 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO_QSPI_SD1 + 0x0000000c + Pad control register + 0x00000052 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO_QSPI_SD2 + 0x00000010 + Pad control register + 0x00000052 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO_QSPI_SD3 + 0x00000014 + Pad control register + 0x00000052 + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + GPIO_QSPI_SS + 0x00000018 + Pad control register + 0x0000005a + + + OD + Output disable. Has priority over output enable from peripherals + [7:7] + read-write + + + IE + Input enable + [6:6] + read-write + + + DRIVE + Drive strength. + [5:4] + read-write + + + 2mA + 0 + + + 4mA + 1 + + + 8mA + 2 + + + 12mA + 3 + + + + + PUE + Pull up enable + [3:3] + read-write + + + PDE + Pull down enable + [2:2] + read-write + + + SCHMITT + Enable schmitt trigger + [1:1] + read-write + + + SLEWFAST + Slew rate control. 1 = Fast, 0 = Slow + [0:0] + read-write + + + + + + + IO_QSPI + 0x40018000 + + 0 + 88 + registers + + + IO_IRQ_QSPI + 14 + + + + GPIO_QSPI_SCLK_STATUS + 0x00000000 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SCLK_CTRL + 0x00000004 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_sclk + 0 + + + sio_30 + 5 + + + null + 31 + + + + + + + GPIO_QSPI_SS_STATUS + 0x00000008 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SS_CTRL + 0x0000000c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_ss_n + 0 + + + sio_31 + 5 + + + null + 31 + + + + + + + GPIO_QSPI_SD0_STATUS + 0x00000010 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SD0_CTRL + 0x00000014 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_sd0 + 0 + + + sio_32 + 5 + + + null + 31 + + + + + + + GPIO_QSPI_SD1_STATUS + 0x00000018 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SD1_CTRL + 0x0000001c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_sd1 + 0 + + + sio_33 + 5 + + + null + 31 + + + + + + + GPIO_QSPI_SD2_STATUS + 0x00000020 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SD2_CTRL + 0x00000024 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_sd2 + 0 + + + sio_34 + 5 + + + null + 31 + + + + + + + GPIO_QSPI_SD3_STATUS + 0x00000028 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO_QSPI_SD3_CTRL + 0x0000002c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + xip_sd3 + 0 + + + sio_35 + 5 + + + null + 31 + + + + + + + INTR + 0x00000030 + Raw Interrupts + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + oneToClear + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + oneToClear + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-only + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-only + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + oneToClear + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + oneToClear + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-only + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-only + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + oneToClear + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + oneToClear + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-only + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-only + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + oneToClear + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + oneToClear + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-only + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-only + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + oneToClear + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + oneToClear + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-only + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-only + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + oneToClear + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + oneToClear + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-only + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-only + + + + + PROC0_INTE + 0x00000034 + Interrupt Enable for proc0 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTF + 0x00000038 + Interrupt Force for proc0 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTS + 0x0000003c + Interrupt status after masking & forcing for proc0 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-only + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-only + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-only + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-only + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-only + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-only + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-only + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-only + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-only + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-only + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-only + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-only + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-only + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-only + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-only + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-only + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-only + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-only + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-only + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-only + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-only + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-only + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-only + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-only + + + + + PROC1_INTE + 0x00000040 + Interrupt Enable for proc1 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTF + 0x00000044 + Interrupt Force for proc1 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTS + 0x00000048 + Interrupt status after masking & forcing for proc1 + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-only + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-only + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-only + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-only + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-only + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-only + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-only + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-only + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-only + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-only + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-only + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-only + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-only + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-only + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-only + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-only + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-only + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-only + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-only + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-only + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-only + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-only + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-only + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-only + + + + + DORMANT_WAKE_INTE + 0x0000004c + Interrupt Enable for dormant_wake + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTF + 0x00000050 + Interrupt Force for dormant_wake + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-write + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-write + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-write + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-write + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-write + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-write + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-write + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-write + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-write + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-write + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-write + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-write + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-write + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-write + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-write + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-write + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-write + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-write + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-write + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-write + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-write + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-write + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-write + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTS + 0x00000054 + Interrupt status after masking & forcing for dormant_wake + 0x00000000 + + + GPIO_QSPI_SD3_EDGE_HIGH + [23:23] + read-only + + + GPIO_QSPI_SD3_EDGE_LOW + [22:22] + read-only + + + GPIO_QSPI_SD3_LEVEL_HIGH + [21:21] + read-only + + + GPIO_QSPI_SD3_LEVEL_LOW + [20:20] + read-only + + + GPIO_QSPI_SD2_EDGE_HIGH + [19:19] + read-only + + + GPIO_QSPI_SD2_EDGE_LOW + [18:18] + read-only + + + GPIO_QSPI_SD2_LEVEL_HIGH + [17:17] + read-only + + + GPIO_QSPI_SD2_LEVEL_LOW + [16:16] + read-only + + + GPIO_QSPI_SD1_EDGE_HIGH + [15:15] + read-only + + + GPIO_QSPI_SD1_EDGE_LOW + [14:14] + read-only + + + GPIO_QSPI_SD1_LEVEL_HIGH + [13:13] + read-only + + + GPIO_QSPI_SD1_LEVEL_LOW + [12:12] + read-only + + + GPIO_QSPI_SD0_EDGE_HIGH + [11:11] + read-only + + + GPIO_QSPI_SD0_EDGE_LOW + [10:10] + read-only + + + GPIO_QSPI_SD0_LEVEL_HIGH + [9:9] + read-only + + + GPIO_QSPI_SD0_LEVEL_LOW + [8:8] + read-only + + + GPIO_QSPI_SS_EDGE_HIGH + [7:7] + read-only + + + GPIO_QSPI_SS_EDGE_LOW + [6:6] + read-only + + + GPIO_QSPI_SS_LEVEL_HIGH + [5:5] + read-only + + + GPIO_QSPI_SS_LEVEL_LOW + [4:4] + read-only + + + GPIO_QSPI_SCLK_EDGE_HIGH + [3:3] + read-only + + + GPIO_QSPI_SCLK_EDGE_LOW + [2:2] + read-only + + + GPIO_QSPI_SCLK_LEVEL_HIGH + [1:1] + read-only + + + GPIO_QSPI_SCLK_LEVEL_LOW + [0:0] + read-only + + + + + + + IO_BANK0 + 0x40014000 + + 0 + 400 + registers + + + IO_IRQ_BANK0 + 13 + + + + GPIO0_STATUS + 0x00000000 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO0_CTRL + 0x00000004 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + jtag_tck + 0 + + + spi0_rx + 1 + + + uart0_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_0 + 4 + + + sio_0 + 5 + + + pio0_0 + 6 + + + pio1_0 + 7 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO1_STATUS + 0x00000008 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO1_CTRL + 0x0000000c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + jtag_tms + 0 + + + spi0_ss_n + 1 + + + uart0_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_0 + 4 + + + sio_1 + 5 + + + pio0_1 + 6 + + + pio1_1 + 7 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO2_STATUS + 0x00000010 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO2_CTRL + 0x00000014 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + jtag_tdi + 0 + + + spi0_sclk + 1 + + + uart0_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_1 + 4 + + + sio_2 + 5 + + + pio0_2 + 6 + + + pio1_2 + 7 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO3_STATUS + 0x00000018 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO3_CTRL + 0x0000001c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + jtag_tdo + 0 + + + spi0_tx + 1 + + + uart0_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_1 + 4 + + + sio_3 + 5 + + + pio0_3 + 6 + + + pio1_3 + 7 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO4_STATUS + 0x00000020 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO4_CTRL + 0x00000024 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_rx + 1 + + + uart1_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_2 + 4 + + + sio_4 + 5 + + + pio0_4 + 6 + + + pio1_4 + 7 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO5_STATUS + 0x00000028 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO5_CTRL + 0x0000002c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_ss_n + 1 + + + uart1_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_2 + 4 + + + sio_5 + 5 + + + pio0_5 + 6 + + + pio1_5 + 7 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO6_STATUS + 0x00000030 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO6_CTRL + 0x00000034 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_sclk + 1 + + + uart1_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_3 + 4 + + + sio_6 + 5 + + + pio0_6 + 6 + + + pio1_6 + 7 + + + usb_muxing_extphy_softcon + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO7_STATUS + 0x00000038 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO7_CTRL + 0x0000003c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_tx + 1 + + + uart1_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_3 + 4 + + + sio_7 + 5 + + + pio0_7 + 6 + + + pio1_7 + 7 + + + usb_muxing_extphy_oe_n + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO8_STATUS + 0x00000040 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO8_CTRL + 0x00000044 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_rx + 1 + + + uart1_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_4 + 4 + + + sio_8 + 5 + + + pio0_8 + 6 + + + pio1_8 + 7 + + + usb_muxing_extphy_rcv + 8 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO9_STATUS + 0x00000048 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO9_CTRL + 0x0000004c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_ss_n + 1 + + + uart1_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_4 + 4 + + + sio_9 + 5 + + + pio0_9 + 6 + + + pio1_9 + 7 + + + usb_muxing_extphy_vp + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO10_STATUS + 0x00000050 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO10_CTRL + 0x00000054 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_sclk + 1 + + + uart1_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_5 + 4 + + + sio_10 + 5 + + + pio0_10 + 6 + + + pio1_10 + 7 + + + usb_muxing_extphy_vm + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO11_STATUS + 0x00000058 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO11_CTRL + 0x0000005c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_tx + 1 + + + uart1_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_5 + 4 + + + sio_11 + 5 + + + pio0_11 + 6 + + + pio1_11 + 7 + + + usb_muxing_extphy_suspnd + 8 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO12_STATUS + 0x00000060 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO12_CTRL + 0x00000064 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_rx + 1 + + + uart0_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_6 + 4 + + + sio_12 + 5 + + + pio0_12 + 6 + + + pio1_12 + 7 + + + usb_muxing_extphy_speed + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO13_STATUS + 0x00000068 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO13_CTRL + 0x0000006c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_ss_n + 1 + + + uart0_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_6 + 4 + + + sio_13 + 5 + + + pio0_13 + 6 + + + pio1_13 + 7 + + + usb_muxing_extphy_vpo + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO14_STATUS + 0x00000070 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO14_CTRL + 0x00000074 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_sclk + 1 + + + uart0_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_7 + 4 + + + sio_14 + 5 + + + pio0_14 + 6 + + + pio1_14 + 7 + + + usb_muxing_extphy_vmo + 8 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO15_STATUS + 0x00000078 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO15_CTRL + 0x0000007c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_tx + 1 + + + uart0_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_7 + 4 + + + sio_15 + 5 + + + pio0_15 + 6 + + + pio1_15 + 7 + + + usb_muxing_digital_dp + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO16_STATUS + 0x00000080 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO16_CTRL + 0x00000084 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_rx + 1 + + + uart0_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_0 + 4 + + + sio_16 + 5 + + + pio0_16 + 6 + + + pio1_16 + 7 + + + usb_muxing_digital_dm + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO17_STATUS + 0x00000088 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO17_CTRL + 0x0000008c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_ss_n + 1 + + + uart0_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_0 + 4 + + + sio_17 + 5 + + + pio0_17 + 6 + + + pio1_17 + 7 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO18_STATUS + 0x00000090 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO18_CTRL + 0x00000094 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_sclk + 1 + + + uart0_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_1 + 4 + + + sio_18 + 5 + + + pio0_18 + 6 + + + pio1_18 + 7 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO19_STATUS + 0x00000098 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO19_CTRL + 0x0000009c + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_tx + 1 + + + uart0_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_1 + 4 + + + sio_19 + 5 + + + pio0_19 + 6 + + + pio1_19 + 7 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO20_STATUS + 0x000000a0 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO20_CTRL + 0x000000a4 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_rx + 1 + + + uart1_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_2 + 4 + + + sio_20 + 5 + + + pio0_20 + 6 + + + pio1_20 + 7 + + + clocks_gpin_0 + 8 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO21_STATUS + 0x000000a8 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO21_CTRL + 0x000000ac + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_ss_n + 1 + + + uart1_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_2 + 4 + + + sio_21 + 5 + + + pio0_21 + 6 + + + pio1_21 + 7 + + + clocks_gpout_0 + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO22_STATUS + 0x000000b0 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO22_CTRL + 0x000000b4 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_sclk + 1 + + + uart1_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_3 + 4 + + + sio_22 + 5 + + + pio0_22 + 6 + + + pio1_22 + 7 + + + clocks_gpin_1 + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO23_STATUS + 0x000000b8 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO23_CTRL + 0x000000bc + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi0_tx + 1 + + + uart1_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_3 + 4 + + + sio_23 + 5 + + + pio0_23 + 6 + + + pio1_23 + 7 + + + clocks_gpout_1 + 8 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO24_STATUS + 0x000000c0 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO24_CTRL + 0x000000c4 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_rx + 1 + + + uart1_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_4 + 4 + + + sio_24 + 5 + + + pio0_24 + 6 + + + pio1_24 + 7 + + + clocks_gpout_2 + 8 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO25_STATUS + 0x000000c8 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO25_CTRL + 0x000000cc + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_ss_n + 1 + + + uart1_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_4 + 4 + + + sio_25 + 5 + + + pio0_25 + 6 + + + pio1_25 + 7 + + + clocks_gpout_3 + 8 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO26_STATUS + 0x000000d0 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO26_CTRL + 0x000000d4 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_sclk + 1 + + + uart1_cts + 2 + + + i2c1_sda + 3 + + + pwm_a_5 + 4 + + + sio_26 + 5 + + + pio0_26 + 6 + + + pio1_26 + 7 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + GPIO27_STATUS + 0x000000d8 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO27_CTRL + 0x000000dc + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_tx + 1 + + + uart1_rts + 2 + + + i2c1_scl + 3 + + + pwm_b_5 + 4 + + + sio_27 + 5 + + + pio0_27 + 6 + + + pio1_27 + 7 + + + usb_muxing_overcurr_detect + 9 + + + null + 31 + + + + + + + GPIO28_STATUS + 0x000000e0 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO28_CTRL + 0x000000e4 + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_rx + 1 + + + uart0_tx + 2 + + + i2c0_sda + 3 + + + pwm_a_6 + 4 + + + sio_28 + 5 + + + pio0_28 + 6 + + + pio1_28 + 7 + + + usb_muxing_vbus_detect + 9 + + + null + 31 + + + + + + + GPIO29_STATUS + 0x000000e8 + GPIO status + 0x00000000 + + + IRQTOPROC + interrupt to processors, after override is applied + [26:26] + read-only + + + IRQFROMPAD + interrupt from pad before override is applied + [24:24] + read-only + + + INTOPERI + input signal to peripheral, after override is applied + [19:19] + read-only + + + INFROMPAD + input signal from pad, before override is applied + [17:17] + read-only + + + OETOPAD + output enable to pad after register override is applied + [13:13] + read-only + + + OEFROMPERI + output enable from selected peripheral, before register override is applied + [12:12] + read-only + + + OUTTOPAD + output signal to pad after register override is applied + [9:9] + read-only + + + OUTFROMPERI + output signal from selected peripheral, before register override is applied + [8:8] + read-only + + + + + GPIO29_CTRL + 0x000000ec + GPIO control including function select and overrides. + 0x0000001f + + + IRQOVER + [29:28] + read-write + + + NORMAL + 0 + don't invert the interrupt + + + INVERT + 1 + invert the interrupt + + + LOW + 2 + drive interrupt low + + + HIGH + 3 + drive interrupt high + + + + + INOVER + [17:16] + read-write + + + NORMAL + 0 + don't invert the peri input + + + INVERT + 1 + invert the peri input + + + LOW + 2 + drive peri input low + + + HIGH + 3 + drive peri input high + + + + + OEOVER + [13:12] + read-write + + + NORMAL + 0 + drive output enable from peripheral signal selected by funcsel + + + INVERT + 1 + drive output enable from inverse of peripheral signal selected by funcsel + + + DISABLE + 2 + disable output + + + ENABLE + 3 + enable output + + + + + OUTOVER + [9:8] + read-write + + + NORMAL + 0 + drive output from peripheral signal selected by funcsel + + + INVERT + 1 + drive output from inverse of peripheral signal selected by funcsel + + + LOW + 2 + drive output low + + + HIGH + 3 + drive output high + + + + + FUNCSEL + 0-31 -> selects pin function according to the gpio table + 31 == NULL + [4:0] + read-write + + + spi1_ss_n + 1 + + + uart0_rx + 2 + + + i2c0_scl + 3 + + + pwm_b_6 + 4 + + + sio_29 + 5 + + + pio0_29 + 6 + + + pio1_29 + 7 + + + usb_muxing_vbus_en + 9 + + + null + 31 + + + + + + + INTR0 + 0x000000f0 + Raw Interrupts + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + oneToClear + + + GPIO7_EDGE_LOW + [30:30] + read-write + oneToClear + + + GPIO7_LEVEL_HIGH + [29:29] + read-only + + + GPIO7_LEVEL_LOW + [28:28] + read-only + + + GPIO6_EDGE_HIGH + [27:27] + read-write + oneToClear + + + GPIO6_EDGE_LOW + [26:26] + read-write + oneToClear + + + GPIO6_LEVEL_HIGH + [25:25] + read-only + + + GPIO6_LEVEL_LOW + [24:24] + read-only + + + GPIO5_EDGE_HIGH + [23:23] + read-write + oneToClear + + + GPIO5_EDGE_LOW + [22:22] + read-write + oneToClear + + + GPIO5_LEVEL_HIGH + [21:21] + read-only + + + GPIO5_LEVEL_LOW + [20:20] + read-only + + + GPIO4_EDGE_HIGH + [19:19] + read-write + oneToClear + + + GPIO4_EDGE_LOW + [18:18] + read-write + oneToClear + + + GPIO4_LEVEL_HIGH + [17:17] + read-only + + + GPIO4_LEVEL_LOW + [16:16] + read-only + + + GPIO3_EDGE_HIGH + [15:15] + read-write + oneToClear + + + GPIO3_EDGE_LOW + [14:14] + read-write + oneToClear + + + GPIO3_LEVEL_HIGH + [13:13] + read-only + + + GPIO3_LEVEL_LOW + [12:12] + read-only + + + GPIO2_EDGE_HIGH + [11:11] + read-write + oneToClear + + + GPIO2_EDGE_LOW + [10:10] + read-write + oneToClear + + + GPIO2_LEVEL_HIGH + [9:9] + read-only + + + GPIO2_LEVEL_LOW + [8:8] + read-only + + + GPIO1_EDGE_HIGH + [7:7] + read-write + oneToClear + + + GPIO1_EDGE_LOW + [6:6] + read-write + oneToClear + + + GPIO1_LEVEL_HIGH + [5:5] + read-only + + + GPIO1_LEVEL_LOW + [4:4] + read-only + + + GPIO0_EDGE_HIGH + [3:3] + read-write + oneToClear + + + GPIO0_EDGE_LOW + [2:2] + read-write + oneToClear + + + GPIO0_LEVEL_HIGH + [1:1] + read-only + + + GPIO0_LEVEL_LOW + [0:0] + read-only + + + + + INTR1 + 0x000000f4 + Raw Interrupts + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + oneToClear + + + GPIO15_EDGE_LOW + [30:30] + read-write + oneToClear + + + GPIO15_LEVEL_HIGH + [29:29] + read-only + + + GPIO15_LEVEL_LOW + [28:28] + read-only + + + GPIO14_EDGE_HIGH + [27:27] + read-write + oneToClear + + + GPIO14_EDGE_LOW + [26:26] + read-write + oneToClear + + + GPIO14_LEVEL_HIGH + [25:25] + read-only + + + GPIO14_LEVEL_LOW + [24:24] + read-only + + + GPIO13_EDGE_HIGH + [23:23] + read-write + oneToClear + + + GPIO13_EDGE_LOW + [22:22] + read-write + oneToClear + + + GPIO13_LEVEL_HIGH + [21:21] + read-only + + + GPIO13_LEVEL_LOW + [20:20] + read-only + + + GPIO12_EDGE_HIGH + [19:19] + read-write + oneToClear + + + GPIO12_EDGE_LOW + [18:18] + read-write + oneToClear + + + GPIO12_LEVEL_HIGH + [17:17] + read-only + + + GPIO12_LEVEL_LOW + [16:16] + read-only + + + GPIO11_EDGE_HIGH + [15:15] + read-write + oneToClear + + + GPIO11_EDGE_LOW + [14:14] + read-write + oneToClear + + + GPIO11_LEVEL_HIGH + [13:13] + read-only + + + GPIO11_LEVEL_LOW + [12:12] + read-only + + + GPIO10_EDGE_HIGH + [11:11] + read-write + oneToClear + + + GPIO10_EDGE_LOW + [10:10] + read-write + oneToClear + + + GPIO10_LEVEL_HIGH + [9:9] + read-only + + + GPIO10_LEVEL_LOW + [8:8] + read-only + + + GPIO9_EDGE_HIGH + [7:7] + read-write + oneToClear + + + GPIO9_EDGE_LOW + [6:6] + read-write + oneToClear + + + GPIO9_LEVEL_HIGH + [5:5] + read-only + + + GPIO9_LEVEL_LOW + [4:4] + read-only + + + GPIO8_EDGE_HIGH + [3:3] + read-write + oneToClear + + + GPIO8_EDGE_LOW + [2:2] + read-write + oneToClear + + + GPIO8_LEVEL_HIGH + [1:1] + read-only + + + GPIO8_LEVEL_LOW + [0:0] + read-only + + + + + INTR2 + 0x000000f8 + Raw Interrupts + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + oneToClear + + + GPIO23_EDGE_LOW + [30:30] + read-write + oneToClear + + + GPIO23_LEVEL_HIGH + [29:29] + read-only + + + GPIO23_LEVEL_LOW + [28:28] + read-only + + + GPIO22_EDGE_HIGH + [27:27] + read-write + oneToClear + + + GPIO22_EDGE_LOW + [26:26] + read-write + oneToClear + + + GPIO22_LEVEL_HIGH + [25:25] + read-only + + + GPIO22_LEVEL_LOW + [24:24] + read-only + + + GPIO21_EDGE_HIGH + [23:23] + read-write + oneToClear + + + GPIO21_EDGE_LOW + [22:22] + read-write + oneToClear + + + GPIO21_LEVEL_HIGH + [21:21] + read-only + + + GPIO21_LEVEL_LOW + [20:20] + read-only + + + GPIO20_EDGE_HIGH + [19:19] + read-write + oneToClear + + + GPIO20_EDGE_LOW + [18:18] + read-write + oneToClear + + + GPIO20_LEVEL_HIGH + [17:17] + read-only + + + GPIO20_LEVEL_LOW + [16:16] + read-only + + + GPIO19_EDGE_HIGH + [15:15] + read-write + oneToClear + + + GPIO19_EDGE_LOW + [14:14] + read-write + oneToClear + + + GPIO19_LEVEL_HIGH + [13:13] + read-only + + + GPIO19_LEVEL_LOW + [12:12] + read-only + + + GPIO18_EDGE_HIGH + [11:11] + read-write + oneToClear + + + GPIO18_EDGE_LOW + [10:10] + read-write + oneToClear + + + GPIO18_LEVEL_HIGH + [9:9] + read-only + + + GPIO18_LEVEL_LOW + [8:8] + read-only + + + GPIO17_EDGE_HIGH + [7:7] + read-write + oneToClear + + + GPIO17_EDGE_LOW + [6:6] + read-write + oneToClear + + + GPIO17_LEVEL_HIGH + [5:5] + read-only + + + GPIO17_LEVEL_LOW + [4:4] + read-only + + + GPIO16_EDGE_HIGH + [3:3] + read-write + oneToClear + + + GPIO16_EDGE_LOW + [2:2] + read-write + oneToClear + + + GPIO16_LEVEL_HIGH + [1:1] + read-only + + + GPIO16_LEVEL_LOW + [0:0] + read-only + + + + + INTR3 + 0x000000fc + Raw Interrupts + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + oneToClear + + + GPIO29_EDGE_LOW + [22:22] + read-write + oneToClear + + + GPIO29_LEVEL_HIGH + [21:21] + read-only + + + GPIO29_LEVEL_LOW + [20:20] + read-only + + + GPIO28_EDGE_HIGH + [19:19] + read-write + oneToClear + + + GPIO28_EDGE_LOW + [18:18] + read-write + oneToClear + + + GPIO28_LEVEL_HIGH + [17:17] + read-only + + + GPIO28_LEVEL_LOW + [16:16] + read-only + + + GPIO27_EDGE_HIGH + [15:15] + read-write + oneToClear + + + GPIO27_EDGE_LOW + [14:14] + read-write + oneToClear + + + GPIO27_LEVEL_HIGH + [13:13] + read-only + + + GPIO27_LEVEL_LOW + [12:12] + read-only + + + GPIO26_EDGE_HIGH + [11:11] + read-write + oneToClear + + + GPIO26_EDGE_LOW + [10:10] + read-write + oneToClear + + + GPIO26_LEVEL_HIGH + [9:9] + read-only + + + GPIO26_LEVEL_LOW + [8:8] + read-only + + + GPIO25_EDGE_HIGH + [7:7] + read-write + oneToClear + + + GPIO25_EDGE_LOW + [6:6] + read-write + oneToClear + + + GPIO25_LEVEL_HIGH + [5:5] + read-only + + + GPIO25_LEVEL_LOW + [4:4] + read-only + + + GPIO24_EDGE_HIGH + [3:3] + read-write + oneToClear + + + GPIO24_EDGE_LOW + [2:2] + read-write + oneToClear + + + GPIO24_LEVEL_HIGH + [1:1] + read-only + + + GPIO24_LEVEL_LOW + [0:0] + read-only + + + + + PROC0_INTE0 + 0x00000100 + Interrupt Enable for proc0 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTE1 + 0x00000104 + Interrupt Enable for proc0 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTE2 + 0x00000108 + Interrupt Enable for proc0 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTE3 + 0x0000010c + Interrupt Enable for proc0 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTF0 + 0x00000110 + Interrupt Force for proc0 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTF1 + 0x00000114 + Interrupt Force for proc0 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTF2 + 0x00000118 + Interrupt Force for proc0 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTF3 + 0x0000011c + Interrupt Force for proc0 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + PROC0_INTS0 + 0x00000120 + Interrupt status after masking & forcing for proc0 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-only + + + GPIO7_EDGE_LOW + [30:30] + read-only + + + GPIO7_LEVEL_HIGH + [29:29] + read-only + + + GPIO7_LEVEL_LOW + [28:28] + read-only + + + GPIO6_EDGE_HIGH + [27:27] + read-only + + + GPIO6_EDGE_LOW + [26:26] + read-only + + + GPIO6_LEVEL_HIGH + [25:25] + read-only + + + GPIO6_LEVEL_LOW + [24:24] + read-only + + + GPIO5_EDGE_HIGH + [23:23] + read-only + + + GPIO5_EDGE_LOW + [22:22] + read-only + + + GPIO5_LEVEL_HIGH + [21:21] + read-only + + + GPIO5_LEVEL_LOW + [20:20] + read-only + + + GPIO4_EDGE_HIGH + [19:19] + read-only + + + GPIO4_EDGE_LOW + [18:18] + read-only + + + GPIO4_LEVEL_HIGH + [17:17] + read-only + + + GPIO4_LEVEL_LOW + [16:16] + read-only + + + GPIO3_EDGE_HIGH + [15:15] + read-only + + + GPIO3_EDGE_LOW + [14:14] + read-only + + + GPIO3_LEVEL_HIGH + [13:13] + read-only + + + GPIO3_LEVEL_LOW + [12:12] + read-only + + + GPIO2_EDGE_HIGH + [11:11] + read-only + + + GPIO2_EDGE_LOW + [10:10] + read-only + + + GPIO2_LEVEL_HIGH + [9:9] + read-only + + + GPIO2_LEVEL_LOW + [8:8] + read-only + + + GPIO1_EDGE_HIGH + [7:7] + read-only + + + GPIO1_EDGE_LOW + [6:6] + read-only + + + GPIO1_LEVEL_HIGH + [5:5] + read-only + + + GPIO1_LEVEL_LOW + [4:4] + read-only + + + GPIO0_EDGE_HIGH + [3:3] + read-only + + + GPIO0_EDGE_LOW + [2:2] + read-only + + + GPIO0_LEVEL_HIGH + [1:1] + read-only + + + GPIO0_LEVEL_LOW + [0:0] + read-only + + + + + PROC0_INTS1 + 0x00000124 + Interrupt status after masking & forcing for proc0 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-only + + + GPIO15_EDGE_LOW + [30:30] + read-only + + + GPIO15_LEVEL_HIGH + [29:29] + read-only + + + GPIO15_LEVEL_LOW + [28:28] + read-only + + + GPIO14_EDGE_HIGH + [27:27] + read-only + + + GPIO14_EDGE_LOW + [26:26] + read-only + + + GPIO14_LEVEL_HIGH + [25:25] + read-only + + + GPIO14_LEVEL_LOW + [24:24] + read-only + + + GPIO13_EDGE_HIGH + [23:23] + read-only + + + GPIO13_EDGE_LOW + [22:22] + read-only + + + GPIO13_LEVEL_HIGH + [21:21] + read-only + + + GPIO13_LEVEL_LOW + [20:20] + read-only + + + GPIO12_EDGE_HIGH + [19:19] + read-only + + + GPIO12_EDGE_LOW + [18:18] + read-only + + + GPIO12_LEVEL_HIGH + [17:17] + read-only + + + GPIO12_LEVEL_LOW + [16:16] + read-only + + + GPIO11_EDGE_HIGH + [15:15] + read-only + + + GPIO11_EDGE_LOW + [14:14] + read-only + + + GPIO11_LEVEL_HIGH + [13:13] + read-only + + + GPIO11_LEVEL_LOW + [12:12] + read-only + + + GPIO10_EDGE_HIGH + [11:11] + read-only + + + GPIO10_EDGE_LOW + [10:10] + read-only + + + GPIO10_LEVEL_HIGH + [9:9] + read-only + + + GPIO10_LEVEL_LOW + [8:8] + read-only + + + GPIO9_EDGE_HIGH + [7:7] + read-only + + + GPIO9_EDGE_LOW + [6:6] + read-only + + + GPIO9_LEVEL_HIGH + [5:5] + read-only + + + GPIO9_LEVEL_LOW + [4:4] + read-only + + + GPIO8_EDGE_HIGH + [3:3] + read-only + + + GPIO8_EDGE_LOW + [2:2] + read-only + + + GPIO8_LEVEL_HIGH + [1:1] + read-only + + + GPIO8_LEVEL_LOW + [0:0] + read-only + + + + + PROC0_INTS2 + 0x00000128 + Interrupt status after masking & forcing for proc0 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-only + + + GPIO23_EDGE_LOW + [30:30] + read-only + + + GPIO23_LEVEL_HIGH + [29:29] + read-only + + + GPIO23_LEVEL_LOW + [28:28] + read-only + + + GPIO22_EDGE_HIGH + [27:27] + read-only + + + GPIO22_EDGE_LOW + [26:26] + read-only + + + GPIO22_LEVEL_HIGH + [25:25] + read-only + + + GPIO22_LEVEL_LOW + [24:24] + read-only + + + GPIO21_EDGE_HIGH + [23:23] + read-only + + + GPIO21_EDGE_LOW + [22:22] + read-only + + + GPIO21_LEVEL_HIGH + [21:21] + read-only + + + GPIO21_LEVEL_LOW + [20:20] + read-only + + + GPIO20_EDGE_HIGH + [19:19] + read-only + + + GPIO20_EDGE_LOW + [18:18] + read-only + + + GPIO20_LEVEL_HIGH + [17:17] + read-only + + + GPIO20_LEVEL_LOW + [16:16] + read-only + + + GPIO19_EDGE_HIGH + [15:15] + read-only + + + GPIO19_EDGE_LOW + [14:14] + read-only + + + GPIO19_LEVEL_HIGH + [13:13] + read-only + + + GPIO19_LEVEL_LOW + [12:12] + read-only + + + GPIO18_EDGE_HIGH + [11:11] + read-only + + + GPIO18_EDGE_LOW + [10:10] + read-only + + + GPIO18_LEVEL_HIGH + [9:9] + read-only + + + GPIO18_LEVEL_LOW + [8:8] + read-only + + + GPIO17_EDGE_HIGH + [7:7] + read-only + + + GPIO17_EDGE_LOW + [6:6] + read-only + + + GPIO17_LEVEL_HIGH + [5:5] + read-only + + + GPIO17_LEVEL_LOW + [4:4] + read-only + + + GPIO16_EDGE_HIGH + [3:3] + read-only + + + GPIO16_EDGE_LOW + [2:2] + read-only + + + GPIO16_LEVEL_HIGH + [1:1] + read-only + + + GPIO16_LEVEL_LOW + [0:0] + read-only + + + + + PROC0_INTS3 + 0x0000012c + Interrupt status after masking & forcing for proc0 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-only + + + GPIO29_EDGE_LOW + [22:22] + read-only + + + GPIO29_LEVEL_HIGH + [21:21] + read-only + + + GPIO29_LEVEL_LOW + [20:20] + read-only + + + GPIO28_EDGE_HIGH + [19:19] + read-only + + + GPIO28_EDGE_LOW + [18:18] + read-only + + + GPIO28_LEVEL_HIGH + [17:17] + read-only + + + GPIO28_LEVEL_LOW + [16:16] + read-only + + + GPIO27_EDGE_HIGH + [15:15] + read-only + + + GPIO27_EDGE_LOW + [14:14] + read-only + + + GPIO27_LEVEL_HIGH + [13:13] + read-only + + + GPIO27_LEVEL_LOW + [12:12] + read-only + + + GPIO26_EDGE_HIGH + [11:11] + read-only + + + GPIO26_EDGE_LOW + [10:10] + read-only + + + GPIO26_LEVEL_HIGH + [9:9] + read-only + + + GPIO26_LEVEL_LOW + [8:8] + read-only + + + GPIO25_EDGE_HIGH + [7:7] + read-only + + + GPIO25_EDGE_LOW + [6:6] + read-only + + + GPIO25_LEVEL_HIGH + [5:5] + read-only + + + GPIO25_LEVEL_LOW + [4:4] + read-only + + + GPIO24_EDGE_HIGH + [3:3] + read-only + + + GPIO24_EDGE_LOW + [2:2] + read-only + + + GPIO24_LEVEL_HIGH + [1:1] + read-only + + + GPIO24_LEVEL_LOW + [0:0] + read-only + + + + + PROC1_INTE0 + 0x00000130 + Interrupt Enable for proc1 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTE1 + 0x00000134 + Interrupt Enable for proc1 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTE2 + 0x00000138 + Interrupt Enable for proc1 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTE3 + 0x0000013c + Interrupt Enable for proc1 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTF0 + 0x00000140 + Interrupt Force for proc1 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTF1 + 0x00000144 + Interrupt Force for proc1 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTF2 + 0x00000148 + Interrupt Force for proc1 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTF3 + 0x0000014c + Interrupt Force for proc1 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + PROC1_INTS0 + 0x00000150 + Interrupt status after masking & forcing for proc1 + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-only + + + GPIO7_EDGE_LOW + [30:30] + read-only + + + GPIO7_LEVEL_HIGH + [29:29] + read-only + + + GPIO7_LEVEL_LOW + [28:28] + read-only + + + GPIO6_EDGE_HIGH + [27:27] + read-only + + + GPIO6_EDGE_LOW + [26:26] + read-only + + + GPIO6_LEVEL_HIGH + [25:25] + read-only + + + GPIO6_LEVEL_LOW + [24:24] + read-only + + + GPIO5_EDGE_HIGH + [23:23] + read-only + + + GPIO5_EDGE_LOW + [22:22] + read-only + + + GPIO5_LEVEL_HIGH + [21:21] + read-only + + + GPIO5_LEVEL_LOW + [20:20] + read-only + + + GPIO4_EDGE_HIGH + [19:19] + read-only + + + GPIO4_EDGE_LOW + [18:18] + read-only + + + GPIO4_LEVEL_HIGH + [17:17] + read-only + + + GPIO4_LEVEL_LOW + [16:16] + read-only + + + GPIO3_EDGE_HIGH + [15:15] + read-only + + + GPIO3_EDGE_LOW + [14:14] + read-only + + + GPIO3_LEVEL_HIGH + [13:13] + read-only + + + GPIO3_LEVEL_LOW + [12:12] + read-only + + + GPIO2_EDGE_HIGH + [11:11] + read-only + + + GPIO2_EDGE_LOW + [10:10] + read-only + + + GPIO2_LEVEL_HIGH + [9:9] + read-only + + + GPIO2_LEVEL_LOW + [8:8] + read-only + + + GPIO1_EDGE_HIGH + [7:7] + read-only + + + GPIO1_EDGE_LOW + [6:6] + read-only + + + GPIO1_LEVEL_HIGH + [5:5] + read-only + + + GPIO1_LEVEL_LOW + [4:4] + read-only + + + GPIO0_EDGE_HIGH + [3:3] + read-only + + + GPIO0_EDGE_LOW + [2:2] + read-only + + + GPIO0_LEVEL_HIGH + [1:1] + read-only + + + GPIO0_LEVEL_LOW + [0:0] + read-only + + + + + PROC1_INTS1 + 0x00000154 + Interrupt status after masking & forcing for proc1 + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-only + + + GPIO15_EDGE_LOW + [30:30] + read-only + + + GPIO15_LEVEL_HIGH + [29:29] + read-only + + + GPIO15_LEVEL_LOW + [28:28] + read-only + + + GPIO14_EDGE_HIGH + [27:27] + read-only + + + GPIO14_EDGE_LOW + [26:26] + read-only + + + GPIO14_LEVEL_HIGH + [25:25] + read-only + + + GPIO14_LEVEL_LOW + [24:24] + read-only + + + GPIO13_EDGE_HIGH + [23:23] + read-only + + + GPIO13_EDGE_LOW + [22:22] + read-only + + + GPIO13_LEVEL_HIGH + [21:21] + read-only + + + GPIO13_LEVEL_LOW + [20:20] + read-only + + + GPIO12_EDGE_HIGH + [19:19] + read-only + + + GPIO12_EDGE_LOW + [18:18] + read-only + + + GPIO12_LEVEL_HIGH + [17:17] + read-only + + + GPIO12_LEVEL_LOW + [16:16] + read-only + + + GPIO11_EDGE_HIGH + [15:15] + read-only + + + GPIO11_EDGE_LOW + [14:14] + read-only + + + GPIO11_LEVEL_HIGH + [13:13] + read-only + + + GPIO11_LEVEL_LOW + [12:12] + read-only + + + GPIO10_EDGE_HIGH + [11:11] + read-only + + + GPIO10_EDGE_LOW + [10:10] + read-only + + + GPIO10_LEVEL_HIGH + [9:9] + read-only + + + GPIO10_LEVEL_LOW + [8:8] + read-only + + + GPIO9_EDGE_HIGH + [7:7] + read-only + + + GPIO9_EDGE_LOW + [6:6] + read-only + + + GPIO9_LEVEL_HIGH + [5:5] + read-only + + + GPIO9_LEVEL_LOW + [4:4] + read-only + + + GPIO8_EDGE_HIGH + [3:3] + read-only + + + GPIO8_EDGE_LOW + [2:2] + read-only + + + GPIO8_LEVEL_HIGH + [1:1] + read-only + + + GPIO8_LEVEL_LOW + [0:0] + read-only + + + + + PROC1_INTS2 + 0x00000158 + Interrupt status after masking & forcing for proc1 + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-only + + + GPIO23_EDGE_LOW + [30:30] + read-only + + + GPIO23_LEVEL_HIGH + [29:29] + read-only + + + GPIO23_LEVEL_LOW + [28:28] + read-only + + + GPIO22_EDGE_HIGH + [27:27] + read-only + + + GPIO22_EDGE_LOW + [26:26] + read-only + + + GPIO22_LEVEL_HIGH + [25:25] + read-only + + + GPIO22_LEVEL_LOW + [24:24] + read-only + + + GPIO21_EDGE_HIGH + [23:23] + read-only + + + GPIO21_EDGE_LOW + [22:22] + read-only + + + GPIO21_LEVEL_HIGH + [21:21] + read-only + + + GPIO21_LEVEL_LOW + [20:20] + read-only + + + GPIO20_EDGE_HIGH + [19:19] + read-only + + + GPIO20_EDGE_LOW + [18:18] + read-only + + + GPIO20_LEVEL_HIGH + [17:17] + read-only + + + GPIO20_LEVEL_LOW + [16:16] + read-only + + + GPIO19_EDGE_HIGH + [15:15] + read-only + + + GPIO19_EDGE_LOW + [14:14] + read-only + + + GPIO19_LEVEL_HIGH + [13:13] + read-only + + + GPIO19_LEVEL_LOW + [12:12] + read-only + + + GPIO18_EDGE_HIGH + [11:11] + read-only + + + GPIO18_EDGE_LOW + [10:10] + read-only + + + GPIO18_LEVEL_HIGH + [9:9] + read-only + + + GPIO18_LEVEL_LOW + [8:8] + read-only + + + GPIO17_EDGE_HIGH + [7:7] + read-only + + + GPIO17_EDGE_LOW + [6:6] + read-only + + + GPIO17_LEVEL_HIGH + [5:5] + read-only + + + GPIO17_LEVEL_LOW + [4:4] + read-only + + + GPIO16_EDGE_HIGH + [3:3] + read-only + + + GPIO16_EDGE_LOW + [2:2] + read-only + + + GPIO16_LEVEL_HIGH + [1:1] + read-only + + + GPIO16_LEVEL_LOW + [0:0] + read-only + + + + + PROC1_INTS3 + 0x0000015c + Interrupt status after masking & forcing for proc1 + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-only + + + GPIO29_EDGE_LOW + [22:22] + read-only + + + GPIO29_LEVEL_HIGH + [21:21] + read-only + + + GPIO29_LEVEL_LOW + [20:20] + read-only + + + GPIO28_EDGE_HIGH + [19:19] + read-only + + + GPIO28_EDGE_LOW + [18:18] + read-only + + + GPIO28_LEVEL_HIGH + [17:17] + read-only + + + GPIO28_LEVEL_LOW + [16:16] + read-only + + + GPIO27_EDGE_HIGH + [15:15] + read-only + + + GPIO27_EDGE_LOW + [14:14] + read-only + + + GPIO27_LEVEL_HIGH + [13:13] + read-only + + + GPIO27_LEVEL_LOW + [12:12] + read-only + + + GPIO26_EDGE_HIGH + [11:11] + read-only + + + GPIO26_EDGE_LOW + [10:10] + read-only + + + GPIO26_LEVEL_HIGH + [9:9] + read-only + + + GPIO26_LEVEL_LOW + [8:8] + read-only + + + GPIO25_EDGE_HIGH + [7:7] + read-only + + + GPIO25_EDGE_LOW + [6:6] + read-only + + + GPIO25_LEVEL_HIGH + [5:5] + read-only + + + GPIO25_LEVEL_LOW + [4:4] + read-only + + + GPIO24_EDGE_HIGH + [3:3] + read-only + + + GPIO24_EDGE_LOW + [2:2] + read-only + + + GPIO24_LEVEL_HIGH + [1:1] + read-only + + + GPIO24_LEVEL_LOW + [0:0] + read-only + + + + + DORMANT_WAKE_INTE0 + 0x00000160 + Interrupt Enable for dormant_wake + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTE1 + 0x00000164 + Interrupt Enable for dormant_wake + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTE2 + 0x00000168 + Interrupt Enable for dormant_wake + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTE3 + 0x0000016c + Interrupt Enable for dormant_wake + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTF0 + 0x00000170 + Interrupt Force for dormant_wake + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-write + + + GPIO7_EDGE_LOW + [30:30] + read-write + + + GPIO7_LEVEL_HIGH + [29:29] + read-write + + + GPIO7_LEVEL_LOW + [28:28] + read-write + + + GPIO6_EDGE_HIGH + [27:27] + read-write + + + GPIO6_EDGE_LOW + [26:26] + read-write + + + GPIO6_LEVEL_HIGH + [25:25] + read-write + + + GPIO6_LEVEL_LOW + [24:24] + read-write + + + GPIO5_EDGE_HIGH + [23:23] + read-write + + + GPIO5_EDGE_LOW + [22:22] + read-write + + + GPIO5_LEVEL_HIGH + [21:21] + read-write + + + GPIO5_LEVEL_LOW + [20:20] + read-write + + + GPIO4_EDGE_HIGH + [19:19] + read-write + + + GPIO4_EDGE_LOW + [18:18] + read-write + + + GPIO4_LEVEL_HIGH + [17:17] + read-write + + + GPIO4_LEVEL_LOW + [16:16] + read-write + + + GPIO3_EDGE_HIGH + [15:15] + read-write + + + GPIO3_EDGE_LOW + [14:14] + read-write + + + GPIO3_LEVEL_HIGH + [13:13] + read-write + + + GPIO3_LEVEL_LOW + [12:12] + read-write + + + GPIO2_EDGE_HIGH + [11:11] + read-write + + + GPIO2_EDGE_LOW + [10:10] + read-write + + + GPIO2_LEVEL_HIGH + [9:9] + read-write + + + GPIO2_LEVEL_LOW + [8:8] + read-write + + + GPIO1_EDGE_HIGH + [7:7] + read-write + + + GPIO1_EDGE_LOW + [6:6] + read-write + + + GPIO1_LEVEL_HIGH + [5:5] + read-write + + + GPIO1_LEVEL_LOW + [4:4] + read-write + + + GPIO0_EDGE_HIGH + [3:3] + read-write + + + GPIO0_EDGE_LOW + [2:2] + read-write + + + GPIO0_LEVEL_HIGH + [1:1] + read-write + + + GPIO0_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTF1 + 0x00000174 + Interrupt Force for dormant_wake + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-write + + + GPIO15_EDGE_LOW + [30:30] + read-write + + + GPIO15_LEVEL_HIGH + [29:29] + read-write + + + GPIO15_LEVEL_LOW + [28:28] + read-write + + + GPIO14_EDGE_HIGH + [27:27] + read-write + + + GPIO14_EDGE_LOW + [26:26] + read-write + + + GPIO14_LEVEL_HIGH + [25:25] + read-write + + + GPIO14_LEVEL_LOW + [24:24] + read-write + + + GPIO13_EDGE_HIGH + [23:23] + read-write + + + GPIO13_EDGE_LOW + [22:22] + read-write + + + GPIO13_LEVEL_HIGH + [21:21] + read-write + + + GPIO13_LEVEL_LOW + [20:20] + read-write + + + GPIO12_EDGE_HIGH + [19:19] + read-write + + + GPIO12_EDGE_LOW + [18:18] + read-write + + + GPIO12_LEVEL_HIGH + [17:17] + read-write + + + GPIO12_LEVEL_LOW + [16:16] + read-write + + + GPIO11_EDGE_HIGH + [15:15] + read-write + + + GPIO11_EDGE_LOW + [14:14] + read-write + + + GPIO11_LEVEL_HIGH + [13:13] + read-write + + + GPIO11_LEVEL_LOW + [12:12] + read-write + + + GPIO10_EDGE_HIGH + [11:11] + read-write + + + GPIO10_EDGE_LOW + [10:10] + read-write + + + GPIO10_LEVEL_HIGH + [9:9] + read-write + + + GPIO10_LEVEL_LOW + [8:8] + read-write + + + GPIO9_EDGE_HIGH + [7:7] + read-write + + + GPIO9_EDGE_LOW + [6:6] + read-write + + + GPIO9_LEVEL_HIGH + [5:5] + read-write + + + GPIO9_LEVEL_LOW + [4:4] + read-write + + + GPIO8_EDGE_HIGH + [3:3] + read-write + + + GPIO8_EDGE_LOW + [2:2] + read-write + + + GPIO8_LEVEL_HIGH + [1:1] + read-write + + + GPIO8_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTF2 + 0x00000178 + Interrupt Force for dormant_wake + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-write + + + GPIO23_EDGE_LOW + [30:30] + read-write + + + GPIO23_LEVEL_HIGH + [29:29] + read-write + + + GPIO23_LEVEL_LOW + [28:28] + read-write + + + GPIO22_EDGE_HIGH + [27:27] + read-write + + + GPIO22_EDGE_LOW + [26:26] + read-write + + + GPIO22_LEVEL_HIGH + [25:25] + read-write + + + GPIO22_LEVEL_LOW + [24:24] + read-write + + + GPIO21_EDGE_HIGH + [23:23] + read-write + + + GPIO21_EDGE_LOW + [22:22] + read-write + + + GPIO21_LEVEL_HIGH + [21:21] + read-write + + + GPIO21_LEVEL_LOW + [20:20] + read-write + + + GPIO20_EDGE_HIGH + [19:19] + read-write + + + GPIO20_EDGE_LOW + [18:18] + read-write + + + GPIO20_LEVEL_HIGH + [17:17] + read-write + + + GPIO20_LEVEL_LOW + [16:16] + read-write + + + GPIO19_EDGE_HIGH + [15:15] + read-write + + + GPIO19_EDGE_LOW + [14:14] + read-write + + + GPIO19_LEVEL_HIGH + [13:13] + read-write + + + GPIO19_LEVEL_LOW + [12:12] + read-write + + + GPIO18_EDGE_HIGH + [11:11] + read-write + + + GPIO18_EDGE_LOW + [10:10] + read-write + + + GPIO18_LEVEL_HIGH + [9:9] + read-write + + + GPIO18_LEVEL_LOW + [8:8] + read-write + + + GPIO17_EDGE_HIGH + [7:7] + read-write + + + GPIO17_EDGE_LOW + [6:6] + read-write + + + GPIO17_LEVEL_HIGH + [5:5] + read-write + + + GPIO17_LEVEL_LOW + [4:4] + read-write + + + GPIO16_EDGE_HIGH + [3:3] + read-write + + + GPIO16_EDGE_LOW + [2:2] + read-write + + + GPIO16_LEVEL_HIGH + [1:1] + read-write + + + GPIO16_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTF3 + 0x0000017c + Interrupt Force for dormant_wake + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-write + + + GPIO29_EDGE_LOW + [22:22] + read-write + + + GPIO29_LEVEL_HIGH + [21:21] + read-write + + + GPIO29_LEVEL_LOW + [20:20] + read-write + + + GPIO28_EDGE_HIGH + [19:19] + read-write + + + GPIO28_EDGE_LOW + [18:18] + read-write + + + GPIO28_LEVEL_HIGH + [17:17] + read-write + + + GPIO28_LEVEL_LOW + [16:16] + read-write + + + GPIO27_EDGE_HIGH + [15:15] + read-write + + + GPIO27_EDGE_LOW + [14:14] + read-write + + + GPIO27_LEVEL_HIGH + [13:13] + read-write + + + GPIO27_LEVEL_LOW + [12:12] + read-write + + + GPIO26_EDGE_HIGH + [11:11] + read-write + + + GPIO26_EDGE_LOW + [10:10] + read-write + + + GPIO26_LEVEL_HIGH + [9:9] + read-write + + + GPIO26_LEVEL_LOW + [8:8] + read-write + + + GPIO25_EDGE_HIGH + [7:7] + read-write + + + GPIO25_EDGE_LOW + [6:6] + read-write + + + GPIO25_LEVEL_HIGH + [5:5] + read-write + + + GPIO25_LEVEL_LOW + [4:4] + read-write + + + GPIO24_EDGE_HIGH + [3:3] + read-write + + + GPIO24_EDGE_LOW + [2:2] + read-write + + + GPIO24_LEVEL_HIGH + [1:1] + read-write + + + GPIO24_LEVEL_LOW + [0:0] + read-write + + + + + DORMANT_WAKE_INTS0 + 0x00000180 + Interrupt status after masking & forcing for dormant_wake + 0x00000000 + + + GPIO7_EDGE_HIGH + [31:31] + read-only + + + GPIO7_EDGE_LOW + [30:30] + read-only + + + GPIO7_LEVEL_HIGH + [29:29] + read-only + + + GPIO7_LEVEL_LOW + [28:28] + read-only + + + GPIO6_EDGE_HIGH + [27:27] + read-only + + + GPIO6_EDGE_LOW + [26:26] + read-only + + + GPIO6_LEVEL_HIGH + [25:25] + read-only + + + GPIO6_LEVEL_LOW + [24:24] + read-only + + + GPIO5_EDGE_HIGH + [23:23] + read-only + + + GPIO5_EDGE_LOW + [22:22] + read-only + + + GPIO5_LEVEL_HIGH + [21:21] + read-only + + + GPIO5_LEVEL_LOW + [20:20] + read-only + + + GPIO4_EDGE_HIGH + [19:19] + read-only + + + GPIO4_EDGE_LOW + [18:18] + read-only + + + GPIO4_LEVEL_HIGH + [17:17] + read-only + + + GPIO4_LEVEL_LOW + [16:16] + read-only + + + GPIO3_EDGE_HIGH + [15:15] + read-only + + + GPIO3_EDGE_LOW + [14:14] + read-only + + + GPIO3_LEVEL_HIGH + [13:13] + read-only + + + GPIO3_LEVEL_LOW + [12:12] + read-only + + + GPIO2_EDGE_HIGH + [11:11] + read-only + + + GPIO2_EDGE_LOW + [10:10] + read-only + + + GPIO2_LEVEL_HIGH + [9:9] + read-only + + + GPIO2_LEVEL_LOW + [8:8] + read-only + + + GPIO1_EDGE_HIGH + [7:7] + read-only + + + GPIO1_EDGE_LOW + [6:6] + read-only + + + GPIO1_LEVEL_HIGH + [5:5] + read-only + + + GPIO1_LEVEL_LOW + [4:4] + read-only + + + GPIO0_EDGE_HIGH + [3:3] + read-only + + + GPIO0_EDGE_LOW + [2:2] + read-only + + + GPIO0_LEVEL_HIGH + [1:1] + read-only + + + GPIO0_LEVEL_LOW + [0:0] + read-only + + + + + DORMANT_WAKE_INTS1 + 0x00000184 + Interrupt status after masking & forcing for dormant_wake + 0x00000000 + + + GPIO15_EDGE_HIGH + [31:31] + read-only + + + GPIO15_EDGE_LOW + [30:30] + read-only + + + GPIO15_LEVEL_HIGH + [29:29] + read-only + + + GPIO15_LEVEL_LOW + [28:28] + read-only + + + GPIO14_EDGE_HIGH + [27:27] + read-only + + + GPIO14_EDGE_LOW + [26:26] + read-only + + + GPIO14_LEVEL_HIGH + [25:25] + read-only + + + GPIO14_LEVEL_LOW + [24:24] + read-only + + + GPIO13_EDGE_HIGH + [23:23] + read-only + + + GPIO13_EDGE_LOW + [22:22] + read-only + + + GPIO13_LEVEL_HIGH + [21:21] + read-only + + + GPIO13_LEVEL_LOW + [20:20] + read-only + + + GPIO12_EDGE_HIGH + [19:19] + read-only + + + GPIO12_EDGE_LOW + [18:18] + read-only + + + GPIO12_LEVEL_HIGH + [17:17] + read-only + + + GPIO12_LEVEL_LOW + [16:16] + read-only + + + GPIO11_EDGE_HIGH + [15:15] + read-only + + + GPIO11_EDGE_LOW + [14:14] + read-only + + + GPIO11_LEVEL_HIGH + [13:13] + read-only + + + GPIO11_LEVEL_LOW + [12:12] + read-only + + + GPIO10_EDGE_HIGH + [11:11] + read-only + + + GPIO10_EDGE_LOW + [10:10] + read-only + + + GPIO10_LEVEL_HIGH + [9:9] + read-only + + + GPIO10_LEVEL_LOW + [8:8] + read-only + + + GPIO9_EDGE_HIGH + [7:7] + read-only + + + GPIO9_EDGE_LOW + [6:6] + read-only + + + GPIO9_LEVEL_HIGH + [5:5] + read-only + + + GPIO9_LEVEL_LOW + [4:4] + read-only + + + GPIO8_EDGE_HIGH + [3:3] + read-only + + + GPIO8_EDGE_LOW + [2:2] + read-only + + + GPIO8_LEVEL_HIGH + [1:1] + read-only + + + GPIO8_LEVEL_LOW + [0:0] + read-only + + + + + DORMANT_WAKE_INTS2 + 0x00000188 + Interrupt status after masking & forcing for dormant_wake + 0x00000000 + + + GPIO23_EDGE_HIGH + [31:31] + read-only + + + GPIO23_EDGE_LOW + [30:30] + read-only + + + GPIO23_LEVEL_HIGH + [29:29] + read-only + + + GPIO23_LEVEL_LOW + [28:28] + read-only + + + GPIO22_EDGE_HIGH + [27:27] + read-only + + + GPIO22_EDGE_LOW + [26:26] + read-only + + + GPIO22_LEVEL_HIGH + [25:25] + read-only + + + GPIO22_LEVEL_LOW + [24:24] + read-only + + + GPIO21_EDGE_HIGH + [23:23] + read-only + + + GPIO21_EDGE_LOW + [22:22] + read-only + + + GPIO21_LEVEL_HIGH + [21:21] + read-only + + + GPIO21_LEVEL_LOW + [20:20] + read-only + + + GPIO20_EDGE_HIGH + [19:19] + read-only + + + GPIO20_EDGE_LOW + [18:18] + read-only + + + GPIO20_LEVEL_HIGH + [17:17] + read-only + + + GPIO20_LEVEL_LOW + [16:16] + read-only + + + GPIO19_EDGE_HIGH + [15:15] + read-only + + + GPIO19_EDGE_LOW + [14:14] + read-only + + + GPIO19_LEVEL_HIGH + [13:13] + read-only + + + GPIO19_LEVEL_LOW + [12:12] + read-only + + + GPIO18_EDGE_HIGH + [11:11] + read-only + + + GPIO18_EDGE_LOW + [10:10] + read-only + + + GPIO18_LEVEL_HIGH + [9:9] + read-only + + + GPIO18_LEVEL_LOW + [8:8] + read-only + + + GPIO17_EDGE_HIGH + [7:7] + read-only + + + GPIO17_EDGE_LOW + [6:6] + read-only + + + GPIO17_LEVEL_HIGH + [5:5] + read-only + + + GPIO17_LEVEL_LOW + [4:4] + read-only + + + GPIO16_EDGE_HIGH + [3:3] + read-only + + + GPIO16_EDGE_LOW + [2:2] + read-only + + + GPIO16_LEVEL_HIGH + [1:1] + read-only + + + GPIO16_LEVEL_LOW + [0:0] + read-only + + + + + DORMANT_WAKE_INTS3 + 0x0000018c + Interrupt status after masking & forcing for dormant_wake + 0x00000000 + + + GPIO29_EDGE_HIGH + [23:23] + read-only + + + GPIO29_EDGE_LOW + [22:22] + read-only + + + GPIO29_LEVEL_HIGH + [21:21] + read-only + + + GPIO29_LEVEL_LOW + [20:20] + read-only + + + GPIO28_EDGE_HIGH + [19:19] + read-only + + + GPIO28_EDGE_LOW + [18:18] + read-only + + + GPIO28_LEVEL_HIGH + [17:17] + read-only + + + GPIO28_LEVEL_LOW + [16:16] + read-only + + + GPIO27_EDGE_HIGH + [15:15] + read-only + + + GPIO27_EDGE_LOW + [14:14] + read-only + + + GPIO27_LEVEL_HIGH + [13:13] + read-only + + + GPIO27_LEVEL_LOW + [12:12] + read-only + + + GPIO26_EDGE_HIGH + [11:11] + read-only + + + GPIO26_EDGE_LOW + [10:10] + read-only + + + GPIO26_LEVEL_HIGH + [9:9] + read-only + + + GPIO26_LEVEL_LOW + [8:8] + read-only + + + GPIO25_EDGE_HIGH + [7:7] + read-only + + + GPIO25_EDGE_LOW + [6:6] + read-only + + + GPIO25_LEVEL_HIGH + [5:5] + read-only + + + GPIO25_LEVEL_LOW + [4:4] + read-only + + + GPIO24_EDGE_HIGH + [3:3] + read-only + + + GPIO24_EDGE_LOW + [2:2] + read-only + + + GPIO24_LEVEL_HIGH + [1:1] + read-only + + + GPIO24_LEVEL_LOW + [0:0] + read-only + + + + + + + SYSINFO + 0x40000000 + + 0 + 20 + registers + + + + CHIP_ID + 0x00000000 + JEDEC JEP-106 compliant chip identifier. + 0x00000000 + + + REVISION + [31:28] + read-only + + + PART + [27:12] + read-only + + + MANUFACTURER + [11:0] + read-only + + + + + PLATFORM + 0x00000004 + Platform register. Allows software to know what environment it is running in. + 0x00000000 + + + ASIC + [1:1] + read-only + + + FPGA + [0:0] + read-only + + + + + GITREF_RP2040 + 0x00000010 + Git hash of the chip source. Used to identify chip version. + 0x00000000 + + + GITREF_RP2040 + [31:0] + read-only + + + + + + + PPB + 0xe0000000 + + 0 + 60836 + registers + + + + SYST_CSR + 0x0000e010 + Use the SysTick Control and Status Register to enable the SysTick features. + 0x00000000 + + + COUNTFLAG + Returns 1 if timer counted to 0 since last time this was read. Clears on read by application or debugger. + [16:16] + read-only + + + CLKSOURCE + SysTick clock source. Always reads as one if SYST_CALIB reports NOREF. + Selects the SysTick timer clock source: + 0 = External reference clock. + 1 = Processor clock. + [2:2] + read-write + + + TICKINT + Enables SysTick exception request: + 0 = Counting down to zero does not assert the SysTick exception request. + 1 = Counting down to zero to asserts the SysTick exception request. + [1:1] + read-write + + + ENABLE + Enable SysTick counter: + 0 = Counter disabled. + 1 = Counter enabled. + [0:0] + read-write + + + + + SYST_RVR + 0x0000e014 + Use the SysTick Reload Value Register to specify the start value to load into the current value register when the counter reaches 0. It can be any value between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect because the SysTick interrupt and COUNTFLAG are activated when counting from 1 to 0. The reset value of this register is UNKNOWN. + To generate a multi-shot timer with a period of N processor clock cycles, use a RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 clock pulses, set RELOAD to 99. + 0x00000000 + + + RELOAD + Value to load into the SysTick Current Value Register when the counter reaches 0. + [23:0] + read-write + + + + + SYST_CVR + 0x0000e018 + Use the SysTick Current Value Register to find the current value in the register. The reset value of this register is UNKNOWN. + 0x00000000 + + + CURRENT + Reads return the current value of the SysTick counter. This register is write-clear. Writing to it with any value clears the register to 0. Clearing this register also clears the COUNTFLAG bit of the SysTick Control and Status Register. + [23:0] + read-write + + + + + SYST_CALIB + 0x0000e01c + Use the SysTick Calibration Value Register to enable software to scale to any required speed using divide and multiply. + 0x00000000 + + + NOREF + If reads as 1, the Reference clock is not provided - the CLKSOURCE bit of the SysTick Control and Status register will be forced to 1 and cannot be cleared to 0. + [31:31] + read-only + + + SKEW + If reads as 1, the calibration value for 10ms is inexact (due to clock frequency). + [30:30] + read-only + + + TENMS + An optional Reload value to be used for 10ms (100Hz) timing, subject to system clock skew errors. If the value reads as 0, the calibration value is not known. + [23:0] + read-only + + + + + NVIC_ISER + 0x0000e100 + Use the Interrupt Set-Enable Register to enable interrupts and determine which interrupts are currently enabled. + If a pending interrupt is enabled, the NVIC activates the interrupt based on its priority. If an interrupt is not enabled, asserting its interrupt signal changes the interrupt state to pending, but the NVIC never activates the interrupt, regardless of its priority. + 0x00000000 + + + SETENA + Interrupt set-enable bits. + Write: + 0 = No effect. + 1 = Enable interrupt. + Read: + 0 = Interrupt disabled. + 1 = Interrupt enabled. + [31:0] + read-write + + + + + NVIC_ICER + 0x0000e180 + Use the Interrupt Clear-Enable Registers to disable interrupts and determine which interrupts are currently enabled. + 0x00000000 + + + CLRENA + Interrupt clear-enable bits. + Write: + 0 = No effect. + 1 = Disable interrupt. + Read: + 0 = Interrupt disabled. + 1 = Interrupt enabled. + [31:0] + read-write + + + + + NVIC_ISPR + 0x0000e200 + The NVIC_ISPR forces interrupts into the pending state, and shows which interrupts are pending. + 0x00000000 + + + SETPEND + Interrupt set-pending bits. + Write: + 0 = No effect. + 1 = Changes interrupt state to pending. + Read: + 0 = Interrupt is not pending. + 1 = Interrupt is pending. + Note: Writing 1 to the NVIC_ISPR bit corresponding to: + An interrupt that is pending has no effect. + A disabled interrupt sets the state of that interrupt to pending. + [31:0] + read-write + + + + + NVIC_ICPR + 0x0000e280 + Use the Interrupt Clear-Pending Register to clear pending interrupts and determine which interrupts are currently pending. + 0x00000000 + + + CLRPEND + Interrupt clear-pending bits. + Write: + 0 = No effect. + 1 = Removes pending state and interrupt. + Read: + 0 = Interrupt is not pending. + 1 = Interrupt is pending. + [31:0] + read-write + + + + + NVIC_IPR0 + 0x0000e400 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + Note: Writing 1 to an NVIC_ICPR bit does not affect the active state of the corresponding interrupt. + These registers are only word-accessible + 0x00000000 + + + IP_3 + Priority of interrupt 3 + [31:30] + read-write + + + IP_2 + Priority of interrupt 2 + [23:22] + read-write + + + IP_1 + Priority of interrupt 1 + [15:14] + read-write + + + IP_0 + Priority of interrupt 0 + [7:6] + read-write + + + + + NVIC_IPR1 + 0x0000e404 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_7 + Priority of interrupt 7 + [31:30] + read-write + + + IP_6 + Priority of interrupt 6 + [23:22] + read-write + + + IP_5 + Priority of interrupt 5 + [15:14] + read-write + + + IP_4 + Priority of interrupt 4 + [7:6] + read-write + + + + + NVIC_IPR2 + 0x0000e408 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_11 + Priority of interrupt 11 + [31:30] + read-write + + + IP_10 + Priority of interrupt 10 + [23:22] + read-write + + + IP_9 + Priority of interrupt 9 + [15:14] + read-write + + + IP_8 + Priority of interrupt 8 + [7:6] + read-write + + + + + NVIC_IPR3 + 0x0000e40c + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_15 + Priority of interrupt 15 + [31:30] + read-write + + + IP_14 + Priority of interrupt 14 + [23:22] + read-write + + + IP_13 + Priority of interrupt 13 + [15:14] + read-write + + + IP_12 + Priority of interrupt 12 + [7:6] + read-write + + + + + NVIC_IPR4 + 0x0000e410 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_19 + Priority of interrupt 19 + [31:30] + read-write + + + IP_18 + Priority of interrupt 18 + [23:22] + read-write + + + IP_17 + Priority of interrupt 17 + [15:14] + read-write + + + IP_16 + Priority of interrupt 16 + [7:6] + read-write + + + + + NVIC_IPR5 + 0x0000e414 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_23 + Priority of interrupt 23 + [31:30] + read-write + + + IP_22 + Priority of interrupt 22 + [23:22] + read-write + + + IP_21 + Priority of interrupt 21 + [15:14] + read-write + + + IP_20 + Priority of interrupt 20 + [7:6] + read-write + + + + + NVIC_IPR6 + 0x0000e418 + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_27 + Priority of interrupt 27 + [31:30] + read-write + + + IP_26 + Priority of interrupt 26 + [23:22] + read-write + + + IP_25 + Priority of interrupt 25 + [15:14] + read-write + + + IP_24 + Priority of interrupt 24 + [7:6] + read-write + + + + + NVIC_IPR7 + 0x0000e41c + Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. + 0x00000000 + + + IP_31 + Priority of interrupt 31 + [31:30] + read-write + + + IP_30 + Priority of interrupt 30 + [23:22] + read-write + + + IP_29 + Priority of interrupt 29 + [15:14] + read-write + + + IP_28 + Priority of interrupt 28 + [7:6] + read-write + + + + + CPUID + 0x0000ed00 + Read the CPU ID Base Register to determine: the ID number of the processor core, the version number of the processor core, the implementation details of the processor core. + 0x410cc601 + + + IMPLEMENTER + Implementor code: 0x41 = ARM + [31:24] + read-only + + + VARIANT + Major revision number n in the rnpm revision status: + 0x0 = Revision 0. + [23:20] + read-only + + + ARCHITECTURE + Constant that defines the architecture of the processor: + 0xC = ARMv6-M architecture. + [19:16] + read-only + + + PARTNO + Number of processor within family: 0xC60 = Cortex-M0+ + [15:4] + read-only + + + REVISION + Minor revision number m in the rnpm revision status: + 0x1 = Patch 1. + [3:0] + read-only + + + + + ICSR + 0x0000ed04 + Use the Interrupt Control State Register to set a pending Non-Maskable Interrupt (NMI), set or clear a pending PendSV, set or clear a pending SysTick, check for pending exceptions, check the vector number of the highest priority pended exception, check the vector number of the active exception. + 0x00000000 + + + NMIPENDSET + Setting this bit will activate an NMI. Since NMI is the highest priority exception, it will activate as soon as it is registered. + NMI set-pending bit. + Write: + 0 = No effect. + 1 = Changes NMI exception state to pending. + Read: + 0 = NMI exception is not pending. + 1 = NMI exception is pending. + Because NMI is the highest-priority exception, normally the processor enters the NMI + exception handler as soon as it detects a write of 1 to this bit. Entering the handler then clears + this bit to 0. This means a read of this bit by the NMI exception handler returns 1 only if the + NMI signal is reasserted while the processor is executing that handler. + [31:31] + read-write + + + PENDSVSET + PendSV set-pending bit. + Write: + 0 = No effect. + 1 = Changes PendSV exception state to pending. + Read: + 0 = PendSV exception is not pending. + 1 = PendSV exception is pending. + Writing 1 to this bit is the only way to set the PendSV exception state to pending. + [28:28] + read-write + + + PENDSVCLR + PendSV clear-pending bit. + Write: + 0 = No effect. + 1 = Removes the pending state from the PendSV exception. + [27:27] + read-write + + + PENDSTSET + SysTick exception set-pending bit. + Write: + 0 = No effect. + 1 = Changes SysTick exception state to pending. + Read: + 0 = SysTick exception is not pending. + 1 = SysTick exception is pending. + [26:26] + read-write + + + PENDSTCLR + SysTick exception clear-pending bit. + Write: + 0 = No effect. + 1 = Removes the pending state from the SysTick exception. + This bit is WO. On a register read its value is Unknown. + [25:25] + read-write + + + ISRPREEMPT + The system can only access this bit when the core is halted. It indicates that a pending interrupt is to be taken in the next running cycle. If C_MASKINTS is clear in the Debug Halting Control and Status Register, the interrupt is serviced. + [23:23] + read-only + + + ISRPENDING + External interrupt pending flag + [22:22] + read-only + + + VECTPENDING + Indicates the exception number for the highest priority pending exception: 0 = no pending exceptions. Non zero = The pending state includes the effect of memory-mapped enable and mask registers. It does not include the PRIMASK special-purpose register qualifier. + [20:12] + read-only + + + VECTACTIVE + Active exception number field. Reset clears the VECTACTIVE field. + [8:0] + read-only + + + + + VTOR + 0x0000ed08 + The VTOR holds the vector table offset address. + 0x00000000 + + + TBLOFF + Bits [31:8] of the indicate the vector table offset address. + [31:8] + read-write + + + + + AIRCR + 0x0000ed0c + Use the Application Interrupt and Reset Control Register to: determine data endianness, clear all active state information from debug halt mode, request a system reset. + 0x00000000 + + + VECTKEY + Register key: + Reads as Unknown + On writes, write 0x05FA to VECTKEY, otherwise the write is ignored. + [31:16] + read-write + + + ENDIANESS + Data endianness implemented: + 0 = Little-endian. + [15:15] + read-only + + + SYSRESETREQ + Writing 1 to this bit causes the SYSRESETREQ signal to the outer system to be asserted to request a reset. The intention is to force a large system reset of all major components except for debug. The C_HALT bit in the DHCSR is cleared as a result of the system reset requested. The debugger does not lose contact with the device. + [2:2] + read-write + + + VECTCLRACTIVE + Clears all active state information for fixed and configurable exceptions. This bit: is self-clearing, can only be set by the DAP when the core is halted. When set: clears all active exception status of the processor, forces a return to Thread mode, forces an IPSR of 0. A debugger must re-initialize the stack. + [1:1] + read-write + + + + + SCR + 0x0000ed10 + System Control Register. Use the System Control Register for power-management functions: signal to the system when the processor can enter a low power state, control how the processor enters and exits low power states. + 0x00000000 + + + SEVONPEND + Send Event on Pending bit: + 0 = Only enabled interrupts or events can wakeup the processor, disabled interrupts are excluded. + 1 = Enabled events and all interrupts, including disabled interrupts, can wakeup the processor. + When an event or interrupt becomes pending, the event signal wakes up the processor from WFE. If the + processor is not waiting for an event, the event is registered and affects the next WFE. + The processor also wakes up on execution of an SEV instruction or an external event. + [4:4] + read-write + + + SLEEPDEEP + Controls whether the processor uses sleep or deep sleep as its low power mode: + 0 = Sleep. + 1 = Deep sleep. + [2:2] + read-write + + + SLEEPONEXIT + Indicates sleep-on-exit when returning from Handler mode to Thread mode: + 0 = Do not sleep when returning to Thread mode. + 1 = Enter sleep, or deep sleep, on return from an ISR to Thread mode. + Setting this bit to 1 enables an interrupt driven application to avoid returning to an empty main application. + [1:1] + read-write + + + + + CCR + 0x0000ed14 + The Configuration and Control Register permanently enables stack alignment and causes unaligned accesses to result in a Hard Fault. + 0x00000000 + + + STKALIGN + Always reads as one, indicates 8-byte stack alignment on exception entry. On exception entry, the processor uses bit[9] of the stacked PSR to indicate the stack alignment. On return from the exception it uses this stacked bit to restore the correct stack alignment. + [9:9] + read-only + + + UNALIGN_TRP + Always reads as one, indicates that all unaligned accesses generate a HardFault. + [3:3] + read-only + + + + + SHPR2 + 0x0000ed1c + System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 2 to set the priority of SVCall. + 0x00000000 + + + PRI_11 + Priority of system handler 11, SVCall + [31:30] + read-write + + + + + SHPR3 + 0x0000ed20 + System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 3 to set the priority of PendSV and SysTick. + 0x00000000 + + + PRI_15 + Priority of system handler 15, SysTick + [31:30] + read-write + + + PRI_14 + Priority of system handler 14, PendSV + [23:22] + read-write + + + + + SHCSR + 0x0000ed24 + Use the System Handler Control and State Register to determine or clear the pending status of SVCall. + 0x00000000 + + + SVCALLPENDED + Reads as 1 if SVCall is Pending. Write 1 to set pending SVCall, write 0 to clear pending SVCall. + [15:15] + read-write + + + + + MPU_TYPE + 0x0000ed90 + Read the MPU Type Register to determine if the processor implements an MPU, and how many regions the MPU supports. + 0x00000800 + + + IREGION + Instruction region. Reads as zero as ARMv6-M only supports a unified MPU. + [23:16] + read-only + + + DREGION + Number of regions supported by the MPU. + [15:8] + read-only + + + SEPARATE + Indicates support for separate instruction and data address maps. Reads as 0 as ARMv6-M only supports a unified MPU. + [0:0] + read-only + + + + + MPU_CTRL + 0x0000ed94 + Use the MPU Control Register to enable and disable the MPU, and to control whether the default memory map is enabled as a background region for privileged accesses, and whether the MPU is enabled for HardFaults and NMIs. + 0x00000000 + + + PRIVDEFENA + Controls whether the default memory map is enabled as a background region for privileged accesses. This bit is ignored when ENABLE is clear. + 0 = If the MPU is enabled, disables use of the default memory map. Any memory access to a location not + covered by any enabled region causes a fault. + 1 = If the MPU is enabled, enables use of the default memory map as a background region for privileged software accesses. + When enabled, the background region acts as if it is region number -1. Any region that is defined and enabled has priority over this default map. + [2:2] + read-write + + + HFNMIENA + Controls the use of the MPU for HardFaults and NMIs. Setting this bit when ENABLE is clear results in UNPREDICTABLE behaviour. + When the MPU is enabled: + 0 = MPU is disabled during HardFault and NMI handlers, regardless of the value of the ENABLE bit. + 1 = the MPU is enabled during HardFault and NMI handlers. + [1:1] + read-write + + + ENABLE + Enables the MPU. If the MPU is disabled, privileged and unprivileged accesses use the default memory map. + 0 = MPU disabled. + 1 = MPU enabled. + [0:0] + read-write + + + + + MPU_RNR + 0x0000ed98 + Use the MPU Region Number Register to select the region currently accessed by MPU_RBAR and MPU_RASR. + 0x00000000 + + + REGION + Indicates the MPU region referenced by the MPU_RBAR and MPU_RASR registers. + The MPU supports 8 memory regions, so the permitted values of this field are 0-7. + [3:0] + read-write + + + + + MPU_RBAR + 0x0000ed9c + Read the MPU Region Base Address Register to determine the base address of the region identified by MPU_RNR. Write to update the base address of said region or that of a specified region, with whose number MPU_RNR will also be updated. + 0x00000000 + + + ADDR + Base address of the region. + [31:8] + read-write + + + VALID + On writes, indicates whether the write must update the base address of the region identified by the REGION field, updating the MPU_RNR to indicate this new region. + Write: + 0 = MPU_RNR not changed, and the processor: + Updates the base address for the region specified in the MPU_RNR. + Ignores the value of the REGION field. + 1 = The processor: + Updates the value of the MPU_RNR to the value of the REGION field. + Updates the base address for the region specified in the REGION field. + Always reads as zero. + [4:4] + read-write + + + REGION + On writes, specifies the number of the region whose base address to update provided VALID is set written as 1. On reads, returns bits [3:0] of MPU_RNR. + [3:0] + read-write + + + + + MPU_RASR + 0x0000eda0 + Use the MPU Region Attribute and Size Register to define the size, access behaviour and memory type of the region identified by MPU_RNR, and enable that region. + 0x00000000 + + + ATTRS + The MPU Region Attribute field. Use to define the region attribute control. + 28 = XN: Instruction access disable bit: + 0 = Instruction fetches enabled. + 1 = Instruction fetches disabled. + 26:24 = AP: Access permission field + 18 = S: Shareable bit + 17 = C: Cacheable bit + 16 = B: Bufferable bit + [31:16] + read-write + + + SRD + Subregion Disable. For regions of 256 bytes or larger, each bit of this field controls whether one of the eight equal subregions is enabled. + [15:8] + read-write + + + SIZE + Indicates the region size. Region size in bytes = 2^(SIZE+1). The minimum permitted value is 7 (b00111) = 256Bytes + [5:1] + read-write + + + ENABLE + Enables the region. + [0:0] + read-write + + + + + + + SSI + DW_apb_ssi has the following features: + * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. + * APB3 and APB4 protocol support. + * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits. + * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices. + * Programmable Dual/Quad/Octal SPI support in Master Mode. + * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation. + * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes. + * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes. + * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests. + * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently. + * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus. + * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains. + * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates. + * Programmable features: + - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire. + - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation. + - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer. + * Configured features: + - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits. + - 1 slave select output. + - Hardware slave-select – Dedicated hardware slave-select line. + - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller. + - Interrupt polarity – active high interrupt lines. + - Serial clock polarity – low serial-clock polarity directly after reset. + - Serial clock phase – capture on first edge of serial-clock directly after reset. + 0x18000000 + + 0 + 252 + registers + + + + CTRLR0 + 0x00000000 + Control register 0 + 0x00000000 + + + SSTE + Slave select toggle enable + [24:24] + read-write + + + SPI_FRF + SPI frame format + [22:21] + read-write + + + STD + 0 + Standard 1-bit SPI frame format; 1 bit per SCK, full-duplex + + + DUAL + 1 + Dual-SPI frame format; two bits per SCK, half-duplex + + + QUAD + 2 + Quad-SPI frame format; four bits per SCK, half-duplex + + + + + DFS_32 + Data frame size in 32b transfer mode + Value of n -> n+1 clocks per frame. + [20:16] + read-write + + + CFS + Control frame size + Value of n -> n+1 clocks per frame. + [15:12] + read-write + + + SRL + Shift register loop (test mode) + [11:11] + read-write + + + SLV_OE + Slave output enable + [10:10] + read-write + + + TMOD + Transfer mode + [9:8] + read-write + + + TX_AND_RX + 0 + Both transmit and receive + + + TX_ONLY + 1 + Transmit only (not for FRF == 0, standard SPI mode) + + + RX_ONLY + 2 + Receive only (not for FRF == 0, standard SPI mode) + + + EEPROM_READ + 3 + EEPROM read mode (TX then RX; RX starts after control data TX'd) + + + + + SCPOL + Serial clock polarity + [7:7] + read-write + + + SCPH + Serial clock phase + [6:6] + read-write + + + FRF + Frame format + [5:4] + read-write + + + DFS + Data frame size + [3:0] + read-write + + + + + CTRLR1 + 0x00000004 + Master Control register 1 + 0x00000000 + + + NDF + Number of data frames + [15:0] + read-write + + + + + SSIENR + 0x00000008 + SSI Enable + 0x00000000 + + + SSI_EN + SSI enable + [0:0] + read-write + + + + + MWCR + 0x0000000c + Microwire Control + 0x00000000 + + + MHS + Microwire handshaking + [2:2] + read-write + + + MDD + Microwire control + [1:1] + read-write + + + MWMOD + Microwire transfer mode + [0:0] + read-write + + + + + SER + 0x00000010 + Slave enable + 0x00000000 + + + SER + For each bit: + 0 -> slave not selected + 1 -> slave selected + [0:0] + read-write + + + + + BAUDR + 0x00000014 + Baud rate + 0x00000000 + + + SCKDV + SSI clock divider + [15:0] + read-write + + + + + TXFTLR + 0x00000018 + TX FIFO threshold level + 0x00000000 + + + TFT + Transmit FIFO threshold + [7:0] + read-write + + + + + RXFTLR + 0x0000001c + RX FIFO threshold level + 0x00000000 + + + RFT + Receive FIFO threshold + [7:0] + read-write + + + + + TXFLR + 0x00000020 + TX FIFO level + 0x00000000 + + + TFTFL + Transmit FIFO level + [7:0] + read-only + + + + + RXFLR + 0x00000024 + RX FIFO level + 0x00000000 + + + RXTFL + Receive FIFO level + [7:0] + read-only + + + + + SR + 0x00000028 + Status register + 0x00000000 + + + DCOL + Data collision error + [6:6] + read-only + + + TXE + Transmission error + [5:5] + read-only + + + RFF + Receive FIFO full + [4:4] + read-only + + + RFNE + Receive FIFO not empty + [3:3] + read-only + + + TFE + Transmit FIFO empty + [2:2] + read-only + + + TFNF + Transmit FIFO not full + [1:1] + read-only + + + BUSY + SSI busy flag + [0:0] + read-only + + + + + IMR + 0x0000002c + Interrupt mask + 0x00000000 + + + MSTIM + Multi-master contention interrupt mask + [5:5] + read-write + + + RXFIM + Receive FIFO full interrupt mask + [4:4] + read-write + + + RXOIM + Receive FIFO overflow interrupt mask + [3:3] + read-write + + + RXUIM + Receive FIFO underflow interrupt mask + [2:2] + read-write + + + TXOIM + Transmit FIFO overflow interrupt mask + [1:1] + read-write + + + TXEIM + Transmit FIFO empty interrupt mask + [0:0] + read-write + + + + + ISR + 0x00000030 + Interrupt status + 0x00000000 + + + MSTIS + Multi-master contention interrupt status + [5:5] + read-only + + + RXFIS + Receive FIFO full interrupt status + [4:4] + read-only + + + RXOIS + Receive FIFO overflow interrupt status + [3:3] + read-only + + + RXUIS + Receive FIFO underflow interrupt status + [2:2] + read-only + + + TXOIS + Transmit FIFO overflow interrupt status + [1:1] + read-only + + + TXEIS + Transmit FIFO empty interrupt status + [0:0] + read-only + + + + + RISR + 0x00000034 + Raw interrupt status + 0x00000000 + + + MSTIR + Multi-master contention raw interrupt status + [5:5] + read-only + + + RXFIR + Receive FIFO full raw interrupt status + [4:4] + read-only + + + RXOIR + Receive FIFO overflow raw interrupt status + [3:3] + read-only + + + RXUIR + Receive FIFO underflow raw interrupt status + [2:2] + read-only + + + TXOIR + Transmit FIFO overflow raw interrupt status + [1:1] + read-only + + + TXEIR + Transmit FIFO empty raw interrupt status + [0:0] + read-only + + + + + TXOICR + 0x00000038 + TX FIFO overflow interrupt clear + 0x00000000 + + + TXOICR + Clear-on-read transmit FIFO overflow interrupt + [0:0] + read-only + + + + + RXOICR + 0x0000003c + RX FIFO overflow interrupt clear + 0x00000000 + + + RXOICR + Clear-on-read receive FIFO overflow interrupt + [0:0] + read-only + + + + + RXUICR + 0x00000040 + RX FIFO underflow interrupt clear + 0x00000000 + + + RXUICR + Clear-on-read receive FIFO underflow interrupt + [0:0] + read-only + + + + + MSTICR + 0x00000044 + Multi-master interrupt clear + 0x00000000 + + + MSTICR + Clear-on-read multi-master contention interrupt + [0:0] + read-only + + + + + ICR + 0x00000048 + Interrupt clear + 0x00000000 + + + ICR + Clear-on-read all active interrupts + [0:0] + read-only + + + + + DMACR + 0x0000004c + DMA control + 0x00000000 + + + TDMAE + Transmit DMA enable + [1:1] + read-write + + + RDMAE + Receive DMA enable + [0:0] + read-write + + + + + DMATDLR + 0x00000050 + DMA TX data level + 0x00000000 + + + DMATDL + Transmit data watermark level + [7:0] + read-write + + + + + DMARDLR + 0x00000054 + DMA RX data level + 0x00000000 + + + DMARDL + Receive data watermark level (DMARDLR+1) + [7:0] + read-write + + + + + IDR + 0x00000058 + Identification register + 0x51535049 + + + IDCODE + Peripheral dentification code + [31:0] + read-only + + + + + SSI_VERSION_ID + 0x0000005c + Version ID + 0x3430312a + + + SSI_COMP_VERSION + SNPS component version (format X.YY) + [31:0] + read-only + + + + + DR0 + 0x00000060 + Data Register 0 (of 36) + 0x00000000 + + + DR + First data register of 36 + [31:0] + read-write + + + + + RX_SAMPLE_DLY + 0x000000f0 + RX sample delay + 0x00000000 + + + RSD + RXD sample delay (in SCLK cycles) + [7:0] + read-write + + + + + SPI_CTRLR0 + 0x000000f4 + SPI control + 0x03000000 + + + XIP_CMD + SPI Command to send in XIP mode (INST_L = 8-bit) or to append to Address (INST_L = 0-bit) + [31:24] + read-write + + + SPI_RXDS_EN + Read data strobe enable + [18:18] + read-write + + + INST_DDR_EN + Instruction DDR transfer enable + [17:17] + read-write + + + SPI_DDR_EN + SPI DDR transfer enable + [16:16] + read-write + + + WAIT_CYCLES + Wait cycles between control frame transmit and data reception (in SCLK cycles) + [15:11] + read-write + + + INST_L + Instruction length (0/4/8/16b) + [9:8] + read-write + + + NONE + 0 + No instruction + + + 4B + 1 + 4-bit instruction + + + 8B + 2 + 8-bit instruction + + + 16B + 3 + 16-bit instruction + + + + + ADDR_L + Address length (0b-60b in 4b increments) + [5:2] + read-write + + + TRANS_TYPE + Address and instruction transfer format + [1:0] + read-write + + + 1C1A + 0 + Command and address both in standard SPI frame format + + + 1C2A + 1 + Command in standard SPI format, address in format specified by FRF + + + 2C2A + 2 + Command and address both in format specified by FRF (e.g. Dual-SPI) + + + + + + + TXD_DRIVE_EDGE + 0x000000f8 + TX drive edge + 0x00000000 + + + TDE + TXD drive edge + [7:0] + read-write + + + + + + + XIP_CTRL + QSPI flash execute-in-place block + 0x14000000 + + 0 + 32 + registers + + + XIP_IRQ + 6 + + + + CTRL + 0x00000000 + Cache control + 0x00000003 + + + POWER_DOWN + When 1, the cache memories are powered down. They retain state, + but can not be accessed. This reduces static power dissipation. + Writing 1 to this bit forces CTRL_EN to 0, i.e. the cache cannot + be enabled when powered down. + Cache-as-SRAM accesses will produce a bus error response when + the cache is powered down. + [3:3] + read-write + + + ERR_BADWRITE + When 1, writes to any alias other than 0x0 (caching, allocating) + will produce a bus fault. When 0, these writes are silently ignored. + In either case, writes to the 0x0 alias will deallocate on tag match, + as usual. + [1:1] + read-write + + + EN + When 1, enable the cache. When the cache is disabled, all XIP accesses + will go straight to the flash, without querying the cache. When enabled, + cacheable XIP accesses will query the cache, and the flash will + not be accessed if the tag matches and the valid bit is set. + + If the cache is enabled, cache-as-SRAM accesses have no effect on the + cache data RAM, and will produce a bus error response. + [0:0] + read-write + + + + + FLUSH + 0x00000004 + Cache Flush control + 0x00000000 + + + FLUSH + Write 1 to flush the cache. This clears the tag memory, but + the data memory retains its contents. (This means cache-as-SRAM + contents is not affected by flush or reset.) + Reading will hold the bus (stall the processor) until the flush + completes. Alternatively STAT can be polled until completion. + [0:0] + write-only + + + + + STAT + 0x00000008 + Cache Status + 0x00000002 + + + FIFO_FULL + When 1, indicates the XIP streaming FIFO is completely full. + The streaming FIFO is 2 entries deep, so the full and empty + flag allow its level to be ascertained. + [2:2] + read-only + + + FIFO_EMPTY + When 1, indicates the XIP streaming FIFO is completely empty. + [1:1] + read-only + + + FLUSH_READY + Reads as 0 while a cache flush is in progress, and 1 otherwise. + The cache is flushed whenever the XIP block is reset, and also + when requested via the FLUSH register. + [0:0] + read-only + + + + + CTR_HIT + 0x0000000c + Cache Hit counter + 0x00000000 + + + CTR_HIT + A 32 bit saturating counter that increments upon each cache hit, + i.e. when an XIP access is serviced directly from cached data. + Write any value to clear. + [31:0] + read-write + oneToClear + + + + + CTR_ACC + 0x00000010 + Cache Access counter + 0x00000000 + + + CTR_ACC + A 32 bit saturating counter that increments upon each XIP access, + whether the cache is hit or not. This includes noncacheable accesses. + Write any value to clear. + [31:0] + read-write + oneToClear + + + + + STREAM_ADDR + 0x00000014 + FIFO stream address + 0x00000000 + + + STREAM_ADDR + The address of the next word to be streamed from flash to the streaming FIFO. + Increments automatically after each flash access. + Write the initial access address here before starting a streaming read. + [31:2] + read-write + + + + + STREAM_CTR + 0x00000018 + FIFO stream control + 0x00000000 + + + STREAM_CTR + Write a nonzero value to start a streaming read. This will then + progress in the background, using flash idle cycles to transfer + a linear data block from flash to the streaming FIFO. + Decrements automatically (1 at a time) as the stream + progresses, and halts on reaching 0. + Write 0 to halt an in-progress stream, and discard any in-flight + read, so that a new stream can immediately be started (after + draining the FIFO and reinitialising STREAM_ADDR) + [21:0] + read-write + + + + + STREAM_FIFO + 0x0000001c + FIFO stream data + 0x00000000 + + + STREAM_FIFO + Streamed data is buffered here, for retrieval by the system DMA. + This FIFO can also be accessed via the XIP_AUX slave, to avoid exposing + the DMA to bus stalls caused by other XIP traffic. + [31:0] + read-only + modify + + + + + + + SYSCFG + Register block for various chip control signals + 0x40004000 + + 0 + 28 + registers + + + + PROC0_NMI_MASK + 0x00000000 + Processor core 0 NMI source mask + 0x00000000 + + + PROC0_NMI_MASK + Set a bit high to enable NMI from that IRQ + [31:0] + read-write + + + + + PROC1_NMI_MASK + 0x00000004 + Processor core 1 NMI source mask + 0x00000000 + + + PROC1_NMI_MASK + Set a bit high to enable NMI from that IRQ + [31:0] + read-write + + + + + PROC_CONFIG + 0x00000008 + Configuration for processors + 0x10000000 + + + PROC1_DAP_INSTID + Configure proc1 DAP instance ID. + Recommend that this is NOT changed until you require debug access in multi-chip environment + WARNING: do not set to 15 as this is reserved for RescueDP + [31:28] + read-write + + + PROC0_DAP_INSTID + Configure proc0 DAP instance ID. + Recommend that this is NOT changed until you require debug access in multi-chip environment + WARNING: do not set to 15 as this is reserved for RescueDP + [27:24] + read-write + + + PROC1_HALTED + Indication that proc1 has halted + [1:1] + read-only + + + PROC0_HALTED + Indication that proc0 has halted + [0:0] + read-only + + + + + PROC_IN_SYNC_BYPASS + 0x0000000c + For each bit, if 1, bypass the input synchronizer between that GPIO + and the GPIO input register in the SIO. The input synchronizers should + generally be unbypassed, to avoid injecting metastabilities into processors. + If you're feeling brave, you can bypass to save two cycles of input + latency. This register applies to GPIO 0...29. + 0x00000000 + + + PROC_IN_SYNC_BYPASS + [29:0] + read-write + + + + + PROC_IN_SYNC_BYPASS_HI + 0x00000010 + For each bit, if 1, bypass the input synchronizer between that GPIO + and the GPIO input register in the SIO. The input synchronizers should + generally be unbypassed, to avoid injecting metastabilities into processors. + If you're feeling brave, you can bypass to save two cycles of input + latency. This register applies to GPIO 30...35 (the QSPI IOs). + 0x00000000 + + + PROC_IN_SYNC_BYPASS_HI + [5:0] + read-write + + + + + DBGFORCE + 0x00000014 + Directly control the SWD debug port of either processor + 0x00000066 + + + PROC1_ATTACH + Attach processor 1 debug port to syscfg controls, and disconnect it from external SWD pads. + [7:7] + read-write + + + PROC1_SWCLK + Directly drive processor 1 SWCLK, if PROC1_ATTACH is set + [6:6] + read-write + + + PROC1_SWDI + Directly drive processor 1 SWDIO input, if PROC1_ATTACH is set + [5:5] + read-write + + + PROC1_SWDO + Observe the value of processor 1 SWDIO output. + [4:4] + read-only + + + PROC0_ATTACH + Attach processor 0 debug port to syscfg controls, and disconnect it from external SWD pads. + [3:3] + read-write + + + PROC0_SWCLK + Directly drive processor 0 SWCLK, if PROC0_ATTACH is set + [2:2] + read-write + + + PROC0_SWDI + Directly drive processor 0 SWDIO input, if PROC0_ATTACH is set + [1:1] + read-write + + + PROC0_SWDO + Observe the value of processor 0 SWDIO output. + [0:0] + read-only + + + + + MEMPOWERDOWN + 0x00000018 + Control power downs to memories. Set high to power down memories. + Use with extreme caution + 0x00000000 + + + ROM + [7:7] + read-write + + + USB + [6:6] + read-write + + + SRAM5 + [5:5] + read-write + + + SRAM4 + [4:4] + read-write + + + SRAM3 + [3:3] + read-write + + + SRAM2 + [2:2] + read-write + + + SRAM1 + [1:1] + read-write + + + SRAM0 + [0:0] + read-write + + + + + + + XOSC + Controls the crystal oscillator + 0x40024000 + + 0 + 32 + registers + + + + CTRL + 0x00000000 + Crystal Oscillator Control + 0x00000000 + + + ENABLE + On power-up this field is initialised to DISABLE and the chip runs from the ROSC. + If the chip has subsequently been programmed to run from the XOSC then DISABLE may lock-up the chip. If this is a concern then run the clk_ref from the ROSC and enable the clk_sys RESUS feature. + The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + [23:12] + read-write + + + DISABLE + 3358 + + + ENABLE + 4011 + + + + + FREQ_RANGE + Frequency range. An invalid setting will retain the previous value. The actual value being used can be read from STATUS_FREQ_RANGE. This resets to 0xAA0 and cannot be changed. + [11:0] + read-write + + + 1_15MHZ + 2720 + + + RESERVED_1 + 2721 + + + RESERVED_2 + 2722 + + + RESERVED_3 + 2723 + + + + + + + STATUS + 0x00000004 + Crystal Oscillator Status + 0x00000000 + + + STABLE + Oscillator is running and stable + [31:31] + read-only + + + BADWRITE + An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or DORMANT + [24:24] + read-write + oneToClear + + + ENABLED + Oscillator is enabled but not necessarily running and stable, resets to 0 + [12:12] + read-only + + + FREQ_RANGE + The current frequency range setting, always reads 0 + [1:0] + read-only + + + 1_15MHZ + 0 + + + RESERVED_1 + 1 + + + RESERVED_2 + 2 + + + RESERVED_3 + 3 + + + + + + + DORMANT + 0x00000008 + Crystal Oscillator pause control + 0x00000000 + + + DORMANT + This is used to save power by pausing the XOSC + On power-up this field is initialised to WAKE + An invalid write will also select WAKE + Warning: stop the PLLs before selecting dormant mode + Warning: setup the irq before selecting dormant mode + [31:0] + read-write + + + dormant + 1668246881 + + + WAKE + 2002873189 + + + + + + + STARTUP + 0x0000000c + Controls the startup delay + 0x00000000 + + + X4 + Multiplies the startup_delay by 4. This is of little value to the user given that the delay can be programmed directly. + [20:20] + read-write + + + DELAY + in multiples of 256*xtal_period. The reset value of 0xc4 corresponds to approx 50 000 cycles. + [13:0] + read-write + + + + + COUNT + 0x0000001c + A down counter running at the xosc frequency which counts to zero and stops. + To start the counter write a non-zero value. + Can be used for short software pauses when setting up time sensitive hardware. + 0x00000000 + + + COUNT + [7:0] + read-write + + + + + + + PLL_SYS + 0x40028000 + + 0 + 16 + registers + + + + CS + 0x00000000 + Control and Status + GENERAL CONSTRAINTS: + Reference clock frequency min=5MHz, max=800MHz + Feedback divider min=16, max=320 + VCO frequency min=750MHz, max=1600MHz + 0x00000001 + + + LOCK + PLL is locked + [31:31] + read-only + + + BYPASS + Passes the reference clock to the output instead of the divided VCO. The VCO continues to run so the user can switch between the reference clock and the divided VCO but the output will glitch when doing so. + [8:8] + read-write + + + REFDIV + Divides the PLL input reference clock. + Behaviour is undefined for div=0. + PLL output will be unpredictable during refdiv changes, wait for lock=1 before using it. + [5:0] + read-write + + + + + PWR + 0x00000004 + Controls the PLL power modes. + 0x0000002d + + + VCOPD + PLL VCO powerdown + To save power set high when PLL output not required or bypass=1. + [5:5] + read-write + + + POSTDIVPD + PLL post divider powerdown + To save power set high when PLL output not required or bypass=1. + [3:3] + read-write + + + DSMPD + PLL DSM powerdown + Nothing is achieved by setting this low. + [2:2] + read-write + + + PD + PLL powerdown + To save power set high when PLL output not required. + [0:0] + read-write + + + + + FBDIV_INT + 0x00000008 + Feedback divisor + (note: this PLL does not support fractional division) + 0x00000000 + + + FBDIV_INT + see ctrl reg description for constraints + [11:0] + read-write + + + + + PRIM + 0x0000000c + Controls the PLL post dividers for the primary output + (note: this PLL does not have a secondary output) + the primary output is driven from VCO divided by postdiv1*postdiv2 + 0x00077000 + + + POSTDIV1 + divide by 1-7 + [18:16] + read-write + + + POSTDIV2 + divide by 1-7 + [14:12] + read-write + + + + + + + PLL_USB + 0x4002c000 + + + UART0 + 0x40034000 + + 0 + 4096 + registers + + + UART0_IRQ + 20 + + + + UARTDR + 0x00000000 + Data Register, UARTDR + 0x00000000 + + + OE + Overrun error. This bit is set to 1 if data is received and the receive FIFO is already full. This is cleared to 0 once there is an empty space in the FIFO and a new character can be written to it. + [11:11] + read-only + + + BE + Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity and stop bits). In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state), and the next valid start bit is received. + [10:10] + read-only + + + PE + Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. In FIFO mode, this error is associated with the character at the top of the FIFO. + [9:9] + read-only + + + FE + Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is associated with the character at the top of the FIFO. + [8:8] + read-only + + + DATA + Receive (read) data character. Transmit (write) data character. + [7:0] + read-write + modify + + + + + UARTRSR + 0x00000004 + Receive Status Register/Error Clear Register, UARTRSR/UARTECR + 0x00000000 + + + OE + Overrun error. This bit is set to 1 if data is received and the FIFO is already full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain valid because no more data is written when the FIFO is full, only the contents of the shift register are overwritten. The CPU must now read the data, to empty the FIFO. + [3:3] + read-write + oneToClear + + + BE + Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity, and stop bits). This bit is cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state) and the next valid start bit is received. + [2:2] + read-write + oneToClear + + + PE + Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + [1:1] + read-write + oneToClear + + + FE + Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + [0:0] + read-write + oneToClear + + + + + UARTFR + 0x00000018 + Flag Register, UARTFR + 0x00000090 + + + RI + Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW. + [8:8] + read-only + + + TXFE + Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is set when the transmit holding register is empty. If the FIFO is enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if there is data in the transmit shift register. + [7:7] + read-only + + + RXFF + Receive FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is full. If the FIFO is enabled, the RXFF bit is set when the receive FIFO is full. + [6:6] + read-only + + + TXFF + Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set when the transmit FIFO is full. + [5:5] + read-only + + + RXFE + Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set when the receive FIFO is empty. + [4:4] + read-only + + + BUSY + UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit remains set until the complete byte, including all the stop bits, has been sent from the shift register. This bit is set as soon as the transmit FIFO becomes non-empty, regardless of whether the UART is enabled or not. + [3:3] + read-only + + + DCD + Data carrier detect. This bit is the complement of the UART data carrier detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. + [2:2] + read-only + + + DSR + Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW. + [1:1] + read-only + + + CTS + Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW. + [0:0] + read-only + + + + + UARTILPR + 0x00000020 + IrDA Low-Power Counter Register, UARTILPR + 0x00000000 + + + ILPDVSR + 8-bit low-power divisor value. These bits are cleared to 0 at reset. + [7:0] + read-write + + + + + UARTIBRD + 0x00000024 + Integer Baud Rate Register, UARTIBRD + 0x00000000 + + + BAUD_DIVINT + The integer baud rate divisor. These bits are cleared to 0 on reset. + [15:0] + read-write + + + + + UARTFBRD + 0x00000028 + Fractional Baud Rate Register, UARTFBRD + 0x00000000 + + + BAUD_DIVFRAC + The fractional baud rate divisor. These bits are cleared to 0 on reset. + [5:0] + read-write + + + + + UARTLCR_H + 0x0000002c + Line Control Register, UARTLCR_H + 0x00000000 + + + SPS + Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then the parity bit is transmitted and checked as a 0. This bit has no effect when the PEN bit disables parity checking and generation. + [7:7] + read-write + + + WLEN + Word length. These bits indicate the number of data bits transmitted or received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. + [6:5] + read-write + + + FEN + Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled (FIFO mode). + [4:4] + read-write + + + STP2 + Two stop bits select. If this bit is set to 1, two stop bits are transmitted at the end of the frame. The receive logic does not check for two stop bits being received. + [3:3] + read-write + + + EPS + Even parity select. Controls the type of parity the UART uses during transmission and reception: 0 = odd parity. The UART generates or checks for an odd number of 1s in the data and parity bits. 1 = even parity. The UART generates or checks for an even number of 1s in the data and parity bits. This bit has no effect when the PEN bit disables parity checking and generation. + [2:2] + read-write + + + PEN + Parity enable: 0 = parity is disabled and no parity bit added to the data frame 1 = parity checking and generation is enabled. + [1:1] + read-write + + + BRK + Send break. If this bit is set to 1, a low-level is continually output on the UARTTXD output, after completing transmission of the current character. For the proper execution of the break command, the software must set this bit for at least two complete frames. For normal use, this bit must be cleared to 0. + [0:0] + read-write + + + + + UARTCR + 0x00000030 + Control Register, UARTCR + 0x00000300 + + + CTSEN + CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow control is enabled. Data is only transmitted when the nUARTCTS signal is asserted. + [15:15] + read-write + + + RTSEN + RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow control is enabled. Data is only requested when there is space in the receive FIFO for it to be received. + [14:14] + read-write + + + OUT2 + This bit is the complement of the UART Out2 (nUARTOut2) modem status output. That is, when the bit is programmed to a 1, the output is 0. For DTE this can be used as Ring Indicator (RI). + [13:13] + read-write + + + OUT1 + This bit is the complement of the UART Out1 (nUARTOut1) modem status output. That is, when the bit is programmed to a 1 the output is 0. For DTE this can be used as Data Carrier Detect (DCD). + [12:12] + read-write + + + RTS + Request to send. This bit is the complement of the UART request to send, nUARTRTS, modem status output. That is, when the bit is programmed to a 1 then nUARTRTS is LOW. + [11:11] + read-write + + + DTR + Data transmit ready. This bit is the complement of the UART data transmit ready, nUARTDTR, modem status output. That is, when the bit is programmed to a 1 then nUARTDTR is LOW. + [10:10] + read-write + + + RXE + Receive enable. If this bit is set to 1, the receive section of the UART is enabled. Data reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of reception, it completes the current character before stopping. + [9:9] + read-write + + + TXE + Transmit enable. If this bit is set to 1, the transmit section of the UART is enabled. Data transmission occurs for either UART signals, or SIR signals depending on the setting of the SIREN bit. When the UART is disabled in the middle of transmission, it completes the current character before stopping. + [8:8] + read-write + + + LBE + Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and the SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the nSIROUT path is inverted, and fed through to the SIRIN path. The SIRTEST bit in the test register must be set to 1 to override the normal half-duplex SIR operation. This must be the requirement for accessing the test registers during normal operation, and SIRTEST must be cleared to 0 when loopback testing is finished. This feature reduces the amount of external coupling required during system test. If this bit is set to 1, and the SIRTEST bit is set to 0, the UARTTXD path is fed through to the UARTRXD path. In either SIR mode or UART mode, when this bit is set, the modem outputs are also fed through to the modem inputs. This bit is cleared to 0 on reset, to disable loopback. + [7:7] + read-write + + + SIRLP + SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If this bit is cleared to 0, low-level bits are transmitted as an active high pulse with a width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are transmitted with a pulse width that is 3 times the period of the IrLPBaud16 input signal, regardless of the selected bit rate. Setting this bit uses less power, but might reduce transmission distances. + [2:2] + read-write + + + SIREN + SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no light pulse generated), and signal transitions on SIRIN have no effect. 1 = IrDA SIR ENDEC is enabled. Data is transmitted and received on nSIROUT and SIRIN. UARTTXD remains HIGH, in the marking state. Signal transitions on UARTRXD or modem status inputs have no effect. This bit has no effect if the UARTEN bit disables the UART. + [1:1] + read-write + + + UARTEN + UART enable: 0 = UART is disabled. If the UART is disabled in the middle of transmission or reception, it completes the current character before stopping. 1 = the UART is enabled. Data transmission and reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. + [0:0] + read-write + + + + + UARTIFLS + 0x00000034 + Interrupt FIFO Level Select Register, UARTIFLS + 0x00000012 + + + RXIFLSEL + Receive interrupt FIFO level select. The trigger points for the receive interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 full b101-b111 = reserved. + [5:3] + read-write + + + TXIFLSEL + Transmit interrupt FIFO level select. The trigger points for the transmit interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 full b101-b111 = reserved. + [2:0] + read-write + + + + + UARTIMSC + 0x00000038 + Interrupt Mask Set/Clear Register, UARTIMSC + 0x00000000 + + + OEIM + Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write of 0 clears the mask. + [10:10] + read-write + + + BEIM + Break error interrupt mask. A read returns the current mask for the UARTBEINTR interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write of 0 clears the mask. + [9:9] + read-write + + + PEIM + Parity error interrupt mask. A read returns the current mask for the UARTPEINTR interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write of 0 clears the mask. + [8:8] + read-write + + + FEIM + Framing error interrupt mask. A read returns the current mask for the UARTFEINTR interrupt. On a write of 1, the mask of the UARTFEINTR interrupt is set. A write of 0 clears the mask. + [7:7] + read-write + + + RTIM + Receive timeout interrupt mask. A read returns the current mask for the UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt is set. A write of 0 clears the mask. + [6:6] + read-write + + + TXIM + Transmit interrupt mask. A read returns the current mask for the UARTTXINTR interrupt. On a write of 1, the mask of the UARTTXINTR interrupt is set. A write of 0 clears the mask. + [5:5] + read-write + + + RXIM + Receive interrupt mask. A read returns the current mask for the UARTRXINTR interrupt. On a write of 1, the mask of the UARTRXINTR interrupt is set. A write of 0 clears the mask. + [4:4] + read-write + + + DSRMIM + nUARTDSR modem interrupt mask. A read returns the current mask for the UARTDSRINTR interrupt. On a write of 1, the mask of the UARTDSRINTR interrupt is set. A write of 0 clears the mask. + [3:3] + read-write + + + DCDMIM + nUARTDCD modem interrupt mask. A read returns the current mask for the UARTDCDINTR interrupt. On a write of 1, the mask of the UARTDCDINTR interrupt is set. A write of 0 clears the mask. + [2:2] + read-write + + + CTSMIM + nUARTCTS modem interrupt mask. A read returns the current mask for the UARTCTSINTR interrupt. On a write of 1, the mask of the UARTCTSINTR interrupt is set. A write of 0 clears the mask. + [1:1] + read-write + + + RIMIM + nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write of 0 clears the mask. + [0:0] + read-write + + + + + UARTRIS + 0x0000003c + Raw Interrupt Status Register, UARTRIS + 0x00000000 + + + OERIS + Overrun error interrupt status. Returns the raw interrupt state of the UARTOEINTR interrupt. + [10:10] + read-only + + + BERIS + Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR interrupt. + [9:9] + read-only + + + PERIS + Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR interrupt. + [8:8] + read-only + + + FERIS + Framing error interrupt status. Returns the raw interrupt state of the UARTFEINTR interrupt. + [7:7] + read-only + + + RTRIS + Receive timeout interrupt status. Returns the raw interrupt state of the UARTRTINTR interrupt. a + [6:6] + read-only + + + TXRIS + Transmit interrupt status. Returns the raw interrupt state of the UARTTXINTR interrupt. + [5:5] + read-only + + + RXRIS + Receive interrupt status. Returns the raw interrupt state of the UARTRXINTR interrupt. + [4:4] + read-only + + + DSRRMIS + nUARTDSR modem interrupt status. Returns the raw interrupt state of the UARTDSRINTR interrupt. + [3:3] + read-only + + + DCDRMIS + nUARTDCD modem interrupt status. Returns the raw interrupt state of the UARTDCDINTR interrupt. + [2:2] + read-only + + + CTSRMIS + nUARTCTS modem interrupt status. Returns the raw interrupt state of the UARTCTSINTR interrupt. + [1:1] + read-only + + + RIRMIS + nUARTRI modem interrupt status. Returns the raw interrupt state of the UARTRIINTR interrupt. + [0:0] + read-only + + + + + UARTMIS + 0x00000040 + Masked Interrupt Status Register, UARTMIS + 0x00000000 + + + OEMIS + Overrun error masked interrupt status. Returns the masked interrupt state of the UARTOEINTR interrupt. + [10:10] + read-only + + + BEMIS + Break error masked interrupt status. Returns the masked interrupt state of the UARTBEINTR interrupt. + [9:9] + read-only + + + PEMIS + Parity error masked interrupt status. Returns the masked interrupt state of the UARTPEINTR interrupt. + [8:8] + read-only + + + FEMIS + Framing error masked interrupt status. Returns the masked interrupt state of the UARTFEINTR interrupt. + [7:7] + read-only + + + RTMIS + Receive timeout masked interrupt status. Returns the masked interrupt state of the UARTRTINTR interrupt. + [6:6] + read-only + + + TXMIS + Transmit masked interrupt status. Returns the masked interrupt state of the UARTTXINTR interrupt. + [5:5] + read-only + + + RXMIS + Receive masked interrupt status. Returns the masked interrupt state of the UARTRXINTR interrupt. + [4:4] + read-only + + + DSRMMIS + nUARTDSR modem masked interrupt status. Returns the masked interrupt state of the UARTDSRINTR interrupt. + [3:3] + read-only + + + DCDMMIS + nUARTDCD modem masked interrupt status. Returns the masked interrupt state of the UARTDCDINTR interrupt. + [2:2] + read-only + + + CTSMMIS + nUARTCTS modem masked interrupt status. Returns the masked interrupt state of the UARTCTSINTR interrupt. + [1:1] + read-only + + + RIMMIS + nUARTRI modem masked interrupt status. Returns the masked interrupt state of the UARTRIINTR interrupt. + [0:0] + read-only + + + + + UARTICR + 0x00000044 + Interrupt Clear Register, UARTICR + 0x00000000 + + + OEIC + Overrun error interrupt clear. Clears the UARTOEINTR interrupt. + [10:10] + read-write + oneToClear + + + BEIC + Break error interrupt clear. Clears the UARTBEINTR interrupt. + [9:9] + read-write + oneToClear + + + PEIC + Parity error interrupt clear. Clears the UARTPEINTR interrupt. + [8:8] + read-write + oneToClear + + + FEIC + Framing error interrupt clear. Clears the UARTFEINTR interrupt. + [7:7] + read-write + oneToClear + + + RTIC + Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. + [6:6] + read-write + oneToClear + + + TXIC + Transmit interrupt clear. Clears the UARTTXINTR interrupt. + [5:5] + read-write + oneToClear + + + RXIC + Receive interrupt clear. Clears the UARTRXINTR interrupt. + [4:4] + read-write + oneToClear + + + DSRMIC + nUARTDSR modem interrupt clear. Clears the UARTDSRINTR interrupt. + [3:3] + read-write + oneToClear + + + DCDMIC + nUARTDCD modem interrupt clear. Clears the UARTDCDINTR interrupt. + [2:2] + read-write + oneToClear + + + CTSMIC + nUARTCTS modem interrupt clear. Clears the UARTCTSINTR interrupt. + [1:1] + read-write + oneToClear + + + RIMIC + nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. + [0:0] + read-write + oneToClear + + + + + UARTDMACR + 0x00000048 + DMA Control Register, UARTDMACR + 0x00000000 + + + DMAONERR + DMA on error. If this bit is set to 1, the DMA receive request outputs, UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is asserted. + [2:2] + read-write + + + TXDMAE + Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + [1:1] + read-write + + + RXDMAE + Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is enabled. + [0:0] + read-write + + + + + UARTPERIPHID0 + 0x00000fe0 + UARTPeriphID0 Register + 0x00000011 + + + PARTNUMBER0 + These bits read back as 0x11 + [7:0] + read-only + + + + + UARTPERIPHID1 + 0x00000fe4 + UARTPeriphID1 Register + 0x00000010 + + + DESIGNER0 + These bits read back as 0x1 + [7:4] + read-only + + + PARTNUMBER1 + These bits read back as 0x0 + [3:0] + read-only + + + + + UARTPERIPHID2 + 0x00000fe8 + UARTPeriphID2 Register + 0x00000034 + + + REVISION + This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 0x2 r1p5 0x3 + [7:4] + read-only + + + DESIGNER1 + These bits read back as 0x4 + [3:0] + read-only + + + + + UARTPERIPHID3 + 0x00000fec + UARTPeriphID3 Register + 0x00000000 + + + CONFIGURATION + These bits read back as 0x00 + [7:0] + read-only + + + + + UARTPCELLID0 + 0x00000ff0 + UARTPCellID0 Register + 0x0000000d + + + UARTPCELLID0 + These bits read back as 0x0D + [7:0] + read-only + + + + + UARTPCELLID1 + 0x00000ff4 + UARTPCellID1 Register + 0x000000f0 + + + UARTPCELLID1 + These bits read back as 0xF0 + [7:0] + read-only + + + + + UARTPCELLID2 + 0x00000ff8 + UARTPCellID2 Register + 0x00000005 + + + UARTPCELLID2 + These bits read back as 0x05 + [7:0] + read-only + + + + + UARTPCELLID3 + 0x00000ffc + UARTPCellID3 Register + 0x000000b1 + + + UARTPCELLID3 + These bits read back as 0xB1 + [7:0] + read-only + + + + + + + UART1 + 0x40038000 + + UART1_IRQ + 21 + + + + ROSC + 0x40060000 + + 0 + 36 + registers + + + + CTRL + 0x00000000 + Ring Oscillator control + 0x00000aa0 + + + ENABLE + On power-up this field is initialised to ENABLE + The system clock must be switched to another source before setting this field to DISABLE otherwise the chip will lock up + The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + [23:12] + read-write + + + DISABLE + 3358 + + + ENABLE + 4011 + + + + + FREQ_RANGE + Controls the number of delay stages in the ROSC ring + LOW uses stages 0 to 7 + MEDIUM uses stages 2 to 7 + HIGH uses stages 4 to 7 + TOOHIGH uses stages 6 to 7 and should not be used because its frequency exceeds design specifications + The clock output will not glitch when changing the range up one step at a time + The clock output will glitch when changing the range down + Note: the values here are gray coded which is why HIGH comes before TOOHIGH + [11:0] + read-write + + + LOW + 4004 + + + MEDIUM + 4005 + + + HIGH + 4007 + + + TOOHIGH + 4006 + + + + + + + FREQA + 0x00000004 + The FREQA & FREQB registers control the frequency by controlling the drive strength of each stage + The drive strength has 4 levels determined by the number of bits set + Increasing the number of bits set increases the drive strength and increases the oscillation frequency + 0 bits set is the default drive strength + 1 bit set doubles the drive strength + 2 bits set triples drive strength + 3 bits set quadruples drive strength + 0x00000000 + + + PASSWD + Set to 0x9696 to apply the settings + Any other value in this field will set all drive strengths to 0 + [31:16] + read-write + + + PASS + 38550 + + + + + DS3 + Stage 3 drive strength + [14:12] + read-write + + + DS2 + Stage 2 drive strength + [10:8] + read-write + + + DS1 + Stage 1 drive strength + [6:4] + read-write + + + DS0 + Stage 0 drive strength + [2:0] + read-write + + + + + FREQB + 0x00000008 + For a detailed description see freqa register + 0x00000000 + + + PASSWD + Set to 0x9696 to apply the settings + Any other value in this field will set all drive strengths to 0 + [31:16] + read-write + + + PASS + 38550 + + + + + DS7 + Stage 7 drive strength + [14:12] + read-write + + + DS6 + Stage 6 drive strength + [10:8] + read-write + + + DS5 + Stage 5 drive strength + [6:4] + read-write + + + DS4 + Stage 4 drive strength + [2:0] + read-write + + + + + DORMANT + 0x0000000c + Ring Oscillator pause control + 0x00000000 + + + DORMANT + This is used to save power by pausing the ROSC + On power-up this field is initialised to WAKE + An invalid write will also select WAKE + Warning: setup the irq before selecting dormant mode + [31:0] + read-write + + + dormant + 1668246881 + + + WAKE + 2002873189 + + + + + + + DIV + 0x00000010 + Controls the output divider + 0x00000000 + + + DIV + set to 0xaa0 + div where + div = 0 divides by 32 + div = 1-31 divides by div + any other value sets div=31 + this register resets to div=16 + [11:0] + read-write + + + PASS + 2720 + + + + + + + PHASE + 0x00000014 + Controls the phase shifted output + 0x00000008 + + + PASSWD + set to 0xaa + any other value enables the output with shift=0 + [11:4] + read-write + + + ENABLE + enable the phase-shifted output + this can be changed on-the-fly + [3:3] + read-write + + + FLIP + invert the phase-shifted output + this is ignored when div=1 + [2:2] + read-write + + + SHIFT + phase shift the phase-shifted output by SHIFT input clocks + this can be changed on-the-fly + must be set to 0 before setting div=1 + [1:0] + read-write + + + + + STATUS + 0x00000018 + Ring Oscillator Status + 0x00000000 + + + STABLE + Oscillator is running and stable + [31:31] + read-only + + + BADWRITE + An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or FREQA or FREQB or DIV or PHASE or DORMANT + [24:24] + read-write + oneToClear + + + DIV_RUNNING + post-divider is running + this resets to 0 but transitions to 1 during chip startup + [16:16] + read-only + + + ENABLED + Oscillator is enabled but not necessarily running and stable + this resets to 0 but transitions to 1 during chip startup + [12:12] + read-only + + + + + RANDOMBIT + 0x0000001c + This just reads the state of the oscillator output so randomness is compromised if the ring oscillator is stopped or run at a harmonic of the bus frequency + 0x00000001 + + + RANDOMBIT + [0:0] + read-only + + + + + COUNT + 0x00000020 + A down counter running at the ROSC frequency which counts to zero and stops. + To start the counter write a non-zero value. + Can be used for short software pauses when setting up time sensitive hardware. + 0x00000000 + + + COUNT + [7:0] + read-write + + + + + + + WATCHDOG + 0x40058000 + + 0 + 48 + registers + + + + CTRL + 0x00000000 + Watchdog control + The rst_wdsel register determines which subsystems are reset when the watchdog is triggered. + The watchdog can be triggered in software. + 0x07000000 + + + TRIGGER + Trigger a watchdog reset + [31:31] + write-only + + + ENABLE + When not enabled the watchdog timer is paused + [30:30] + read-write + + + PAUSE_DBG1 + Pause the watchdog timer when processor 1 is in debug mode + [26:26] + read-write + + + PAUSE_DBG0 + Pause the watchdog timer when processor 0 is in debug mode + [25:25] + read-write + + + PAUSE_JTAG + Pause the watchdog timer when JTAG is accessing the bus fabric + [24:24] + read-write + + + TIME + Indicates the number of ticks / 2 (see errata RP2040-E1) before a watchdog reset will be triggered + [23:0] + read-only + + + + + LOAD + 0x00000004 + Load the watchdog timer. The maximum setting is 0xffffff which corresponds to 0xffffff / 2 ticks before triggering a watchdog reset (see errata RP2040-E1). + 0x00000000 + + + LOAD + [23:0] + write-only + + + + + REASON + 0x00000008 + Logs the reason for the last reset. Both bits are zero for the case of a hardware reset. + 0x00000000 + + + FORCE + [1:1] + read-only + + + TIMER + [0:0] + read-only + + + + + SCRATCH0 + 0x0000000c + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH0 + [31:0] + read-write + + + + + SCRATCH1 + 0x00000010 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH1 + [31:0] + read-write + + + + + SCRATCH2 + 0x00000014 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH2 + [31:0] + read-write + + + + + SCRATCH3 + 0x00000018 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH3 + [31:0] + read-write + + + + + SCRATCH4 + 0x0000001c + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH4 + [31:0] + read-write + + + + + SCRATCH5 + 0x00000020 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH5 + [31:0] + read-write + + + + + SCRATCH6 + 0x00000024 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH6 + [31:0] + read-write + + + + + SCRATCH7 + 0x00000028 + Scratch register. Information persists through soft reset of the chip. + 0x00000000 + + + SCRATCH7 + [31:0] + read-write + + + + + TICK + 0x0000002c + Controls the tick generator + 0x00000200 + + + COUNT + Count down timer: the remaining number clk_tick cycles before the next tick is generated. + [19:11] + read-only + + + RUNNING + Is the tick generator running? + [10:10] + read-only + + + ENABLE + start / stop tick generation + [9:9] + read-write + + + CYCLES + Total number of clk_tick cycles before the next tick. + [8:0] + read-write + + + + + + + DMA + DMA with separate read and write masters + 0x50000000 + + 0 + 2760 + registers + + + DMA_IRQ_0 + 11 + + + DMA_IRQ_1 + 12 + + + + CH0_READ_ADDR + 0x00000000 + DMA Channel 0 Read Address pointer + 0x00000000 + + + CH0_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH0_WRITE_ADDR + 0x00000004 + DMA Channel 0 Write Address pointer + 0x00000000 + + + CH0_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH0_TRANS_COUNT + 0x00000008 + DMA Channel 0 Transfer Count + 0x00000000 + + + CH0_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH0_CTRL_TRIG + 0x0000000c + DMA Channel 0 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH0_AL1_CTRL + 0x00000010 + Alias for channel 0 CTRL register + 0x00000000 + + + CH0_AL1_CTRL + [31:0] + read-write + + + + + CH0_AL1_READ_ADDR + 0x00000014 + Alias for channel 0 READ_ADDR register + 0x00000000 + + + CH0_AL1_READ_ADDR + [31:0] + read-write + + + + + CH0_AL1_WRITE_ADDR + 0x00000018 + Alias for channel 0 WRITE_ADDR register + 0x00000000 + + + CH0_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH0_AL1_TRANS_COUNT_TRIG + 0x0000001c + Alias for channel 0 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH0_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH0_AL2_CTRL + 0x00000020 + Alias for channel 0 CTRL register + 0x00000000 + + + CH0_AL2_CTRL + [31:0] + read-write + + + + + CH0_AL2_TRANS_COUNT + 0x00000024 + Alias for channel 0 TRANS_COUNT register + 0x00000000 + + + CH0_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH0_AL2_READ_ADDR + 0x00000028 + Alias for channel 0 READ_ADDR register + 0x00000000 + + + CH0_AL2_READ_ADDR + [31:0] + read-write + + + + + CH0_AL2_WRITE_ADDR_TRIG + 0x0000002c + Alias for channel 0 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH0_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH0_AL3_CTRL + 0x00000030 + Alias for channel 0 CTRL register + 0x00000000 + + + CH0_AL3_CTRL + [31:0] + read-write + + + + + CH0_AL3_WRITE_ADDR + 0x00000034 + Alias for channel 0 WRITE_ADDR register + 0x00000000 + + + CH0_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH0_AL3_TRANS_COUNT + 0x00000038 + Alias for channel 0 TRANS_COUNT register + 0x00000000 + + + CH0_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH0_AL3_READ_ADDR_TRIG + 0x0000003c + Alias for channel 0 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH0_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH1_READ_ADDR + 0x00000040 + DMA Channel 1 Read Address pointer + 0x00000000 + + + CH1_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH1_WRITE_ADDR + 0x00000044 + DMA Channel 1 Write Address pointer + 0x00000000 + + + CH1_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH1_TRANS_COUNT + 0x00000048 + DMA Channel 1 Transfer Count + 0x00000000 + + + CH1_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH1_CTRL_TRIG + 0x0000004c + DMA Channel 1 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH1_AL1_CTRL + 0x00000050 + Alias for channel 1 CTRL register + 0x00000000 + + + CH1_AL1_CTRL + [31:0] + read-write + + + + + CH1_AL1_READ_ADDR + 0x00000054 + Alias for channel 1 READ_ADDR register + 0x00000000 + + + CH1_AL1_READ_ADDR + [31:0] + read-write + + + + + CH1_AL1_WRITE_ADDR + 0x00000058 + Alias for channel 1 WRITE_ADDR register + 0x00000000 + + + CH1_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH1_AL1_TRANS_COUNT_TRIG + 0x0000005c + Alias for channel 1 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH1_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH1_AL2_CTRL + 0x00000060 + Alias for channel 1 CTRL register + 0x00000000 + + + CH1_AL2_CTRL + [31:0] + read-write + + + + + CH1_AL2_TRANS_COUNT + 0x00000064 + Alias for channel 1 TRANS_COUNT register + 0x00000000 + + + CH1_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH1_AL2_READ_ADDR + 0x00000068 + Alias for channel 1 READ_ADDR register + 0x00000000 + + + CH1_AL2_READ_ADDR + [31:0] + read-write + + + + + CH1_AL2_WRITE_ADDR_TRIG + 0x0000006c + Alias for channel 1 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH1_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH1_AL3_CTRL + 0x00000070 + Alias for channel 1 CTRL register + 0x00000000 + + + CH1_AL3_CTRL + [31:0] + read-write + + + + + CH1_AL3_WRITE_ADDR + 0x00000074 + Alias for channel 1 WRITE_ADDR register + 0x00000000 + + + CH1_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH1_AL3_TRANS_COUNT + 0x00000078 + Alias for channel 1 TRANS_COUNT register + 0x00000000 + + + CH1_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH1_AL3_READ_ADDR_TRIG + 0x0000007c + Alias for channel 1 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH1_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH2_READ_ADDR + 0x00000080 + DMA Channel 2 Read Address pointer + 0x00000000 + + + CH2_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH2_WRITE_ADDR + 0x00000084 + DMA Channel 2 Write Address pointer + 0x00000000 + + + CH2_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH2_TRANS_COUNT + 0x00000088 + DMA Channel 2 Transfer Count + 0x00000000 + + + CH2_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH2_CTRL_TRIG + 0x0000008c + DMA Channel 2 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH2_AL1_CTRL + 0x00000090 + Alias for channel 2 CTRL register + 0x00000000 + + + CH2_AL1_CTRL + [31:0] + read-write + + + + + CH2_AL1_READ_ADDR + 0x00000094 + Alias for channel 2 READ_ADDR register + 0x00000000 + + + CH2_AL1_READ_ADDR + [31:0] + read-write + + + + + CH2_AL1_WRITE_ADDR + 0x00000098 + Alias for channel 2 WRITE_ADDR register + 0x00000000 + + + CH2_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH2_AL1_TRANS_COUNT_TRIG + 0x0000009c + Alias for channel 2 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH2_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH2_AL2_CTRL + 0x000000a0 + Alias for channel 2 CTRL register + 0x00000000 + + + CH2_AL2_CTRL + [31:0] + read-write + + + + + CH2_AL2_TRANS_COUNT + 0x000000a4 + Alias for channel 2 TRANS_COUNT register + 0x00000000 + + + CH2_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH2_AL2_READ_ADDR + 0x000000a8 + Alias for channel 2 READ_ADDR register + 0x00000000 + + + CH2_AL2_READ_ADDR + [31:0] + read-write + + + + + CH2_AL2_WRITE_ADDR_TRIG + 0x000000ac + Alias for channel 2 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH2_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH2_AL3_CTRL + 0x000000b0 + Alias for channel 2 CTRL register + 0x00000000 + + + CH2_AL3_CTRL + [31:0] + read-write + + + + + CH2_AL3_WRITE_ADDR + 0x000000b4 + Alias for channel 2 WRITE_ADDR register + 0x00000000 + + + CH2_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH2_AL3_TRANS_COUNT + 0x000000b8 + Alias for channel 2 TRANS_COUNT register + 0x00000000 + + + CH2_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH2_AL3_READ_ADDR_TRIG + 0x000000bc + Alias for channel 2 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH2_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH3_READ_ADDR + 0x000000c0 + DMA Channel 3 Read Address pointer + 0x00000000 + + + CH3_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH3_WRITE_ADDR + 0x000000c4 + DMA Channel 3 Write Address pointer + 0x00000000 + + + CH3_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH3_TRANS_COUNT + 0x000000c8 + DMA Channel 3 Transfer Count + 0x00000000 + + + CH3_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH3_CTRL_TRIG + 0x000000cc + DMA Channel 3 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH3_AL1_CTRL + 0x000000d0 + Alias for channel 3 CTRL register + 0x00000000 + + + CH3_AL1_CTRL + [31:0] + read-write + + + + + CH3_AL1_READ_ADDR + 0x000000d4 + Alias for channel 3 READ_ADDR register + 0x00000000 + + + CH3_AL1_READ_ADDR + [31:0] + read-write + + + + + CH3_AL1_WRITE_ADDR + 0x000000d8 + Alias for channel 3 WRITE_ADDR register + 0x00000000 + + + CH3_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH3_AL1_TRANS_COUNT_TRIG + 0x000000dc + Alias for channel 3 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH3_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH3_AL2_CTRL + 0x000000e0 + Alias for channel 3 CTRL register + 0x00000000 + + + CH3_AL2_CTRL + [31:0] + read-write + + + + + CH3_AL2_TRANS_COUNT + 0x000000e4 + Alias for channel 3 TRANS_COUNT register + 0x00000000 + + + CH3_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH3_AL2_READ_ADDR + 0x000000e8 + Alias for channel 3 READ_ADDR register + 0x00000000 + + + CH3_AL2_READ_ADDR + [31:0] + read-write + + + + + CH3_AL2_WRITE_ADDR_TRIG + 0x000000ec + Alias for channel 3 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH3_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH3_AL3_CTRL + 0x000000f0 + Alias for channel 3 CTRL register + 0x00000000 + + + CH3_AL3_CTRL + [31:0] + read-write + + + + + CH3_AL3_WRITE_ADDR + 0x000000f4 + Alias for channel 3 WRITE_ADDR register + 0x00000000 + + + CH3_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH3_AL3_TRANS_COUNT + 0x000000f8 + Alias for channel 3 TRANS_COUNT register + 0x00000000 + + + CH3_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH3_AL3_READ_ADDR_TRIG + 0x000000fc + Alias for channel 3 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH3_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH4_READ_ADDR + 0x00000100 + DMA Channel 4 Read Address pointer + 0x00000000 + + + CH4_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH4_WRITE_ADDR + 0x00000104 + DMA Channel 4 Write Address pointer + 0x00000000 + + + CH4_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH4_TRANS_COUNT + 0x00000108 + DMA Channel 4 Transfer Count + 0x00000000 + + + CH4_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH4_CTRL_TRIG + 0x0000010c + DMA Channel 4 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH4_AL1_CTRL + 0x00000110 + Alias for channel 4 CTRL register + 0x00000000 + + + CH4_AL1_CTRL + [31:0] + read-write + + + + + CH4_AL1_READ_ADDR + 0x00000114 + Alias for channel 4 READ_ADDR register + 0x00000000 + + + CH4_AL1_READ_ADDR + [31:0] + read-write + + + + + CH4_AL1_WRITE_ADDR + 0x00000118 + Alias for channel 4 WRITE_ADDR register + 0x00000000 + + + CH4_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH4_AL1_TRANS_COUNT_TRIG + 0x0000011c + Alias for channel 4 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH4_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH4_AL2_CTRL + 0x00000120 + Alias for channel 4 CTRL register + 0x00000000 + + + CH4_AL2_CTRL + [31:0] + read-write + + + + + CH4_AL2_TRANS_COUNT + 0x00000124 + Alias for channel 4 TRANS_COUNT register + 0x00000000 + + + CH4_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH4_AL2_READ_ADDR + 0x00000128 + Alias for channel 4 READ_ADDR register + 0x00000000 + + + CH4_AL2_READ_ADDR + [31:0] + read-write + + + + + CH4_AL2_WRITE_ADDR_TRIG + 0x0000012c + Alias for channel 4 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH4_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH4_AL3_CTRL + 0x00000130 + Alias for channel 4 CTRL register + 0x00000000 + + + CH4_AL3_CTRL + [31:0] + read-write + + + + + CH4_AL3_WRITE_ADDR + 0x00000134 + Alias for channel 4 WRITE_ADDR register + 0x00000000 + + + CH4_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH4_AL3_TRANS_COUNT + 0x00000138 + Alias for channel 4 TRANS_COUNT register + 0x00000000 + + + CH4_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH4_AL3_READ_ADDR_TRIG + 0x0000013c + Alias for channel 4 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH4_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH5_READ_ADDR + 0x00000140 + DMA Channel 5 Read Address pointer + 0x00000000 + + + CH5_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH5_WRITE_ADDR + 0x00000144 + DMA Channel 5 Write Address pointer + 0x00000000 + + + CH5_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH5_TRANS_COUNT + 0x00000148 + DMA Channel 5 Transfer Count + 0x00000000 + + + CH5_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH5_CTRL_TRIG + 0x0000014c + DMA Channel 5 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH5_AL1_CTRL + 0x00000150 + Alias for channel 5 CTRL register + 0x00000000 + + + CH5_AL1_CTRL + [31:0] + read-write + + + + + CH5_AL1_READ_ADDR + 0x00000154 + Alias for channel 5 READ_ADDR register + 0x00000000 + + + CH5_AL1_READ_ADDR + [31:0] + read-write + + + + + CH5_AL1_WRITE_ADDR + 0x00000158 + Alias for channel 5 WRITE_ADDR register + 0x00000000 + + + CH5_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH5_AL1_TRANS_COUNT_TRIG + 0x0000015c + Alias for channel 5 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH5_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH5_AL2_CTRL + 0x00000160 + Alias for channel 5 CTRL register + 0x00000000 + + + CH5_AL2_CTRL + [31:0] + read-write + + + + + CH5_AL2_TRANS_COUNT + 0x00000164 + Alias for channel 5 TRANS_COUNT register + 0x00000000 + + + CH5_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH5_AL2_READ_ADDR + 0x00000168 + Alias for channel 5 READ_ADDR register + 0x00000000 + + + CH5_AL2_READ_ADDR + [31:0] + read-write + + + + + CH5_AL2_WRITE_ADDR_TRIG + 0x0000016c + Alias for channel 5 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH5_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH5_AL3_CTRL + 0x00000170 + Alias for channel 5 CTRL register + 0x00000000 + + + CH5_AL3_CTRL + [31:0] + read-write + + + + + CH5_AL3_WRITE_ADDR + 0x00000174 + Alias for channel 5 WRITE_ADDR register + 0x00000000 + + + CH5_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH5_AL3_TRANS_COUNT + 0x00000178 + Alias for channel 5 TRANS_COUNT register + 0x00000000 + + + CH5_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH5_AL3_READ_ADDR_TRIG + 0x0000017c + Alias for channel 5 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH5_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH6_READ_ADDR + 0x00000180 + DMA Channel 6 Read Address pointer + 0x00000000 + + + CH6_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH6_WRITE_ADDR + 0x00000184 + DMA Channel 6 Write Address pointer + 0x00000000 + + + CH6_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH6_TRANS_COUNT + 0x00000188 + DMA Channel 6 Transfer Count + 0x00000000 + + + CH6_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH6_CTRL_TRIG + 0x0000018c + DMA Channel 6 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH6_AL1_CTRL + 0x00000190 + Alias for channel 6 CTRL register + 0x00000000 + + + CH6_AL1_CTRL + [31:0] + read-write + + + + + CH6_AL1_READ_ADDR + 0x00000194 + Alias for channel 6 READ_ADDR register + 0x00000000 + + + CH6_AL1_READ_ADDR + [31:0] + read-write + + + + + CH6_AL1_WRITE_ADDR + 0x00000198 + Alias for channel 6 WRITE_ADDR register + 0x00000000 + + + CH6_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH6_AL1_TRANS_COUNT_TRIG + 0x0000019c + Alias for channel 6 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH6_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH6_AL2_CTRL + 0x000001a0 + Alias for channel 6 CTRL register + 0x00000000 + + + CH6_AL2_CTRL + [31:0] + read-write + + + + + CH6_AL2_TRANS_COUNT + 0x000001a4 + Alias for channel 6 TRANS_COUNT register + 0x00000000 + + + CH6_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH6_AL2_READ_ADDR + 0x000001a8 + Alias for channel 6 READ_ADDR register + 0x00000000 + + + CH6_AL2_READ_ADDR + [31:0] + read-write + + + + + CH6_AL2_WRITE_ADDR_TRIG + 0x000001ac + Alias for channel 6 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH6_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH6_AL3_CTRL + 0x000001b0 + Alias for channel 6 CTRL register + 0x00000000 + + + CH6_AL3_CTRL + [31:0] + read-write + + + + + CH6_AL3_WRITE_ADDR + 0x000001b4 + Alias for channel 6 WRITE_ADDR register + 0x00000000 + + + CH6_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH6_AL3_TRANS_COUNT + 0x000001b8 + Alias for channel 6 TRANS_COUNT register + 0x00000000 + + + CH6_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH6_AL3_READ_ADDR_TRIG + 0x000001bc + Alias for channel 6 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH6_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH7_READ_ADDR + 0x000001c0 + DMA Channel 7 Read Address pointer + 0x00000000 + + + CH7_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH7_WRITE_ADDR + 0x000001c4 + DMA Channel 7 Write Address pointer + 0x00000000 + + + CH7_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH7_TRANS_COUNT + 0x000001c8 + DMA Channel 7 Transfer Count + 0x00000000 + + + CH7_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH7_CTRL_TRIG + 0x000001cc + DMA Channel 7 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH7_AL1_CTRL + 0x000001d0 + Alias for channel 7 CTRL register + 0x00000000 + + + CH7_AL1_CTRL + [31:0] + read-write + + + + + CH7_AL1_READ_ADDR + 0x000001d4 + Alias for channel 7 READ_ADDR register + 0x00000000 + + + CH7_AL1_READ_ADDR + [31:0] + read-write + + + + + CH7_AL1_WRITE_ADDR + 0x000001d8 + Alias for channel 7 WRITE_ADDR register + 0x00000000 + + + CH7_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH7_AL1_TRANS_COUNT_TRIG + 0x000001dc + Alias for channel 7 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH7_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH7_AL2_CTRL + 0x000001e0 + Alias for channel 7 CTRL register + 0x00000000 + + + CH7_AL2_CTRL + [31:0] + read-write + + + + + CH7_AL2_TRANS_COUNT + 0x000001e4 + Alias for channel 7 TRANS_COUNT register + 0x00000000 + + + CH7_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH7_AL2_READ_ADDR + 0x000001e8 + Alias for channel 7 READ_ADDR register + 0x00000000 + + + CH7_AL2_READ_ADDR + [31:0] + read-write + + + + + CH7_AL2_WRITE_ADDR_TRIG + 0x000001ec + Alias for channel 7 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH7_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH7_AL3_CTRL + 0x000001f0 + Alias for channel 7 CTRL register + 0x00000000 + + + CH7_AL3_CTRL + [31:0] + read-write + + + + + CH7_AL3_WRITE_ADDR + 0x000001f4 + Alias for channel 7 WRITE_ADDR register + 0x00000000 + + + CH7_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH7_AL3_TRANS_COUNT + 0x000001f8 + Alias for channel 7 TRANS_COUNT register + 0x00000000 + + + CH7_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH7_AL3_READ_ADDR_TRIG + 0x000001fc + Alias for channel 7 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH7_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH8_READ_ADDR + 0x00000200 + DMA Channel 8 Read Address pointer + 0x00000000 + + + CH8_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH8_WRITE_ADDR + 0x00000204 + DMA Channel 8 Write Address pointer + 0x00000000 + + + CH8_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH8_TRANS_COUNT + 0x00000208 + DMA Channel 8 Transfer Count + 0x00000000 + + + CH8_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH8_CTRL_TRIG + 0x0000020c + DMA Channel 8 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH8_AL1_CTRL + 0x00000210 + Alias for channel 8 CTRL register + 0x00000000 + + + CH8_AL1_CTRL + [31:0] + read-write + + + + + CH8_AL1_READ_ADDR + 0x00000214 + Alias for channel 8 READ_ADDR register + 0x00000000 + + + CH8_AL1_READ_ADDR + [31:0] + read-write + + + + + CH8_AL1_WRITE_ADDR + 0x00000218 + Alias for channel 8 WRITE_ADDR register + 0x00000000 + + + CH8_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH8_AL1_TRANS_COUNT_TRIG + 0x0000021c + Alias for channel 8 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH8_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH8_AL2_CTRL + 0x00000220 + Alias for channel 8 CTRL register + 0x00000000 + + + CH8_AL2_CTRL + [31:0] + read-write + + + + + CH8_AL2_TRANS_COUNT + 0x00000224 + Alias for channel 8 TRANS_COUNT register + 0x00000000 + + + CH8_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH8_AL2_READ_ADDR + 0x00000228 + Alias for channel 8 READ_ADDR register + 0x00000000 + + + CH8_AL2_READ_ADDR + [31:0] + read-write + + + + + CH8_AL2_WRITE_ADDR_TRIG + 0x0000022c + Alias for channel 8 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH8_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH8_AL3_CTRL + 0x00000230 + Alias for channel 8 CTRL register + 0x00000000 + + + CH8_AL3_CTRL + [31:0] + read-write + + + + + CH8_AL3_WRITE_ADDR + 0x00000234 + Alias for channel 8 WRITE_ADDR register + 0x00000000 + + + CH8_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH8_AL3_TRANS_COUNT + 0x00000238 + Alias for channel 8 TRANS_COUNT register + 0x00000000 + + + CH8_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH8_AL3_READ_ADDR_TRIG + 0x0000023c + Alias for channel 8 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH8_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH9_READ_ADDR + 0x00000240 + DMA Channel 9 Read Address pointer + 0x00000000 + + + CH9_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH9_WRITE_ADDR + 0x00000244 + DMA Channel 9 Write Address pointer + 0x00000000 + + + CH9_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH9_TRANS_COUNT + 0x00000248 + DMA Channel 9 Transfer Count + 0x00000000 + + + CH9_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH9_CTRL_TRIG + 0x0000024c + DMA Channel 9 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH9_AL1_CTRL + 0x00000250 + Alias for channel 9 CTRL register + 0x00000000 + + + CH9_AL1_CTRL + [31:0] + read-write + + + + + CH9_AL1_READ_ADDR + 0x00000254 + Alias for channel 9 READ_ADDR register + 0x00000000 + + + CH9_AL1_READ_ADDR + [31:0] + read-write + + + + + CH9_AL1_WRITE_ADDR + 0x00000258 + Alias for channel 9 WRITE_ADDR register + 0x00000000 + + + CH9_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH9_AL1_TRANS_COUNT_TRIG + 0x0000025c + Alias for channel 9 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH9_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH9_AL2_CTRL + 0x00000260 + Alias for channel 9 CTRL register + 0x00000000 + + + CH9_AL2_CTRL + [31:0] + read-write + + + + + CH9_AL2_TRANS_COUNT + 0x00000264 + Alias for channel 9 TRANS_COUNT register + 0x00000000 + + + CH9_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH9_AL2_READ_ADDR + 0x00000268 + Alias for channel 9 READ_ADDR register + 0x00000000 + + + CH9_AL2_READ_ADDR + [31:0] + read-write + + + + + CH9_AL2_WRITE_ADDR_TRIG + 0x0000026c + Alias for channel 9 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH9_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH9_AL3_CTRL + 0x00000270 + Alias for channel 9 CTRL register + 0x00000000 + + + CH9_AL3_CTRL + [31:0] + read-write + + + + + CH9_AL3_WRITE_ADDR + 0x00000274 + Alias for channel 9 WRITE_ADDR register + 0x00000000 + + + CH9_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH9_AL3_TRANS_COUNT + 0x00000278 + Alias for channel 9 TRANS_COUNT register + 0x00000000 + + + CH9_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH9_AL3_READ_ADDR_TRIG + 0x0000027c + Alias for channel 9 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH9_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH10_READ_ADDR + 0x00000280 + DMA Channel 10 Read Address pointer + 0x00000000 + + + CH10_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH10_WRITE_ADDR + 0x00000284 + DMA Channel 10 Write Address pointer + 0x00000000 + + + CH10_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH10_TRANS_COUNT + 0x00000288 + DMA Channel 10 Transfer Count + 0x00000000 + + + CH10_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH10_CTRL_TRIG + 0x0000028c + DMA Channel 10 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH10_AL1_CTRL + 0x00000290 + Alias for channel 10 CTRL register + 0x00000000 + + + CH10_AL1_CTRL + [31:0] + read-write + + + + + CH10_AL1_READ_ADDR + 0x00000294 + Alias for channel 10 READ_ADDR register + 0x00000000 + + + CH10_AL1_READ_ADDR + [31:0] + read-write + + + + + CH10_AL1_WRITE_ADDR + 0x00000298 + Alias for channel 10 WRITE_ADDR register + 0x00000000 + + + CH10_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH10_AL1_TRANS_COUNT_TRIG + 0x0000029c + Alias for channel 10 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH10_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH10_AL2_CTRL + 0x000002a0 + Alias for channel 10 CTRL register + 0x00000000 + + + CH10_AL2_CTRL + [31:0] + read-write + + + + + CH10_AL2_TRANS_COUNT + 0x000002a4 + Alias for channel 10 TRANS_COUNT register + 0x00000000 + + + CH10_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH10_AL2_READ_ADDR + 0x000002a8 + Alias for channel 10 READ_ADDR register + 0x00000000 + + + CH10_AL2_READ_ADDR + [31:0] + read-write + + + + + CH10_AL2_WRITE_ADDR_TRIG + 0x000002ac + Alias for channel 10 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH10_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH10_AL3_CTRL + 0x000002b0 + Alias for channel 10 CTRL register + 0x00000000 + + + CH10_AL3_CTRL + [31:0] + read-write + + + + + CH10_AL3_WRITE_ADDR + 0x000002b4 + Alias for channel 10 WRITE_ADDR register + 0x00000000 + + + CH10_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH10_AL3_TRANS_COUNT + 0x000002b8 + Alias for channel 10 TRANS_COUNT register + 0x00000000 + + + CH10_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH10_AL3_READ_ADDR_TRIG + 0x000002bc + Alias for channel 10 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH10_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + CH11_READ_ADDR + 0x000002c0 + DMA Channel 11 Read Address pointer + 0x00000000 + + + CH11_READ_ADDR + This register updates automatically each time a read completes. The current value is the next address to be read by this channel. + [31:0] + read-write + + + + + CH11_WRITE_ADDR + 0x000002c4 + DMA Channel 11 Write Address pointer + 0x00000000 + + + CH11_WRITE_ADDR + This register updates automatically each time a write completes. The current value is the next address to be written by this channel. + [31:0] + read-write + + + + + CH11_TRANS_COUNT + 0x000002c8 + DMA Channel 11 Transfer Count + 0x00000000 + + + CH11_TRANS_COUNT + Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). + + When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. + + Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. + + The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. + [31:0] + read-write + + + + + CH11_CTRL_TRIG + 0x000002cc + DMA Channel 11 Control and Status + 0x00000000 + + + AHB_ERROR + Logical OR of the READ_ERROR and WRITE_ERROR flags. The channel halts when it encounters any bus error, and always raises its channel IRQ flag. + [31:31] + read-only + + + READ_ERROR + If 1, the channel received a read bus error. Write one to clear. + READ_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 3 transfers later) + [30:30] + read-write + oneToClear + + + WRITE_ERROR + If 1, the channel received a write bus error. Write one to clear. + WRITE_ADDR shows the approximate address where the bus error was encountered (will not be earlier, or more than 5 transfers later) + [29:29] + read-write + oneToClear + + + BUSY + This flag goes high when the channel starts a new transfer sequence, and low when the last transfer of that sequence completes. Clearing EN while BUSY is high pauses the channel, and BUSY will stay high while paused. + + To terminate a sequence early (and clear the BUSY flag), see CHAN_ABORT. + [24:24] + read-only + + + SNIFF_EN + If 1, this channel's data transfers are visible to the sniff hardware, and each transfer will advance the state of the checksum. This only applies if the sniff hardware is enabled, and has this channel selected. + + This allows checksum to be enabled or disabled on a per-control- block basis. + [23:23] + read-write + + + BSWAP + Apply byte-swap transformation to DMA data. + For byte data, this has no effect. For halfword data, the two bytes of each halfword are swapped. For word data, the four bytes of each word are swapped to reverse order. + [22:22] + read-write + + + IRQ_QUIET + In QUIET mode, the channel does not generate IRQs at the end of every transfer block. Instead, an IRQ is raised when NULL is written to a trigger register, indicating the end of a control block chain. + + This reduces the number of interrupts to be serviced by the CPU when transferring a DMA chain of many small control blocks. + [21:21] + read-write + + + TREQ_SEL + Select a Transfer Request signal. + The channel uses the transfer request signal to pace its data transfer rate. Sources for TREQ signals are internal (TIMERS) or external (DREQ, a Data Request from the system). + 0x0 to 0x3a -> select DREQ n as TREQ + [20:15] + read-write + + + PIO0_TX0 + 0 + Select PIO0's TX FIFO 0 as TREQ + + + PIO0_TX1 + 1 + Select PIO0's TX FIFO 1 as TREQ + + + PIO0_TX2 + 2 + Select PIO0's TX FIFO 2 as TREQ + + + PIO0_TX3 + 3 + Select PIO0's TX FIFO 3 as TREQ + + + PIO0_RX0 + 4 + Select PIO0's RX FIFO 0 as TREQ + + + PIO0_RX1 + 5 + Select PIO0's RX FIFO 1 as TREQ + + + PIO0_RX2 + 6 + Select PIO0's RX FIFO 2 as TREQ + + + PIO0_RX3 + 7 + Select PIO0's RX FIFO 3 as TREQ + + + PIO1_TX0 + 8 + Select PIO1's TX FIFO 0 as TREQ + + + PIO1_TX1 + 9 + Select PIO1's TX FIFO 1 as TREQ + + + PIO1_TX2 + 10 + Select PIO1's TX FIFO 2 as TREQ + + + PIO1_TX3 + 11 + Select PIO1's TX FIFO 3 as TREQ + + + PIO1_RX0 + 12 + Select PIO1's RX FIFO 0 as TREQ + + + PIO1_RX1 + 13 + Select PIO1's RX FIFO 1 as TREQ + + + PIO1_RX2 + 14 + Select PIO1's RX FIFO 2 as TREQ + + + PIO1_RX3 + 15 + Select PIO1's RX FIFO 3 as TREQ + + + SPI0_TX + 16 + Select SPI0's TX FIFO as TREQ + + + SPI0_RX + 17 + Select SPI0's RX FIFO as TREQ + + + SPI1_TX + 18 + Select SPI1's TX FIFO as TREQ + + + SPI1_RX + 19 + Select SPI1's RX FIFO as TREQ + + + UART0_TX + 20 + Select UART0's TX FIFO as TREQ + + + UART0_RX + 21 + Select UART0's RX FIFO as TREQ + + + UART1_TX + 22 + Select UART1's TX FIFO as TREQ + + + UART1_RX + 23 + Select UART1's RX FIFO as TREQ + + + PWM_WRAP0 + 24 + Select PWM Counter 0's Wrap Value as TREQ + + + PWM_WRAP1 + 25 + Select PWM Counter 1's Wrap Value as TREQ + + + PWM_WRAP2 + 26 + Select PWM Counter 2's Wrap Value as TREQ + + + PWM_WRAP3 + 27 + Select PWM Counter 3's Wrap Value as TREQ + + + PWM_WRAP4 + 28 + Select PWM Counter 4's Wrap Value as TREQ + + + PWM_WRAP5 + 29 + Select PWM Counter 5's Wrap Value as TREQ + + + PWM_WRAP6 + 30 + Select PWM Counter 6's Wrap Value as TREQ + + + PWM_WRAP7 + 31 + Select PWM Counter 7's Wrap Value as TREQ + + + I2C0_TX + 32 + Select I2C0's TX FIFO as TREQ + + + I2C0_RX + 33 + Select I2C0's RX FIFO as TREQ + + + I2C1_TX + 34 + Select I2C1's TX FIFO as TREQ + + + I2C1_RX + 35 + Select I2C1's RX FIFO as TREQ + + + ADC + 36 + Select the ADC as TREQ + + + XIP_STREAM + 37 + Select the XIP Streaming FIFO as TREQ + + + XIP_SSITX + 38 + Select the XIP SSI TX FIFO as TREQ + + + XIP_SSIRX + 39 + Select the XIP SSI RX FIFO as TREQ + + + TIMER0 + 59 + Select Timer 0 as TREQ + + + TIMER1 + 60 + Select Timer 1 as TREQ + + + TIMER2 + 61 + Select Timer 2 as TREQ (Optional) + + + TIMER3 + 62 + Select Timer 3 as TREQ (Optional) + + + PERMANENT + 63 + Permanent request, for unpaced transfers. + + + + + CHAIN_TO + When this channel completes, it will trigger the channel indicated by CHAIN_TO. Disable by setting CHAIN_TO = _(this channel)_. + [14:11] + read-write + + + RING_SEL + Select whether RING_SIZE applies to read or write addresses. + If 0, read addresses are wrapped on a (1 << RING_SIZE) boundary. If 1, write addresses are wrapped. + [10:10] + read-write + + + RING_SIZE + Size of address wrap region. If 0, don't wrap. For values n > 0, only the lower n bits of the address will change. This wraps the address on a (1 << n) byte boundary, facilitating access to naturally-aligned ring buffers. + + Ring sizes between 2 and 32768 bytes are possible. This can apply to either read or write addresses, based on value of RING_SEL. + [9:6] + read-write + + + RING_NONE + 0 + + + + + INCR_WRITE + If 1, the write address increments with each transfer. If 0, each write is directed to the same, initial address. + + Generally this should be disabled for memory-to-peripheral transfers. + [5:5] + read-write + + + INCR_READ + If 1, the read address increments with each transfer. If 0, each read is directed to the same, initial address. + + Generally this should be disabled for peripheral-to-memory transfers. + [4:4] + read-write + + + DATA_SIZE + Set the size of each bus transfer (byte/halfword/word). READ_ADDR and WRITE_ADDR advance by this amount (1/2/4 bytes) with each transfer. + [3:2] + read-write + + + SIZE_BYTE + 0 + + + SIZE_HALFWORD + 1 + + + SIZE_WORD + 2 + + + + + HIGH_PRIORITY + HIGH_PRIORITY gives a channel preferential treatment in issue scheduling: in each scheduling round, all high priority channels are considered first, and then only a single low priority channel, before returning to the high priority channels. + + This only affects the order in which the DMA schedules channels. The DMA's bus priority is not changed. If the DMA is not saturated then a low priority channel will see no loss of throughput. + [1:1] + read-write + + + EN + DMA Channel Enable. + When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) + [0:0] + read-write + + + + + CH11_AL1_CTRL + 0x000002d0 + Alias for channel 11 CTRL register + 0x00000000 + + + CH11_AL1_CTRL + [31:0] + read-write + + + + + CH11_AL1_READ_ADDR + 0x000002d4 + Alias for channel 11 READ_ADDR register + 0x00000000 + + + CH11_AL1_READ_ADDR + [31:0] + read-write + + + + + CH11_AL1_WRITE_ADDR + 0x000002d8 + Alias for channel 11 WRITE_ADDR register + 0x00000000 + + + CH11_AL1_WRITE_ADDR + [31:0] + read-write + + + + + CH11_AL1_TRANS_COUNT_TRIG + 0x000002dc + Alias for channel 11 TRANS_COUNT register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH11_AL1_TRANS_COUNT_TRIG + [31:0] + read-write + + + + + CH11_AL2_CTRL + 0x000002e0 + Alias for channel 11 CTRL register + 0x00000000 + + + CH11_AL2_CTRL + [31:0] + read-write + + + + + CH11_AL2_TRANS_COUNT + 0x000002e4 + Alias for channel 11 TRANS_COUNT register + 0x00000000 + + + CH11_AL2_TRANS_COUNT + [31:0] + read-write + + + + + CH11_AL2_READ_ADDR + 0x000002e8 + Alias for channel 11 READ_ADDR register + 0x00000000 + + + CH11_AL2_READ_ADDR + [31:0] + read-write + + + + + CH11_AL2_WRITE_ADDR_TRIG + 0x000002ec + Alias for channel 11 WRITE_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH11_AL2_WRITE_ADDR_TRIG + [31:0] + read-write + + + + + CH11_AL3_CTRL + 0x000002f0 + Alias for channel 11 CTRL register + 0x00000000 + + + CH11_AL3_CTRL + [31:0] + read-write + + + + + CH11_AL3_WRITE_ADDR + 0x000002f4 + Alias for channel 11 WRITE_ADDR register + 0x00000000 + + + CH11_AL3_WRITE_ADDR + [31:0] + read-write + + + + + CH11_AL3_TRANS_COUNT + 0x000002f8 + Alias for channel 11 TRANS_COUNT register + 0x00000000 + + + CH11_AL3_TRANS_COUNT + [31:0] + read-write + + + + + CH11_AL3_READ_ADDR_TRIG + 0x000002fc + Alias for channel 11 READ_ADDR register + This is a trigger register (0xc). Writing a nonzero value will + reload the channel counter and start the channel. + 0x00000000 + + + CH11_AL3_READ_ADDR_TRIG + [31:0] + read-write + + + + + INTR + 0x00000400 + Interrupt Status (raw) + 0x00000000 + + + INTR + Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. + + Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. + + This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. + + It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + [15:0] + read-write + oneToClear + + + + + INTE0 + 0x00000404 + Interrupt Enables for IRQ 0 + 0x00000000 + + + INTE0 + Set bit n to pass interrupts from channel n to DMA IRQ 0. + [15:0] + read-write + + + + + INTF0 + 0x00000408 + Force Interrupts + 0x00000000 + + + INTF0 + Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + [15:0] + read-write + + + + + INTS0 + 0x0000040c + Interrupt Status for IRQ 0 + 0x00000000 + + + INTS0 + Indicates active channel interrupt requests which are currently causing IRQ 0 to be asserted. + Channel interrupts can be cleared by writing a bit mask here. + [15:0] + read-write + oneToClear + + + + + INTR1 + 0x00000410 + Interrupt Status (raw) + 0x00000000 + + + INTR1 + Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. + + Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. + + This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. + + It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + [15:0] + read-write + oneToClear + + + + + INTE1 + 0x00000414 + Interrupt Enables for IRQ 1 + 0x00000000 + + + INTE1 + Set bit n to pass interrupts from channel n to DMA IRQ 1. + [15:0] + read-write + + + + + INTF1 + 0x00000418 + Force Interrupts for IRQ 1 + 0x00000000 + + + INTF1 + Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + [15:0] + read-write + + + + + INTS1 + 0x0000041c + Interrupt Status (masked) for IRQ 1 + 0x00000000 + + + INTS1 + Indicates active channel interrupt requests which are currently causing IRQ 1 to be asserted. + Channel interrupts can be cleared by writing a bit mask here. + [15:0] + read-write + oneToClear + + + + + TIMER0 + 0x00000420 + Pacing (X/Y) Fractional Timer + The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + 0x00000000 + + + X + Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + [31:16] + read-write + + + Y + Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + [15:0] + read-write + + + + + TIMER1 + 0x00000424 + Pacing (X/Y) Fractional Timer + The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + 0x00000000 + + + X + Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + [31:16] + read-write + + + Y + Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + [15:0] + read-write + + + + + TIMER2 + 0x00000428 + Pacing (X/Y) Fractional Timer + The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + 0x00000000 + + + X + Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + [31:16] + read-write + + + Y + Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + [15:0] + read-write + + + + + TIMER3 + 0x0000042c + Pacing (X/Y) Fractional Timer + The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. + 0x00000000 + + + X + Pacing Timer Dividend. Specifies the X value for the (X/Y) fractional timer. + [31:16] + read-write + + + Y + Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. + [15:0] + read-write + + + + + MULTI_CHAN_TRIGGER + 0x00000430 + Trigger one or more channels simultaneously + 0x00000000 + + + MULTI_CHAN_TRIGGER + Each bit in this register corresponds to a DMA channel. Writing a 1 to the relevant bit is the same as writing to that channel's trigger register; the channel will start if it is currently enabled and not already busy. + [15:0] + write-only + + + + + SNIFF_CTRL + 0x00000434 + Sniffer Control + 0x00000000 + + + OUT_INV + If set, the result appears inverted (bitwise complement) when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + [11:11] + read-write + + + OUT_REV + If set, the result appears bit-reversed when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + [10:10] + read-write + + + BSWAP + Locally perform a byte reverse on the sniffed data, before feeding into checksum. + + Note that the sniff hardware is downstream of the DMA channel byteswap performed in the read master: if channel CTRL_BSWAP and SNIFF_CTRL_BSWAP are both enabled, their effects cancel from the sniffer's point of view. + [9:9] + read-write + + + CALC + [8:5] + read-write + + + CRC32 + 0 + Calculate a CRC-32 (IEEE802.3 polynomial) + + + CRC32R + 1 + Calculate a CRC-32 (IEEE802.3 polynomial) with bit reversed data + + + CRC16 + 2 + Calculate a CRC-16-CCITT + + + CRC16R + 3 + Calculate a CRC-16-CCITT with bit reversed data + + + EVEN + 14 + XOR reduction over all data. == 1 if the total 1 population count is odd. + + + SUM + 15 + Calculate a simple 32-bit checksum (addition with a 32 bit accumulator) + + + + + DMACH + DMA channel for Sniffer to observe + [4:1] + read-write + + + EN + Enable sniffer + [0:0] + read-write + + + + + SNIFF_DATA + 0x00000438 + Data accumulator for sniff hardware + 0x00000000 + + + SNIFF_DATA + Write an initial seed value here before starting a DMA transfer on the channel indicated by SNIFF_CTRL_DMACH. The hardware will update this register each time it observes a read from the indicated channel. Once the channel completes, the final result can be read from this register. + [31:0] + read-write + + + + + FIFO_LEVELS + 0x00000440 + Debug RAF, WAF, TDF levels + 0x00000000 + + + RAF_LVL + Current Read-Address-FIFO fill level + [23:16] + read-only + + + WAF_LVL + Current Write-Address-FIFO fill level + [15:8] + read-only + + + TDF_LVL + Current Transfer-Data-FIFO fill level + [7:0] + read-only + + + + + CHAN_ABORT + 0x00000444 + Abort an in-progress transfer sequence on one or more channels + 0x00000000 + + + CHAN_ABORT + Each bit corresponds to a channel. Writing a 1 aborts whatever transfer sequence is in progress on that channel. The bit will remain high until any in-flight transfers have been flushed through the address and data FIFOs. + + After writing, this register must be polled until it returns all-zero. Until this point, it is unsafe to restart the channel. + [15:0] + read-write + oneToClear + + + + + N_CHANNELS + 0x00000448 + The number of channels this DMA instance is equipped with. This DMA supports up to 16 hardware channels, but can be configured with as few as one, to minimise silicon area. + 0x00000000 + + + N_CHANNELS + [4:0] + read-only + + + + + CH0_DBG_CTDREQ + 0x00000800 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH0_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH0_DBG_TCR + 0x00000804 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH0_DBG_TCR + [31:0] + read-only + + + + + CH1_DBG_CTDREQ + 0x00000840 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH1_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH1_DBG_TCR + 0x00000844 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH1_DBG_TCR + [31:0] + read-only + + + + + CH2_DBG_CTDREQ + 0x00000880 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH2_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH2_DBG_TCR + 0x00000884 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH2_DBG_TCR + [31:0] + read-only + + + + + CH3_DBG_CTDREQ + 0x000008c0 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH3_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH3_DBG_TCR + 0x000008c4 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH3_DBG_TCR + [31:0] + read-only + + + + + CH4_DBG_CTDREQ + 0x00000900 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH4_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH4_DBG_TCR + 0x00000904 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH4_DBG_TCR + [31:0] + read-only + + + + + CH5_DBG_CTDREQ + 0x00000940 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH5_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH5_DBG_TCR + 0x00000944 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH5_DBG_TCR + [31:0] + read-only + + + + + CH6_DBG_CTDREQ + 0x00000980 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH6_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH6_DBG_TCR + 0x00000984 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH6_DBG_TCR + [31:0] + read-only + + + + + CH7_DBG_CTDREQ + 0x000009c0 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH7_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH7_DBG_TCR + 0x000009c4 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH7_DBG_TCR + [31:0] + read-only + + + + + CH8_DBG_CTDREQ + 0x00000a00 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH8_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH8_DBG_TCR + 0x00000a04 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH8_DBG_TCR + [31:0] + read-only + + + + + CH9_DBG_CTDREQ + 0x00000a40 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH9_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH9_DBG_TCR + 0x00000a44 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH9_DBG_TCR + [31:0] + read-only + + + + + CH10_DBG_CTDREQ + 0x00000a80 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH10_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH10_DBG_TCR + 0x00000a84 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH10_DBG_TCR + [31:0] + read-only + + + + + CH11_DBG_CTDREQ + 0x00000ac0 + Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. + 0x00000000 + + + CH11_DBG_CTDREQ + [5:0] + read-write + oneToClear + + + + + CH11_DBG_TCR + 0x00000ac4 + Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer + 0x00000000 + + + CH11_DBG_TCR + [31:0] + read-only + + + + + + + TIMER + Controls time and alarms + time is a 64 bit value indicating the time in usec since power-on + timeh is the top 32 bits of time & timel is the bottom 32 bits + to change time write to timelw before timehw + to read time read from timelr before timehr + An alarm is set by setting alarm_enable and writing to the corresponding alarm register + When an alarm is pending, the corresponding alarm_running signal will be high + An alarm can be cancelled before it has finished by clearing the alarm_enable + When an alarm fires, the corresponding alarm_irq is set and alarm_running is cleared + To clear the interrupt write a 1 to the corresponding alarm_irq + 0x40054000 + + 0 + 68 + registers + + + TIMER_IRQ_0 + 0 + + + TIMER_IRQ_1 + 1 + + + TIMER_IRQ_2 + 2 + + + TIMER_IRQ_3 + 3 + + + + TIMEHW + 0x00000000 + Write to bits 63:32 of time + always write timelw before timehw + 0x00000000 + + + TIMEHW + [31:0] + write-only + + + + + TIMELW + 0x00000004 + Write to bits 31:0 of time + writes do not get copied to time until timehw is written + 0x00000000 + + + TIMELW + [31:0] + write-only + + + + + TIMEHR + 0x00000008 + Read from bits 63:32 of time + always read timelr before timehr + 0x00000000 + + + TIMEHR + [31:0] + read-only + + + + + TIMELR + 0x0000000c + Read from bits 31:0 of time + 0x00000000 + + + TIMELR + [31:0] + read-only + modify + + + + + ALARM0 + 0x00000010 + Arm alarm 0, and configure the time it will fire. + Once armed, the alarm fires when TIMER_ALARM0 == TIMELR. + The alarm will disarm itself once it fires, and can + be disarmed early using the ARMED status register. + 0x00000000 + + + ALARM0 + [31:0] + read-write + + + + + ALARM1 + 0x00000014 + Arm alarm 1, and configure the time it will fire. + Once armed, the alarm fires when TIMER_ALARM1 == TIMELR. + The alarm will disarm itself once it fires, and can + be disarmed early using the ARMED status register. + 0x00000000 + + + ALARM1 + [31:0] + read-write + + + + + ALARM2 + 0x00000018 + Arm alarm 2, and configure the time it will fire. + Once armed, the alarm fires when TIMER_ALARM2 == TIMELR. + The alarm will disarm itself once it fires, and can + be disarmed early using the ARMED status register. + 0x00000000 + + + ALARM2 + [31:0] + read-write + + + + + ALARM3 + 0x0000001c + Arm alarm 3, and configure the time it will fire. + Once armed, the alarm fires when TIMER_ALARM3 == TIMELR. + The alarm will disarm itself once it fires, and can + be disarmed early using the ARMED status register. + 0x00000000 + + + ALARM3 + [31:0] + read-write + + + + + ARMED + 0x00000020 + Indicates the armed/disarmed status of each alarm. + A write to the corresponding ALARMx register arms the alarm. + Alarms automatically disarm upon firing, but writing ones here + will disarm immediately without waiting to fire. + 0x00000000 + + + ARMED + [3:0] + read-write + oneToClear + + + + + TIMERAWH + 0x00000024 + Raw read from bits 63:32 of time (no side effects) + 0x00000000 + + + TIMERAWH + [31:0] + read-only + + + + + TIMERAWL + 0x00000028 + Raw read from bits 31:0 of time (no side effects) + 0x00000000 + + + TIMERAWL + [31:0] + read-only + + + + + DBGPAUSE + 0x0000002c + Set bits high to enable pause when the corresponding debug ports are active + 0x00000007 + + + DBG1 + Pause when processor 1 is in debug mode + [2:2] + read-write + + + DBG0 + Pause when processor 0 is in debug mode + [1:1] + read-write + + + + + PAUSE + 0x00000030 + Set high to pause the timer + 0x00000000 + + + PAUSE + [0:0] + read-write + + + + + INTR + 0x00000034 + Raw Interrupts + 0x00000000 + + + ALARM_3 + [3:3] + read-write + oneToClear + + + ALARM_2 + [2:2] + read-write + oneToClear + + + ALARM_1 + [1:1] + read-write + oneToClear + + + ALARM_0 + [0:0] + read-write + oneToClear + + + + + INTE + 0x00000038 + Interrupt Enable + 0x00000000 + + + ALARM_3 + [3:3] + read-write + + + ALARM_2 + [2:2] + read-write + + + ALARM_1 + [1:1] + read-write + + + ALARM_0 + [0:0] + read-write + + + + + INTF + 0x0000003c + Interrupt Force + 0x00000000 + + + ALARM_3 + [3:3] + read-write + + + ALARM_2 + [2:2] + read-write + + + ALARM_1 + [1:1] + read-write + + + ALARM_0 + [0:0] + read-write + + + + + INTS + 0x00000040 + Interrupt status after masking & forcing + 0x00000000 + + + ALARM_3 + [3:3] + read-only + + + ALARM_2 + [2:2] + read-only + + + ALARM_1 + [1:1] + read-only + + + ALARM_0 + [0:0] + read-only + + + + + + + PWM + Simple PWM + 0x40050000 + + 0 + 180 + registers + + + PWM_IRQ_WRAP + 4 + + + + CH0_CSR + 0x00000000 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH0_DIV + 0x00000004 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH0_CTR + 0x00000008 + Direct access to the PWM counter + 0x00000000 + + + CH0_CTR + [15:0] + read-write + + + + + CH0_CC + 0x0000000c + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH0_TOP + 0x00000010 + Counter wrap value + 0x0000ffff + + + CH0_TOP + [15:0] + read-write + + + + + CH1_CSR + 0x00000014 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH1_DIV + 0x00000018 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH1_CTR + 0x0000001c + Direct access to the PWM counter + 0x00000000 + + + CH1_CTR + [15:0] + read-write + + + + + CH1_CC + 0x00000020 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH1_TOP + 0x00000024 + Counter wrap value + 0x0000ffff + + + CH1_TOP + [15:0] + read-write + + + + + CH2_CSR + 0x00000028 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH2_DIV + 0x0000002c + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH2_CTR + 0x00000030 + Direct access to the PWM counter + 0x00000000 + + + CH2_CTR + [15:0] + read-write + + + + + CH2_CC + 0x00000034 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH2_TOP + 0x00000038 + Counter wrap value + 0x0000ffff + + + CH2_TOP + [15:0] + read-write + + + + + CH3_CSR + 0x0000003c + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH3_DIV + 0x00000040 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH3_CTR + 0x00000044 + Direct access to the PWM counter + 0x00000000 + + + CH3_CTR + [15:0] + read-write + + + + + CH3_CC + 0x00000048 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH3_TOP + 0x0000004c + Counter wrap value + 0x0000ffff + + + CH3_TOP + [15:0] + read-write + + + + + CH4_CSR + 0x00000050 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH4_DIV + 0x00000054 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH4_CTR + 0x00000058 + Direct access to the PWM counter + 0x00000000 + + + CH4_CTR + [15:0] + read-write + + + + + CH4_CC + 0x0000005c + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH4_TOP + 0x00000060 + Counter wrap value + 0x0000ffff + + + CH4_TOP + [15:0] + read-write + + + + + CH5_CSR + 0x00000064 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH5_DIV + 0x00000068 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH5_CTR + 0x0000006c + Direct access to the PWM counter + 0x00000000 + + + CH5_CTR + [15:0] + read-write + + + + + CH5_CC + 0x00000070 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH5_TOP + 0x00000074 + Counter wrap value + 0x0000ffff + + + CH5_TOP + [15:0] + read-write + + + + + CH6_CSR + 0x00000078 + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH6_DIV + 0x0000007c + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH6_CTR + 0x00000080 + Direct access to the PWM counter + 0x00000000 + + + CH6_CTR + [15:0] + read-write + + + + + CH6_CC + 0x00000084 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH6_TOP + 0x00000088 + Counter wrap value + 0x0000ffff + + + CH6_TOP + [15:0] + read-write + + + + + CH7_CSR + 0x0000008c + Control and status register + 0x00000000 + + + PH_ADV + Advance the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running + at less than full speed (div_int + div_frac / 16 > 1) + [7:7] + write-only + + + PH_RET + Retard the phase of the counter by 1 count, while it is running. + Self-clearing. Write a 1, and poll until low. Counter must be running. + [6:6] + write-only + + + DIVMODE + [5:4] + read-write + + + div + 0 + Free-running counting at rate dictated by fractional divider + + + level + 1 + Fractional divider operation is gated by the PWM B pin. + + + rise + 2 + Counter advances with each rising edge of the PWM B pin. + + + fall + 3 + Counter advances with each falling edge of the PWM B pin. + + + + + B_INV + Invert output B + [3:3] + read-write + + + A_INV + Invert output A + [2:2] + read-write + + + PH_CORRECT + 1: Enable phase-correct modulation. 0: Trailing-edge + [1:1] + read-write + + + EN + Enable the PWM channel. + [0:0] + read-write + + + + + CH7_DIV + 0x00000090 + INT and FRAC form a fixed-point fractional number. + Counting rate is system clock frequency divided by this number. + Fractional division uses simple 1st-order sigma-delta. + 0x00000010 + + + INT + [11:4] + read-write + + + FRAC + [3:0] + read-write + + + + + CH7_CTR + 0x00000094 + Direct access to the PWM counter + 0x00000000 + + + CH7_CTR + [15:0] + read-write + + + + + CH7_CC + 0x00000098 + Counter compare values + 0x00000000 + + + B + [31:16] + read-write + + + A + [15:0] + read-write + + + + + CH7_TOP + 0x0000009c + Counter wrap value + 0x0000ffff + + + CH7_TOP + [15:0] + read-write + + + + + EN + 0x000000a0 + This register aliases the CSR_EN bits for all channels. + Writing to this register allows multiple channels to be enabled + or disabled simultaneously, so they can run in perfect sync. + For each channel, there is only one physical EN register bit, + which can be accessed through here or CHx_CSR. + 0x00000000 + + + CH7 + [7:7] + read-write + + + CH6 + [6:6] + read-write + + + CH5 + [5:5] + read-write + + + CH4 + [4:4] + read-write + + + CH3 + [3:3] + read-write + + + CH2 + [2:2] + read-write + + + CH1 + [1:1] + read-write + + + CH0 + [0:0] + read-write + + + + + INTR + 0x000000a4 + Raw Interrupts + 0x00000000 + + + CH7 + [7:7] + read-write + oneToClear + + + CH6 + [6:6] + read-write + oneToClear + + + CH5 + [5:5] + read-write + oneToClear + + + CH4 + [4:4] + read-write + oneToClear + + + CH3 + [3:3] + read-write + oneToClear + + + CH2 + [2:2] + read-write + oneToClear + + + CH1 + [1:1] + read-write + oneToClear + + + CH0 + [0:0] + read-write + oneToClear + + + + + INTE + 0x000000a8 + Interrupt Enable + 0x00000000 + + + CH7 + [7:7] + read-write + + + CH6 + [6:6] + read-write + + + CH5 + [5:5] + read-write + + + CH4 + [4:4] + read-write + + + CH3 + [3:3] + read-write + + + CH2 + [2:2] + read-write + + + CH1 + [1:1] + read-write + + + CH0 + [0:0] + read-write + + + + + INTF + 0x000000ac + Interrupt Force + 0x00000000 + + + CH7 + [7:7] + read-write + + + CH6 + [6:6] + read-write + + + CH5 + [5:5] + read-write + + + CH4 + [4:4] + read-write + + + CH3 + [3:3] + read-write + + + CH2 + [2:2] + read-write + + + CH1 + [1:1] + read-write + + + CH0 + [0:0] + read-write + + + + + INTS + 0x000000b0 + Interrupt status after masking & forcing + 0x00000000 + + + CH7 + [7:7] + read-only + + + CH6 + [6:6] + read-only + + + CH5 + [5:5] + read-only + + + CH4 + [4:4] + read-only + + + CH3 + [3:3] + read-only + + + CH2 + [2:2] + read-only + + + CH1 + [1:1] + read-only + + + CH0 + [0:0] + read-only + + + + + + + ADC + Control and data interface to SAR ADC + 0x4004c000 + + 0 + 36 + registers + + + ADC_IRQ_FIFO + 22 + + + + CS + 0x00000000 + ADC Control and Status + 0x00000000 + + + RROBIN + Round-robin sampling. 1 bit per channel. Set all bits to 0 to disable. + Otherwise, the ADC will cycle through each enabled channel in a round-robin fashion. + The first channel to be sampled will be the one currently indicated by AINSEL. + AINSEL will be updated after each conversion with the newly-selected channel. + [20:16] + read-write + + + AINSEL + Select analog mux input. Updated automatically in round-robin mode. + [14:12] + read-write + + + ERR_STICKY + Some past ADC conversion encountered an error. Write 1 to clear. + [10:10] + read-write + oneToClear + + + ERR + The most recent ADC conversion encountered an error; result is undefined or noisy. + [9:9] + read-only + + + READY + 1 if the ADC is ready to start a new conversion. Implies any previous conversion has completed. + 0 whilst conversion in progress. + [8:8] + read-only + + + START_MANY + Continuously perform conversions whilst this bit is 1. A new conversion will start immediately after the previous finishes. + [3:3] + read-write + + + START_ONCE + Start a single conversion. Self-clearing. Ignored if start_many is asserted. + [2:2] + write-only + + + TS_EN + Power on temperature sensor. 1 - enabled. 0 - disabled. + [1:1] + read-write + + + EN + Power on ADC and enable its clock. + 1 - enabled. 0 - disabled. + [0:0] + read-write + + + + + RESULT + 0x00000004 + Result of most recent ADC conversion + 0x00000000 + + + RESULT + [11:0] + read-only + + + + + FCS + 0x00000008 + FIFO control and status + 0x00000000 + + + THRESH + DREQ/IRQ asserted when level >= threshold + [27:24] + read-write + + + LEVEL + The number of conversion results currently waiting in the FIFO + [19:16] + read-only + + + OVER + 1 if the FIFO has been overflowed. Write 1 to clear. + [11:11] + read-write + oneToClear + + + UNDER + 1 if the FIFO has been underflowed. Write 1 to clear. + [10:10] + read-write + oneToClear + + + FULL + [9:9] + read-only + + + EMPTY + [8:8] + read-only + + + DREQ_EN + If 1: assert DMA requests when FIFO contains data + [3:3] + read-write + + + ERR + If 1: conversion error bit appears in the FIFO alongside the result + [2:2] + read-write + + + SHIFT + If 1: FIFO results are right-shifted to be one byte in size. Enables DMA to byte buffers. + [1:1] + read-write + + + EN + If 1: write result to the FIFO after each conversion. + [0:0] + read-write + + + + + FIFO + 0x0000000c + Conversion result FIFO + 0x00000000 + + + ERR + 1 if this particular sample experienced a conversion error. Remains in the same location if the sample is shifted. + [15:15] + read-only + modify + + + VAL + [11:0] + read-only + modify + + + + + DIV + 0x00000010 + Clock divider. If non-zero, CS_START_MANY will start conversions + at regular intervals rather than back-to-back. + The divider is reset when either of these fields are written. + Total period is 1 + INT + FRAC / 256 + 0x00000000 + + + INT + Integer part of clock divisor. + [23:8] + read-write + + + FRAC + Fractional part of clock divisor. First-order delta-sigma. + [7:0] + read-write + + + + + INTR + 0x00000014 + Raw Interrupts + 0x00000000 + + + FIFO + Triggered when the sample FIFO reaches a certain level. + This level can be programmed via the FCS_THRESH field. + [0:0] + read-only + + + + + INTE + 0x00000018 + Interrupt Enable + 0x00000000 + + + FIFO + Triggered when the sample FIFO reaches a certain level. + This level can be programmed via the FCS_THRESH field. + [0:0] + read-write + + + + + INTF + 0x0000001c + Interrupt Force + 0x00000000 + + + FIFO + Triggered when the sample FIFO reaches a certain level. + This level can be programmed via the FCS_THRESH field. + [0:0] + read-write + + + + + INTS + 0x00000020 + Interrupt status after masking & forcing + 0x00000000 + + + FIFO + Triggered when the sample FIFO reaches a certain level. + This level can be programmed via the FCS_THRESH field. + [0:0] + read-only + + + + + + + I2C0 + DW_apb_i2c address block + + List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): + + IC_ULTRA_FAST_MODE ................ 0x0 + IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 + IC_UFM_SCL_LOW_COUNT .............. 0x0008 + IC_UFM_SCL_HIGH_COUNT ............. 0x0006 + IC_TX_TL .......................... 0x0 + IC_TX_CMD_BLOCK ................... 0x1 + IC_HAS_DMA ........................ 0x1 + IC_HAS_ASYNC_FIFO ................. 0x0 + IC_SMBUS_ARP ...................... 0x0 + IC_FIRST_DATA_BYTE_STATUS ......... 0x1 + IC_INTR_IO ........................ 0x1 + IC_MASTER_MODE .................... 0x1 + IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 + IC_INTR_POL ....................... 0x1 + IC_OPTIONAL_SAR ................... 0x0 + IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 + IC_DEFAULT_SLAVE_ADDR ............. 0x055 + IC_DEFAULT_HS_SPKLEN .............. 0x1 + IC_FS_SCL_HIGH_COUNT .............. 0x0006 + IC_HS_SCL_LOW_COUNT ............... 0x0008 + IC_DEVICE_ID_VALUE ................ 0x0 + IC_10BITADDR_MASTER ............... 0x0 + IC_CLK_FREQ_OPTIMIZATION .......... 0x0 + IC_DEFAULT_FS_SPKLEN .............. 0x7 + IC_ADD_ENCODED_PARAMS ............. 0x0 + IC_DEFAULT_SDA_HOLD ............... 0x000001 + IC_DEFAULT_SDA_SETUP .............. 0x64 + IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 + IC_CLOCK_PERIOD ................... 100 + IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 + IC_RESTART_EN ..................... 0x1 + IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 + IC_BUS_CLEAR_FEATURE .............. 0x0 + IC_CAP_LOADING .................... 100 + IC_FS_SCL_LOW_COUNT ............... 0x000d + APB_DATA_WIDTH .................... 32 + IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff + IC_SLV_DATA_NACK_ONLY ............. 0x1 + IC_10BITADDR_SLAVE ................ 0x0 + IC_CLK_TYPE ....................... 0x0 + IC_SMBUS_UDID_MSB ................. 0x0 + IC_SMBUS_SUSPEND_ALERT ............ 0x0 + IC_HS_SCL_HIGH_COUNT .............. 0x0006 + IC_SLV_RESTART_DET_EN ............. 0x1 + IC_SMBUS .......................... 0x0 + IC_OPTIONAL_SAR_DEFAULT ........... 0x0 + IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 + IC_USE_COUNTS ..................... 0x0 + IC_RX_BUFFER_DEPTH ................ 16 + IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff + IC_RX_FULL_HLD_BUS_EN ............. 0x1 + IC_SLAVE_DISABLE .................. 0x1 + IC_RX_TL .......................... 0x0 + IC_DEVICE_ID ...................... 0x0 + IC_HC_COUNT_VALUES ................ 0x0 + I2C_DYNAMIC_TAR_UPDATE ............ 0 + IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff + IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff + IC_HS_MASTER_CODE ................. 0x1 + IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff + IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff + IC_SS_SCL_HIGH_COUNT .............. 0x0028 + IC_SS_SCL_LOW_COUNT ............... 0x002f + IC_MAX_SPEED_MODE ................. 0x2 + IC_STAT_FOR_CLK_STRETCH ........... 0x0 + IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 + IC_DEFAULT_UFM_SPKLEN ............. 0x1 + IC_TX_BUFFER_DEPTH ................ 16 + 0x40044000 + + 0 + 256 + registers + + + I2C0_IRQ + 23 + + + + IC_CON + 0x00000000 + I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only. + 0x00000065 + + + STOP_DET_IF_MASTER_ACTIVE + Master issues the STOP_DET interrupt irrespective of whether master is active or not + [10:10] + read-only + + + RX_FIFO_FULL_HLD_CTRL + This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is physically full to its RX_BUFFER_DEPTH, as described in the IC_RX_FULL_HLD_BUS_EN parameter. + + Reset value: 0x0. + [9:9] + read-write + + + DISABLED + 0 + Overflow when RX_FIFO is full + + + ENABLED + 1 + Hold bus when RX_FIFO is full + + + + + TX_EMPTY_CTRL + This bit controls the generation of the TX_EMPTY interrupt, as described in the IC_RAW_INTR_STAT register. + + Reset value: 0x0. + [8:8] + read-write + + + DISABLED + 0 + Default behaviour of TX_EMPTY interrupt + + + ENABLED + 1 + Controlled generation of TX_EMPTY interrupt + + + + + STOP_DET_IFADDRESSED + In slave mode: - 1'b1: issues the STOP_DET interrupt only when it is addressed. - 1'b0: issues the STOP_DET irrespective of whether it's addressed or not. Reset value: 0x0 + + NOTE: During a general call address, this slave does not issue the STOP_DET interrupt if STOP_DET_IF_ADDRESSED = 1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). + [7:7] + read-write + + + DISABLED + 0 + slave issues STOP_DET intr always + + + ENABLED + 1 + slave issues STOP_DET intr only if addressed + + + + + IC_SLAVE_DISABLE + This bit controls whether I2C has its slave disabled, which means once the presetn signal is applied, then this bit is set and the slave is disabled. + + If this bit is set (slave is disabled), DW_apb_i2c functions only as a master and does not perform any action that requires a slave. + + NOTE: Software should ensure that if this bit is written with 0, then bit 0 should also be written with a 0. + [6:6] + read-write + + + SLAVE_ENABLED + 0 + Slave mode is enabled + + + SLAVE_DISABLED + 1 + Slave mode is disabled + + + + + IC_RESTART_EN + Determines whether RESTART conditions may be sent when acting as a master. Some older slaves do not support handling RESTART conditions; however, RESTART conditions are used in several DW_apb_i2c operations. When RESTART is disabled, the master is prohibited from performing the following functions: - Sending a START BYTE - Performing any high-speed mode operation - High-speed mode operation - Performing direction changes in combined format mode - Performing a read operation with a 10-bit address By replacing RESTART condition followed by a STOP and a subsequent START condition, split operations are broken down into multiple DW_apb_i2c transfers. If the above operations are performed, it will result in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. + + Reset value: ENABLED + [5:5] + read-write + + + DISABLED + 0 + Master restart disabled + + + ENABLED + 1 + Master restart enabled + + + + + IC_10BITADDR_MASTER + Controls whether the DW_apb_i2c starts its transfers in 7- or 10-bit addressing mode when acting as a master. - 0: 7-bit addressing - 1: 10-bit addressing + [4:4] + read-write + + + ADDR_7BITS + 0 + Master 7Bit addressing mode + + + ADDR_10BITS + 1 + Master 10Bit addressing mode + + + + + IC_10BITADDR_SLAVE + When acting as a slave, this bit controls whether the DW_apb_i2c responds to 7- or 10-bit addresses. - 0: 7-bit addressing. The DW_apb_i2c ignores transactions that involve 10-bit addressing; for 7-bit addressing, only the lower 7 bits of the IC_SAR register are compared. - 1: 10-bit addressing. The DW_apb_i2c responds to only 10-bit addressing transfers that match the full 10 bits of the IC_SAR register. + [3:3] + read-write + + + ADDR_7BITS + 0 + Slave 7Bit addressing + + + ADDR_10BITS + 1 + Slave 10Bit addressing + + + + + SPEED + These bits control at which speed the DW_apb_i2c operates; its setting is relevant only if one is operating the DW_apb_i2c in master mode. Hardware protects against illegal values being programmed by software. These bits must be programmed appropriately for slave mode also, as it is used to capture correct value of spike filter as per the speed mode. + + This register should be programmed only with a value in the range of 1 to IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of IC_MAX_SPEED_MODE. + + 1: standard mode (100 kbit/s) + + 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s) + + 3: high speed mode (3.4 Mbit/s) + + Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 + [2:1] + read-write + + + STANDARD + 1 + Standard Speed mode of operation + + + FAST + 2 + Fast or Fast Plus mode of operation + + + HIGH + 3 + High Speed mode of operation + + + + + MASTER_MODE + This bit controls whether the DW_apb_i2c master is enabled. + + NOTE: Software should ensure that if this bit is written with '1' then bit 6 should also be written with a '1'. + [0:0] + read-write + + + DISABLED + 0 + Master mode is disabled + + + ENABLED + 1 + Master mode is enabled + + + + + + + IC_TAR + 0x00000004 + I2C Target Address Register + + This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0. + + Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only. + 0x00000055 + + + SPECIAL + This bit indicates whether software performs a Device-ID or General Call or START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: perform special I2C command as specified in Device_ID or GC_OR_START bit Reset value: 0x0 + [11:11] + read-write + + + DISABLED + 0 + Disables programming of GENERAL_CALL or START_BYTE transmission + + + ENABLED + 1 + Enables programming of GENERAL_CALL or START_BYTE transmission + + + + + GC_OR_START + If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit indicates whether a General Call or START byte command is to be performed by the DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only writes may be performed. Attempting to issue a read command results in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START BYTE Reset value: 0x0 + [10:10] + read-write + + + GENERAL_CALL + 0 + GENERAL_CALL byte transmission + + + START_BYTE + 1 + START byte transmission + + + + + IC_TAR + This is the target address for any master transaction. When transmitting a General Call, these bits are ignored. To generate a START BYTE, the CPU needs to write only once into these bits. + + If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared between master and slave, so full loopback is not feasible. Only one direction loopback mode is supported (simplex), not duplex. A master cannot transmit to itself; it can transmit to only a slave. + [9:0] + read-write + + + + + IC_SAR + 0x00000008 + I2C Slave Address Register + 0x00000055 + + + IC_SAR + The IC_SAR holds the slave address when the I2C is operating as a slave. For 7-bit addressing, only IC_SAR[6:0] is used. + + This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + Note: The default values cannot be any of the reserved address locations: that is, 0x00 to 0x07, or 0x78 to 0x7f. The correct operation of the device is not guaranteed if you program the IC_SAR or IC_TAR to a reserved value. Refer to <<table_I2C_firstbyte_bit_defs>> for a complete list of these reserved values. + [9:0] + read-write + + + + + IC_DATA_CMD + 0x00000010 + I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO. + + The size of the register changes as follows: + + Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging. + 0x00000000 + + + FIRST_DATA_BYTE + Indicates the first data byte received after the address phase for receive transfer in Master receiver or Slave receiver mode. + + Reset value : 0x0 + + NOTE: In case of APB_DATA_WIDTH=8, + + 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status on 11 bit. + + 2. In order to read the 11 bit, the user has to perform the first data byte read [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in order to know the status of 11 bit (whether the data received in previous read is a first data byte or not). + + 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] (offset 0x11) if not interested in FIRST_DATA_BYTE status. + [11:11] + read-only + + + INACTIVE + 0 + Sequential data byte received + + + ACTIVE + 1 + Non sequential data byte received + + + + + RESTART + This bit controls whether a RESTART is issued before the byte is sent or received. + + 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received (according to the value of CMD), regardless of whether or not the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. + + 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. + + Reset value: 0x0 + [10:10] + write-only + + + DISABLE + 0 + Don't Issue RESTART before this command + + + ENABLE + 1 + Issue RESTART before this command + + + + + STOP + This bit controls whether a STOP is issued after the byte is sent or received. + + - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master immediately tries to start a new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master continues the current transfer by sending/receiving data bytes according to the value of the CMD bit. If the Tx FIFO is empty, the master holds the SCL line low and stalls the bus until a new command is available in the Tx FIFO. Reset value: 0x0 + [9:9] + write-only + + + DISABLE + 0 + Don't Issue STOP after this command + + + ENABLE + 1 + Issue STOP after this command + + + + + CMD + This bit controls whether a read or a write is performed. This bit does not control the direction when the DW_apb_i2con acts as a slave. It controls only the direction when it acts as a master. + + When a command is entered in the TX FIFO, this bit distinguishes the write and read commands. In slave-receiver mode, this bit is a 'don't care' because writes to this register are not required. In slave-transmitter mode, a '0' indicates that the data in IC_DATA_CMD is to be transmitted. + + When programming this bit, you should remember the following: attempting to perform a read operation after a General Call command has been sent results in a TX_ABRT interrupt (bit 6 of the IC_RAW_INTR_STAT register), unless bit 11 (SPECIAL) in the IC_TAR register has been cleared. If a '1' is written to this bit after receiving a RD_REQ interrupt, then a TX_ABRT interrupt occurs. + + Reset value: 0x0 + [8:8] + write-only + + + WRITE + 0 + Master Write Command + + + READ + 1 + Master Read Command + + + + + DAT + This register contains the data to be transmitted or received on the I2C bus. If you are writing to this register and want to perform a read, bits 7:0 (DAT) are ignored by the DW_apb_i2c. However, when you read this register, these bits return the value of data received on the DW_apb_i2c interface. + + Reset value: 0x0 + [7:0] + read-write + + + + + IC_SS_SCL_HCNT + 0x00000014 + Standard Speed I2C Clock SCL High Count Register + 0x00000028 + + + IC_SS_SCL_HCNT + This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration'. + + This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. + + NOTE: This register must not be programmed to a value higher than 65525, because DW_apb_i2c uses a 16-bit counter to flag an I2C bus idle condition when this counter reaches a value of IC_SS_SCL_HCNT + 10. + [15:0] + read-write + + + + + IC_SS_SCL_LCNT + 0x00000018 + Standard Speed I2C Clock SCL Low Count Register + 0x0000002f + + + IC_SS_SCL_LCNT + This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration' + + This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + The minimum valid value is 8; hardware prevents values less than this being written, and if attempted, results in 8 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of DW_apb_i2c. The lower byte must be programmed first, and then the upper byte is programmed. + [15:0] + read-write + + + + + IC_FS_SCL_HCNT + 0x0000001c + Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register + 0x00000006 + + + IC_FS_SCL_HCNT + This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for fast mode or fast mode plus. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. + + This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH == 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. + [15:0] + read-write + + + + + IC_FS_SCL_LCNT + 0x00000020 + Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register + 0x0000000d + + + IC_FS_SCL_LCNT + This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for fast speed. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. + + This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. + + This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. + + The minimum valid value is 8; hardware prevents values less than this being written, and if attempted results in 8 being set. For designs with APB_DATA_WIDTH = 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. If the value is less than 8 then the count value gets changed to 8. + [15:0] + read-write + + + + + IC_INTR_STAT + 0x0000002c + I2C Interrupt Status Register + + Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. + 0x00000000 + + + R_RESTART_DET + See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit. + + Reset value: 0x0 + [12:12] + read-only + + + INACTIVE + 0 + R_RESTART_DET interrupt is inactive + + + ACTIVE + 1 + R_RESTART_DET interrupt is active + + + + + R_GEN_CALL + See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit. + + Reset value: 0x0 + [11:11] + read-only + + + INACTIVE + 0 + R_GEN_CALL interrupt is inactive + + + ACTIVE + 1 + R_GEN_CALL interrupt is active + + + + + R_START_DET + See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit. + + Reset value: 0x0 + [10:10] + read-only + + + INACTIVE + 0 + R_START_DET interrupt is inactive + + + ACTIVE + 1 + R_START_DET interrupt is active + + + + + R_STOP_DET + See IC_RAW_INTR_STAT for a detailed description of R_STOP_DET bit. + + Reset value: 0x0 + [9:9] + read-only + + + INACTIVE + 0 + R_STOP_DET interrupt is inactive + + + ACTIVE + 1 + R_STOP_DET interrupt is active + + + + + R_ACTIVITY + See IC_RAW_INTR_STAT for a detailed description of R_ACTIVITY bit. + + Reset value: 0x0 + [8:8] + read-only + + + INACTIVE + 0 + R_ACTIVITY interrupt is inactive + + + ACTIVE + 1 + R_ACTIVITY interrupt is active + + + + + R_RX_DONE + See IC_RAW_INTR_STAT for a detailed description of R_RX_DONE bit. + + Reset value: 0x0 + [7:7] + read-only + + + INACTIVE + 0 + R_RX_DONE interrupt is inactive + + + ACTIVE + 1 + R_RX_DONE interrupt is active + + + + + R_TX_ABRT + See IC_RAW_INTR_STAT for a detailed description of R_TX_ABRT bit. + + Reset value: 0x0 + [6:6] + read-only + + + INACTIVE + 0 + R_TX_ABRT interrupt is inactive + + + ACTIVE + 1 + R_TX_ABRT interrupt is active + + + + + R_RD_REQ + See IC_RAW_INTR_STAT for a detailed description of R_RD_REQ bit. + + Reset value: 0x0 + [5:5] + read-only + + + INACTIVE + 0 + R_RD_REQ interrupt is inactive + + + ACTIVE + 1 + R_RD_REQ interrupt is active + + + + + R_TX_EMPTY + See IC_RAW_INTR_STAT for a detailed description of R_TX_EMPTY bit. + + Reset value: 0x0 + [4:4] + read-only + + + INACTIVE + 0 + R_TX_EMPTY interrupt is inactive + + + ACTIVE + 1 + R_TX_EMPTY interrupt is active + + + + + R_TX_OVER + See IC_RAW_INTR_STAT for a detailed description of R_TX_OVER bit. + + Reset value: 0x0 + [3:3] + read-only + + + INACTIVE + 0 + R_TX_OVER interrupt is inactive + + + ACTIVE + 1 + R_TX_OVER interrupt is active + + + + + R_RX_FULL + See IC_RAW_INTR_STAT for a detailed description of R_RX_FULL bit. + + Reset value: 0x0 + [2:2] + read-only + + + INACTIVE + 0 + R_RX_FULL interrupt is inactive + + + ACTIVE + 1 + R_RX_FULL interrupt is active + + + + + R_RX_OVER + See IC_RAW_INTR_STAT for a detailed description of R_RX_OVER bit. + + Reset value: 0x0 + [1:1] + read-only + + + INACTIVE + 0 + R_RX_OVER interrupt is inactive + + + ACTIVE + 1 + R_RX_OVER interrupt is active + + + + + R_RX_UNDER + See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit. + + Reset value: 0x0 + [0:0] + read-only + + + INACTIVE + 0 + RX_UNDER interrupt is inactive + + + ACTIVE + 1 + RX_UNDER interrupt is active + + + + + + + IC_INTR_MASK + 0x00000030 + I2C Interrupt Mask Register. + + These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. + 0x000008ff + + + M_RESTART_DET + This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register. + + Reset value: 0x0 + [12:12] + read-write + + + ENABLED + 0 + RESTART_DET interrupt is masked + + + DISABLED + 1 + RESTART_DET interrupt is unmasked + + + + + M_GEN_CALL + This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [11:11] + read-write + + + ENABLED + 0 + GEN_CALL interrupt is masked + + + DISABLED + 1 + GEN_CALL interrupt is unmasked + + + + + M_START_DET + This bit masks the R_START_DET interrupt in IC_INTR_STAT register. + + Reset value: 0x0 + [10:10] + read-write + + + ENABLED + 0 + START_DET interrupt is masked + + + DISABLED + 1 + START_DET interrupt is unmasked + + + + + M_STOP_DET + This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register. + + Reset value: 0x0 + [9:9] + read-write + + + ENABLED + 0 + STOP_DET interrupt is masked + + + DISABLED + 1 + STOP_DET interrupt is unmasked + + + + + M_ACTIVITY + This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register. + + Reset value: 0x0 + [8:8] + read-write + + + ENABLED + 0 + ACTIVITY interrupt is masked + + + DISABLED + 1 + ACTIVITY interrupt is unmasked + + + + + M_RX_DONE + This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [7:7] + read-write + + + ENABLED + 0 + RX_DONE interrupt is masked + + + DISABLED + 1 + RX_DONE interrupt is unmasked + + + + + M_TX_ABRT + This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [6:6] + read-write + + + ENABLED + 0 + TX_ABORT interrupt is masked + + + DISABLED + 1 + TX_ABORT interrupt is unmasked + + + + + M_RD_REQ + This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [5:5] + read-write + + + ENABLED + 0 + RD_REQ interrupt is masked + + + DISABLED + 1 + RD_REQ interrupt is unmasked + + + + + M_TX_EMPTY + This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [4:4] + read-write + + + ENABLED + 0 + TX_EMPTY interrupt is masked + + + DISABLED + 1 + TX_EMPTY interrupt is unmasked + + + + + M_TX_OVER + This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [3:3] + read-write + + + ENABLED + 0 + TX_OVER interrupt is masked + + + DISABLED + 1 + TX_OVER interrupt is unmasked + + + + + M_RX_FULL + This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [2:2] + read-write + + + ENABLED + 0 + RX_FULL interrupt is masked + + + DISABLED + 1 + RX_FULL interrupt is unmasked + + + + + M_RX_OVER + This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [1:1] + read-write + + + ENABLED + 0 + RX_OVER interrupt is masked + + + DISABLED + 1 + RX_OVER interrupt is unmasked + + + + + M_RX_UNDER + This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register. + + Reset value: 0x1 + [0:0] + read-write + + + ENABLED + 0 + RX_UNDER interrupt is masked + + + DISABLED + 1 + RX_UNDER interrupt is unmasked + + + + + + + IC_RAW_INTR_STAT + 0x00000034 + I2C Raw Interrupt Status Register + + Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c. + 0x00000000 + + + RESTART_DET + Indicates whether a RESTART condition has occurred on the I2C interface when DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled only when IC_SLV_RESTART_DET_EN=1. + + Note: However, in high-speed mode or during a START BYTE transfer, the RESTART comes before the address field as per the I2C protocol. In this case, the slave is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does not generate the RESTART_DET interrupt. + + Reset value: 0x0 + [12:12] + read-only + + + INACTIVE + 0 + RESTART_DET interrupt is inactive + + + ACTIVE + 1 + RESTART_DET interrupt is active + + + + + GEN_CALL + Set only when a General Call address is received and it is acknowledged. It stays set until it is cleared either by disabling DW_apb_i2c or when the CPU reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data in the Rx buffer. + + Reset value: 0x0 + [11:11] + read-only + + + INACTIVE + 0 + GEN_CALL interrupt is inactive + + + ACTIVE + 1 + GEN_CALL interrupt is active + + + + + START_DET + Indicates whether a START or RESTART condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. + + Reset value: 0x0 + [10:10] + read-only + + + INACTIVE + 0 + START_DET interrupt is inactive + + + ACTIVE + 1 + START_DET interrupt is active + + + + + STOP_DET + Indicates whether a STOP condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. + + In Slave Mode: - If IC_CON[7]=1'b1 (STOP_DET_IFADDRESSED), the STOP_DET interrupt will be issued only if slave is addressed. Note: During a general call address, this slave does not issue a STOP_DET interrupt if STOP_DET_IF_ADDRESSED=1'b1, even if the slave responds to the general call address by generating ACK. The STOP_DET interrupt is generated only when the transmitted address matches the slave address (SAR). - If IC_CON[7]=1'b0 (STOP_DET_IFADDRESSED), the STOP_DET interrupt is issued irrespective of whether it is being addressed. In Master Mode: - If IC_CON[10]=1'b1 (STOP_DET_IF_MASTER_ACTIVE),the STOP_DET interrupt will be issued only if Master is active. - If IC_CON[10]=1'b0 (STOP_DET_IFADDRESSED),the STOP_DET interrupt will be issued irrespective of whether master is active or not. Reset value: 0x0 + [9:9] + read-only + + + INACTIVE + 0 + STOP_DET interrupt is inactive + + + ACTIVE + 1 + STOP_DET interrupt is active + + + + + ACTIVITY + This bit captures DW_apb_i2c activity and stays set until it is cleared. There are four ways to clear it: - Disabling the DW_apb_i2c - Reading the IC_CLR_ACTIVITY register - Reading the IC_CLR_INTR register - System reset Once this bit is set, it stays set unless one of the four methods is used to clear it. Even if the DW_apb_i2c module is idle, this bit remains set until cleared, indicating that there was activity on the bus. + + Reset value: 0x0 + [8:8] + read-only + + + INACTIVE + 0 + RAW_INTR_ACTIVITY interrupt is inactive + + + ACTIVE + 1 + RAW_INTR_ACTIVITY interrupt is active + + + + + RX_DONE + When the DW_apb_i2c is acting as a slave-transmitter, this bit is set to 1 if the master does not acknowledge a transmitted byte. This occurs on the last byte of the transmission, indicating that the transmission is done. + + Reset value: 0x0 + [7:7] + read-only + + + INACTIVE + 0 + RX_DONE interrupt is inactive + + + ACTIVE + 1 + RX_DONE interrupt is active + + + + + TX_ABRT + This bit indicates if DW_apb_i2c, as an I2C transmitter, is unable to complete the intended actions on the contents of the transmit FIFO. This situation can occur both as an I2C master or an I2C slave, and is referred to as a 'transmit abort'. When this bit is set to 1, the IC_TX_ABRT_SOURCE register indicates the reason why the transmit abort takes places. + + Note: The DW_apb_i2c flushes/resets/empties the TX_FIFO and RX_FIFO whenever there is a transmit abort caused by any of the events tracked by the IC_TX_ABRT_SOURCE register. The FIFOs remains in this flushed state until the register IC_CLR_TX_ABRT is read. Once this read is performed, the Tx FIFO is then ready to accept more data bytes from the APB interface. + + Reset value: 0x0 + [6:6] + read-only + + + INACTIVE + 0 + TX_ABRT interrupt is inactive + + + ACTIVE + 1 + TX_ABRT interrupt is active + + + + + RD_REQ + This bit is set to 1 when DW_apb_i2c is acting as a slave and another I2C master is attempting to read data from DW_apb_i2c. The DW_apb_i2c holds the I2C bus in a wait state (SCL=0) until this interrupt is serviced, which means that the slave has been addressed by a remote master that is asking for data to be transferred. The processor must respond to this interrupt and then write the requested data to the IC_DATA_CMD register. This bit is set to 0 just after the processor reads the IC_CLR_RD_REQ register. + + Reset value: 0x0 + [5:5] + read-only + + + INACTIVE + 0 + RD_REQ interrupt is inactive + + + ACTIVE + 1 + RD_REQ interrupt is active + + + + + TX_EMPTY + The behavior of the TX_EMPTY interrupt status differs based on the TX_EMPTY_CTRL selection in the IC_CON register. - When TX_EMPTY_CTRL = 0: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register. - When TX_EMPTY_CTRL = 1: This bit is set to 1 when the transmit buffer is at or below the threshold value set in the IC_TX_TL register and the transmission of the address/data from the internal shift register for the most recently popped command is completed. It is automatically cleared by hardware when the buffer level goes above the threshold. When IC_ENABLE[0] is set to 0, the TX FIFO is flushed and held in reset. There the TX FIFO looks like it has no data within it, so this bit is set to 1, provided there is activity in the master or slave state machines. When there is no longer any activity, then with ic_en=0, this bit is set to 0. + + Reset value: 0x0. + [4:4] + read-only + + + INACTIVE + 0 + TX_EMPTY interrupt is inactive + + + ACTIVE + 1 + TX_EMPTY interrupt is active + + + + + TX_OVER + Set during transmit if the transmit buffer is filled to IC_TX_BUFFER_DEPTH and the processor attempts to issue another I2C command by writing to the IC_DATA_CMD register. When the module is disabled, this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. + + Reset value: 0x0 + [3:3] + read-only + + + INACTIVE + 0 + TX_OVER interrupt is inactive + + + ACTIVE + 1 + TX_OVER interrupt is active + + + + + RX_FULL + Set when the receive buffer reaches or goes above the RX_TL threshold in the IC_RX_TL register. It is automatically cleared by hardware when buffer level goes below the threshold. If the module is disabled (IC_ENABLE[0]=0), the RX FIFO is flushed and held in reset; therefore the RX FIFO is not full. So this bit is cleared once the IC_ENABLE bit 0 is programmed with a 0, regardless of the activity that continues. + + Reset value: 0x0 + [2:2] + read-only + + + INACTIVE + 0 + RX_FULL interrupt is inactive + + + ACTIVE + 1 + RX_FULL interrupt is active + + + + + RX_OVER + Set if the receive buffer is completely filled to IC_RX_BUFFER_DEPTH and an additional byte is received from an external I2C device. The DW_apb_i2c acknowledges this, but any data bytes received after the FIFO is full are lost. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. + + Note: If bit 9 of the IC_CON register (RX_FIFO_FULL_HLD_CTRL) is programmed to HIGH, then the RX_OVER interrupt never occurs, because the Rx FIFO never overflows. + + Reset value: 0x0 + [1:1] + read-only + + + INACTIVE + 0 + RX_OVER interrupt is inactive + + + ACTIVE + 1 + RX_OVER interrupt is active + + + + + RX_UNDER + Set if the processor attempts to read the receive buffer when it is empty by reading from the IC_DATA_CMD register. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. + + Reset value: 0x0 + [0:0] + read-only + + + INACTIVE + 0 + RX_UNDER interrupt is inactive + + + ACTIVE + 1 + RX_UNDER interrupt is active + + + + + + + IC_RX_TL + 0x00000038 + I2C Receive FIFO Threshold Register + 0x00000000 + + + RX_TL + Receive FIFO Threshold Level. + + Controls the level of entries (or above) that triggers the RX_FULL interrupt (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that hardware does not allow this value to be set to a value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. + [7:0] + read-write + + + + + IC_TX_TL + 0x0000003c + I2C Transmit FIFO Threshold Register + 0x00000000 + + + TX_TL + Transmit FIFO Threshold Level. + + Controls the level of entries (or below) that trigger the TX_EMPTY interrupt (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that it may not be set to value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and a value of 255 sets the threshold for 255 entries. + [7:0] + read-write + + + + + IC_CLR_INTR + 0x00000040 + Clear Combined and Individual Interrupt Register + 0x00000000 + + + CLR_INTR + Read this register to clear the combined interrupt, all individual interrupts, and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable interrupts but software clearable interrupts. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_RX_UNDER + 0x00000044 + Clear RX_UNDER Interrupt Register + 0x00000000 + + + CLR_RX_UNDER + Read this register to clear the RX_UNDER interrupt (bit 0) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_RX_OVER + 0x00000048 + Clear RX_OVER Interrupt Register + 0x00000000 + + + CLR_RX_OVER + Read this register to clear the RX_OVER interrupt (bit 1) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_TX_OVER + 0x0000004c + Clear TX_OVER Interrupt Register + 0x00000000 + + + CLR_TX_OVER + Read this register to clear the TX_OVER interrupt (bit 3) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_RD_REQ + 0x00000050 + Clear RD_REQ Interrupt Register + 0x00000000 + + + CLR_RD_REQ + Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_TX_ABRT + 0x00000054 + Clear TX_ABRT Interrupt Register + 0x00000000 + + + CLR_TX_ABRT + Read this register to clear the TX_ABRT interrupt (bit 6) of the IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also releases the TX FIFO from the flushed/reset state, allowing more writes to the TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_RX_DONE + 0x00000058 + Clear RX_DONE Interrupt Register + 0x00000000 + + + CLR_RX_DONE + Read this register to clear the RX_DONE interrupt (bit 7) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_ACTIVITY + 0x0000005c + Clear ACTIVITY Interrupt Register + 0x00000000 + + + CLR_ACTIVITY + Reading this register clears the ACTIVITY interrupt if the I2C is not active anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt bit continues to be set. It is automatically cleared by hardware if the module is disabled and if there is no further activity on the bus. The value read from this register to get status of the ACTIVITY interrupt (bit 8) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_STOP_DET + 0x00000060 + Clear STOP_DET Interrupt Register + 0x00000000 + + + CLR_STOP_DET + Read this register to clear the STOP_DET interrupt (bit 9) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_START_DET + 0x00000064 + Clear START_DET Interrupt Register + 0x00000000 + + + CLR_START_DET + Read this register to clear the START_DET interrupt (bit 10) of the IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_CLR_GEN_CALL + 0x00000068 + Clear GEN_CALL Interrupt Register + 0x00000000 + + + CLR_GEN_CALL + Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_ENABLE + 0x0000006c + I2C Enable Register + 0x00000000 + + + TX_CMD_BLOCK + In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus automatically, as soon as the first data is available in the Tx FIFO. Note: To block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT + [2:2] + read-write + + + NOT_BLOCKED + 0 + Tx Command execution not blocked + + + BLOCKED + 1 + Tx Command execution blocked + + + + + ABORT + When set, the controller initiates the transfer abort. - 0: ABORT not initiated or ABORT done - 1: ABORT operation in progress The software can abort the I2C transfer in master mode by setting this bit. The software can set this bit only when ENABLE is already set; otherwise, the controller ignores any write to ABORT bit. The software cannot clear the ABORT bit once set. In response to an ABORT, the controller issues a STOP and flushes the Tx FIFO after completing the current transfer, then sets the TX_ABORT interrupt after the abort operation. The ABORT bit is cleared automatically after the abort operation. + + For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C Transfers'. + + Reset value: 0x0 + [1:1] + read-write + + + DISABLE + 0 + ABORT operation not in progress + + + ENABLED + 1 + ABORT operation in progress + + + + + ENABLE + Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable DW_apb_i2c while it is active. However, it is important that care be taken to ensure that DW_apb_i2c is disabled properly. A recommended procedure is described in 'Disabling DW_apb_i2c'. + + When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get flushed. - Status bits in the IC_INTR_STAT register are still active until DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well as deletes the contents of the transmit buffer after the current transfer is complete. If the module is receiving, the DW_apb_i2c stops the current transfer at the end of the current byte and does not acknowledge the transfer. + + In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to asynchronous (1), there is a two ic_clk delay when enabling or disabling the DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to 'Disabling DW_apb_i2c' + + Reset value: 0x0 + [0:0] + read-write + + + DISABLED + 0 + I2C is disabled + + + ENABLED + 1 + I2C is enabled + + + + + + + IC_STATUS + 0x00000070 + I2C Status Register + + This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt. + + When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 + 0x00000006 + + + SLV_ACTIVITY + Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the Slave part of DW_apb_i2c is Active Reset value: 0x0 + [6:6] + read-only + + + IDLE + 0 + Slave is idle + + + ACTIVE + 1 + Slave not idle + + + + + MST_ACTIVITY + Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is the OR of SLV_ACTIVITY and MST_ACTIVITY bits. + + Reset value: 0x0 + [5:5] + read-only + + + IDLE + 0 + Master is idle + + + ACTIVE + 1 + Master not idle + + + + + RFF + Receive FIFO Completely Full. When the receive FIFO is completely full, this bit is set. When the receive FIFO contains one or more empty location, this bit is cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: 0x0 + [4:4] + read-only + + + NOT_FULL + 0 + Rx FIFO not full + + + FULL + 1 + Rx FIFO is full + + + + + RFNE + Receive FIFO Not Empty. This bit is set when the receive FIFO contains one or more entries; it is cleared when the receive FIFO is empty. - 0: Receive FIFO is empty - 1: Receive FIFO is not empty Reset value: 0x0 + [3:3] + read-only + + + EMPTY + 0 + Rx FIFO is empty + + + NOT_EMPTY + 1 + Rx FIFO not empty + + + + + TFE + Transmit FIFO Completely Empty. When the transmit FIFO is completely empty, this bit is set. When it contains one or more valid entries, this bit is cleared. This bit field does not request an interrupt. - 0: Transmit FIFO is not empty - 1: Transmit FIFO is empty Reset value: 0x1 + [2:2] + read-only + + + NON_EMPTY + 0 + Tx FIFO not empty + + + EMPTY + 1 + Tx FIFO is empty + + + + + TFNF + Transmit FIFO Not Full. Set when the transmit FIFO contains one or more empty locations, and is cleared when the FIFO is full. - 0: Transmit FIFO is full - 1: Transmit FIFO is not full Reset value: 0x1 + [1:1] + read-only + + + FULL + 0 + Tx FIFO is full + + + NOT_FULL + 1 + Tx FIFO not full + + + + + ACTIVITY + I2C Activity Status. Reset value: 0x0 + [0:0] + read-only + + + INACTIVE + 0 + I2C is idle + + + ACTIVE + 1 + I2C is active + + + + + + + IC_TXFLR + 0x00000074 + I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO. + 0x00000000 + + + TXFLR + Transmit FIFO Level. Contains the number of valid data entries in the transmit FIFO. + + Reset value: 0x0 + [4:0] + read-only + + + + + IC_RXFLR + 0x00000078 + I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO. + 0x00000000 + + + RXFLR + Receive FIFO Level. Contains the number of valid data entries in the receive FIFO. + + Reset value: 0x0 + [4:0] + read-only + + + + + IC_SDA_HOLD + 0x0000007c + I2C SDA Hold Time Length Register + + The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW). + + The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode. + + Writes to this register succeed only when IC_ENABLE[0]=0. + + The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented. + + The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles. + 0x00000001 + + + IC_SDA_RX_HOLD + Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a receiver. + + Reset value: IC_DEFAULT_SDA_HOLD[23:16]. + [23:16] + read-write + + + IC_SDA_TX_HOLD + Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a transmitter. + + Reset value: IC_DEFAULT_SDA_HOLD[15:0]. + [15:0] + read-write + + + + + IC_TX_ABRT_SOURCE + 0x00000080 + I2C Transmit Abort Source Register + + This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). + + Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted. + 0x00000000 + + + TX_FLUSH_CNT + This field indicates the number of Tx FIFO Data Commands which are flushed due to TX_ABRT interrupt. It is cleared whenever I2C is disabled. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + [31:23] + read-only + + + ABRT_USER_ABRT + This is a master-mode-only bit. Master has detected the transfer abort (IC_ENABLE[1]) + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter + [16:16] + read-only + + + ABRT_USER_ABRT_VOID + 0 + Transfer abort detected by master- scenario not present + + + ABRT_USER_ABRT_GENERATED + 1 + Transfer abort detected by master + + + + + ABRT_SLVRD_INTX + 1: When the processor side responds to a slave mode request for data to be transmitted to a remote master and user writes a 1 in CMD (bit 8) of IC_DATA_CMD register. + + Reset value: 0x0 + + Role of DW_apb_i2c: Slave-Transmitter + [15:15] + read-only + + + ABRT_SLVRD_INTX_VOID + 0 + Slave trying to transmit to remote master in read mode- scenario not present + + + ABRT_SLVRD_INTX_GENERATED + 1 + Slave trying to transmit to remote master in read mode + + + + + ABRT_SLV_ARBLOST + This field indicates that a Slave has lost the bus while transmitting data to a remote master. IC_TX_ABRT_SOURCE[12] is set at the same time. Note: Even though the slave never 'owns' the bus, something could go wrong on the bus. This is a fail safe check. For instance, during a data transmission at the low-to-high transition of SCL, if what is on the data bus is not what is supposed to be transmitted, then DW_apb_i2c no longer own the bus. + + Reset value: 0x0 + + Role of DW_apb_i2c: Slave-Transmitter + [14:14] + read-only + + + ABRT_SLV_ARBLOST_VOID + 0 + Slave lost arbitration to remote master- scenario not present + + + ABRT_SLV_ARBLOST_GENERATED + 1 + Slave lost arbitration to remote master + + + + + ABRT_SLVFLUSH_TXFIFO + This field specifies that the Slave has received a read command and some data exists in the TX FIFO, so the slave issues a TX_ABRT interrupt to flush old data in TX FIFO. + + Reset value: 0x0 + + Role of DW_apb_i2c: Slave-Transmitter + [13:13] + read-only + + + ABRT_SLVFLUSH_TXFIFO_VOID + 0 + Slave flushes existing data in TX-FIFO upon getting read command- scenario not present + + + ABRT_SLVFLUSH_TXFIFO_GENERATED + 1 + Slave flushes existing data in TX-FIFO upon getting read command + + + + + ARB_LOST + This field specifies that the Master has lost arbitration, or if IC_TX_ABRT_SOURCE[14] is also set, then the slave transmitter has lost arbitration. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Slave-Transmitter + [12:12] + read-only + + + ABRT_LOST_VOID + 0 + Master or Slave-Transmitter lost arbitration- scenario not present + + + ABRT_LOST_GENERATED + 1 + Master or Slave-Transmitter lost arbitration + + + + + ABRT_MASTER_DIS + This field indicates that the User tries to initiate a Master operation with the Master mode disabled. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + [11:11] + read-only + + + ABRT_MASTER_DIS_VOID + 0 + User initiating master operation when MASTER disabled- scenario not present + + + ABRT_MASTER_DIS_GENERATED + 1 + User initiating master operation when MASTER disabled + + + + + ABRT_10B_RD_NORSTRT + This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the master sends a read command in 10-bit addressing mode. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Receiver + [10:10] + read-only + + + ABRT_10B_RD_VOID + 0 + Master not trying to read in 10Bit addressing mode when RESTART disabled + + + ABRT_10B_RD_GENERATED + 1 + Master trying to read in 10Bit addressing mode when RESTART disabled + + + + + ABRT_SBYTE_NORSTRT + To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; restart must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, bit 9 clears for one cycle and then gets reasserted. When this field is set to 1, the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to send a START Byte. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master + [9:9] + read-only + + + ABRT_SBYTE_NORSTRT_VOID + 0 + User trying to send START byte when RESTART disabled- scenario not present + + + ABRT_SBYTE_NORSTRT_GENERATED + 1 + User trying to send START byte when RESTART disabled + + + + + ABRT_HS_NORSTRT + This field indicates that the restart is disabled (IC_RESTART_EN bit (IC_CON[5]) =0) and the user is trying to use the master to transfer data in High Speed mode. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + [8:8] + read-only + + + ABRT_HS_NORSTRT_VOID + 0 + User trying to switch Master to HS mode when RESTART disabled- scenario not present + + + ABRT_HS_NORSTRT_GENERATED + 1 + User trying to switch Master to HS mode when RESTART disabled + + + + + ABRT_SBYTE_ACKDET + This field indicates that the Master has sent a START Byte and the START Byte was acknowledged (wrong behavior). + + Reset value: 0x0 + + Role of DW_apb_i2c: Master + [7:7] + read-only + + + ABRT_SBYTE_ACKDET_VOID + 0 + ACK detected for START byte- scenario not present + + + ABRT_SBYTE_ACKDET_GENERATED + 1 + ACK detected for START byte + + + + + ABRT_HS_ACKDET + This field indicates that the Master is in High Speed mode and the High Speed Master code was acknowledged (wrong behavior). + + Reset value: 0x0 + + Role of DW_apb_i2c: Master + [6:6] + read-only + + + ABRT_HS_ACK_VOID + 0 + HS Master code ACKed in HS Mode- scenario not present + + + ABRT_HS_ACK_GENERATED + 1 + HS Master code ACKed in HS Mode + + + + + ABRT_GCALL_READ + This field indicates that DW_apb_i2c in the master mode has sent a General Call but the user programmed the byte following the General Call to be a read from the bus (IC_DATA_CMD[9] is set to 1). + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter + [5:5] + read-only + + + ABRT_GCALL_READ_VOID + 0 + GCALL is followed by read from bus-scenario not present + + + ABRT_GCALL_READ_GENERATED + 1 + GCALL is followed by read from bus + + + + + ABRT_GCALL_NOACK + This field indicates that DW_apb_i2c in master mode has sent a General Call and no slave on the bus acknowledged the General Call. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter + [4:4] + read-only + + + ABRT_GCALL_NOACK_VOID + 0 + GCALL not ACKed by any slave-scenario not present + + + ABRT_GCALL_NOACK_GENERATED + 1 + GCALL not ACKed by any slave + + + + + ABRT_TXDATA_NOACK + This field indicates the master-mode only bit. When the master receives an acknowledgement for the address, but when it sends data byte(s) following the address, it did not receive an acknowledge from the remote slave(s). + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter + [3:3] + read-only + + + ABRT_TXDATA_NOACK_VOID + 0 + Transmitted data non-ACKed by addressed slave-scenario not present + + + ABRT_TXDATA_NOACK_GENERATED + 1 + Transmitted data not ACKed by addressed slave + + + + + ABRT_10ADDR2_NOACK + This field indicates that the Master is in 10-bit address mode and that the second address byte of the 10-bit address was not acknowledged by any slave. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + [2:2] + read-only + + + INACTIVE + 0 + This abort is not generated + + + ACTIVE + 1 + Byte 2 of 10Bit Address not ACKed by any slave + + + + + ABRT_10ADDR1_NOACK + This field indicates that the Master is in 10-bit address mode and the first 10-bit address byte was not acknowledged by any slave. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + [1:1] + read-only + + + INACTIVE + 0 + This abort is not generated + + + ACTIVE + 1 + Byte 1 of 10Bit Address not ACKed by any slave + + + + + ABRT_7B_ADDR_NOACK + This field indicates that the Master is in 7-bit addressing mode and the address sent was not acknowledged by any slave. + + Reset value: 0x0 + + Role of DW_apb_i2c: Master-Transmitter or Master-Receiver + [0:0] + read-only + + + INACTIVE + 0 + This abort is not generated + + + ACTIVE + 1 + This abort is generated because of NOACK for 7-bit address + + + + + + + IC_SLV_DATA_NACK_ONLY + 0x00000084 + Generate Slave Data NACK Register + + The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect. + + A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit. + 0x00000000 + + + NACK + Generate NACK. This NACK generation only occurs when DW_apb_i2c is a slave-receiver. If this register is set to a value of 1, it can only generate a NACK after a data byte is received; hence, the data transfer is aborted and the data received is not pushed to the receive buffer. + + When the register is set to a value of 0, it generates NACK/ACK, depending on normal criteria. - 1: generate NACK after data byte received - 0: generate NACK/ACK normally Reset value: 0x0 + [0:0] + read-write + + + DISABLED + 0 + Slave receiver generates NACK normally + + + ENABLED + 1 + Slave receiver generates NACK upon data reception only + + + + + + + IC_DMA_CR + 0x00000088 + DMA Control Register + + The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE. + 0x00000000 + + + TDMAE + Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. Reset value: 0x0 + [1:1] + read-write + + + DISABLED + 0 + transmit FIFO DMA channel disabled + + + ENABLED + 1 + Transmit FIFO DMA channel enabled + + + + + RDMAE + Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. Reset value: 0x0 + [0:0] + read-write + + + DISABLED + 0 + Receive FIFO DMA channel disabled + + + ENABLED + 1 + Receive FIFO DMA channel enabled + + + + + + + IC_DMA_TDLR + 0x0000008c + DMA Transmit Data Level Register + 0x00000000 + + + DMATDL + Transmit Data Level. This bit field controls the level at which a DMA request is made by the transmit logic. It is equal to the watermark level; that is, the dma_tx_req signal is generated when the number of valid data entries in the transmit FIFO is equal to or below this field value, and TDMAE = 1. + + Reset value: 0x0 + [3:0] + read-write + + + + + IC_DMA_RDLR + 0x00000090 + I2C Receive Data Level Register + 0x00000000 + + + DMARDL + Receive Data Level. This bit field controls the level at which a DMA request is made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req is generated when the number of valid data entries in the receive FIFO is equal to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is 0, then dma_rx_req is asserted when 1 or more data entries are present in the receive FIFO. + + Reset value: 0x0 + [3:0] + read-write + + + + + IC_SDA_SETUP + 0x00000094 + I2C SDA Setup Register + + This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2. + + Writes to this register succeed only when IC_ENABLE[0] = 0. + + Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter. + 0x00000064 + + + SDA_SETUP + SDA Setup. It is recommended that if the required delay is 1000ns, then for an ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. IC_SDA_SETUP must be programmed with a minimum value of 2. + [7:0] + read-write + + + + + IC_ACK_GENERAL_CALL + 0x00000098 + I2C ACK General Call Register + + The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address. + + This register is applicable only when the DW_apb_i2c is in slave mode. + 0x00000001 + + + ACK_GEN_CALL + ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with a NACK (by negating ic_data_oe). + [0:0] + read-write + + + DISABLED + 0 + Generate NACK for a General Call + + + ENABLED + 1 + Generate ACK for a General Call + + + + + + + IC_ENABLE_STATUS + 0x0000009c + I2C Enable Status Register + + The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled. + + If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1. + + If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'. + + Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities. + 0x00000000 + + + SLV_RX_DATA_LOST + Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has been aborted with at least one data byte received from an I2C transfer due to the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed to have been actively engaged in an aborted I2C transfer (with matching address) and the data phase of the I2C transfer has been entered, even though a data byte has been responded with a NACK. + + Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit is also set to 1. + + When read as 0, DW_apb_i2c is deemed to have been disabled without being actively involved in the data phase of a Slave-Receiver transfer. + + Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. + + Reset value: 0x0 + [2:2] + read-only + + + INACTIVE + 0 + Slave RX Data is not lost + + + ACTIVE + 1 + Slave RX Data is lost + + + + + SLV_DISABLED_WHILE_BUSY + Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential or active Slave operation has been aborted due to the setting bit 0 of the IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the IC_ENABLE register while: + + (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation from a remote master; + + OR, + + (b) address and data bytes of the Slave-Receiver operation from a remote master. + + When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an I2C transfer, irrespective of whether the I2C address matches the slave address set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before IC_ENABLE is set to 0 but has not taken effect. + + Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit will also be set to 1. + + When read as 0, DW_apb_i2c is deemed to have been disabled when there is master activity, or when the I2C bus is idle. + + Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. + + Reset value: 0x0 + [1:1] + read-only + + + INACTIVE + 0 + Slave is disabled when it is idle + + + ACTIVE + 1 + Slave is disabled when it is active + + + + + IC_EN + ic_en Status. This bit always reflects the value driven on the output port ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely read this bit anytime. When this bit is read as 0, the CPU can safely read SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1). + + Reset value: 0x0 + [0:0] + read-only + + + DISABLED + 0 + I2C disabled + + + ENABLED + 1 + I2C enabled + + + + + + + IC_FS_SPKLEN + 0x000000a0 + I2C SS, FS or FM+ spike suppression limit + + This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1. + 0x00000007 + + + IC_FS_SPKLEN + This register must be set before any I2C bus transaction can take place to ensure stable operation. This register sets the duration, measured in ic_clk cycles, of the longest spike in the SCL or SDA lines that will be filtered out by the spike suppression logic. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 1; hardware prevents values less than this being written, and if attempted results in 1 being set. or more information, refer to 'Spike Suppression'. + [7:0] + read-write + + + + + IC_CLR_RESTART_DET + 0x000000a8 + Clear RESTART_DET Interrupt Register + 0x00000000 + + + CLR_RESTART_DET + Read this register to clear the RESTART_DET interrupt (bit 12) of IC_RAW_INTR_STAT register. + + Reset value: 0x0 + [0:0] + read-only + + + + + IC_COMP_PARAM_1 + 0x000000f4 + Component Parameter Register 1 + + Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters + 0x00000000 + + + TX_BUFFER_DEPTH + TX Buffer Depth = 16 + [23:16] + read-only + + + RX_BUFFER_DEPTH + RX Buffer Depth = 16 + [15:8] + read-only + + + ADD_ENCODED_PARAMS + Encoded parameters not visible + [7:7] + read-only + + + HAS_DMA + DMA handshaking signals are enabled + [6:6] + read-only + + + INTR_IO + COMBINED Interrupt outputs + [5:5] + read-only + + + HC_COUNT_VALUES + Programmable count values for each mode. + [4:4] + read-only + + + MAX_SPEED_MODE + MAX SPEED MODE = FAST MODE + [3:2] + read-only + + + APB_DATA_WIDTH + APB data bus width is 32 bits + [1:0] + read-only + + + + + IC_COMP_VERSION + 0x000000f8 + I2C Component Version Register + 0x3230312a + + + IC_COMP_VERSION + [31:0] + read-only + + + + + IC_COMP_TYPE + 0x000000fc + I2C Component Type Register + 0x44570140 + + + IC_COMP_TYPE + Designware Component Type number = 0x44_57_01_40. This assigned unique hex value is constant and is derived from the two ASCII letters 'DW' followed by a 16-bit unsigned number. + [31:0] + read-only + + + + + + + I2C1 + 0x40048000 + + I2C1_IRQ + 24 + + + + SPI0 + 0x4003c000 + + 0 + 4096 + registers + + + SPI0_IRQ + 18 + + + + SSPCR0 + 0x00000000 + Control register 0, SSPCR0 on page 3-4 + 0x00000000 + + + SCR + Serial clock rate. The value SCR is used to generate the transmit and receive bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and SCR is a value from 0-255. + [15:8] + read-write + + + SPH + SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + [7:7] + read-write + + + SPO + SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + [6:6] + read-write + + + FRF + Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame format. 10 National Microwire frame format. 11 Reserved, undefined operation. + [5:4] + read-write + + + DSS + Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. 1110 15-bit data. 1111 16-bit data. + [3:0] + read-write + + + + + SSPCR1 + 0x00000004 + Control register 1, SSPCR1 on page 3-5 + 0x00000000 + + + SOD + Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast a message to all slaves in the system while ensuring that only one slave drives data onto its serial output line. In such systems the RXD lines from multiple slaves could be tied together. To operate in such systems, the SOD bit can be set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD output in slave mode. + [3:3] + read-write + + + MS + Master or slave mode select. This bit can be modified only when the PrimeCell SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device configured as slave. + [2:2] + read-write + + + SSE + Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation enabled. + [1:1] + read-write + + + LBM + Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit serial shifter is connected to input of receive serial shifter internally. + [0:0] + read-write + + + + + SSPDR + 0x00000008 + Data register, SSPDR on page 3-6 + 0x00000000 + + + DATA + Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must right-justify data when the PrimeCell SSP is programmed for a data size that is less than 16 bits. Unused bits at the top are ignored by transmit logic. The receive logic automatically right-justifies. + [15:0] + read-write + modify + + + + + SSPSR + 0x0000000c + Status register, SSPSR on page 3-7 + 0x00000003 + + + BSY + PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting and/or receiving a frame or the transmit FIFO is not empty. + [4:4] + read-only + + + RFF + Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. + [3:3] + read-only + + + RNE + Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not empty. + [2:2] + read-only + + + TNF + Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not full. + [1:1] + read-only + + + TFE + Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. + [0:0] + read-only + + + + + SSPCPSR + 0x00000010 + Clock prescale register, SSPCPSR on page 3-8 + 0x00000000 + + + CPSDVSR + Clock prescale divisor. Must be an even number from 2-254, depending on the frequency of SSPCLK. The least significant bit always returns zero on reads. + [7:0] + read-write + + + + + SSPIMSC + 0x00000014 + Interrupt mask set or clear register, SSPIMSC on page 3-9 + 0x00000000 + + + TXIM + Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is not masked. + [3:3] + read-write + + + RXIM + Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not masked. + [2:2] + read-write + + + RTIM + Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior to timeout period interrupt is not masked. + [1:1] + read-write + + + RORIM + Receive overrun interrupt mask: 0 Receive FIFO written to while full condition interrupt is masked. 1 Receive FIFO written to while full condition interrupt is not masked. + [0:0] + read-write + + + + + SSPRIS + 0x00000018 + Raw interrupt status register, SSPRIS on page 3-10 + 0x00000008 + + + TXRIS + Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt + [3:3] + read-only + + + RXRIS + Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt + [2:2] + read-only + + + RTRIS + Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt + [1:1] + read-only + + + RORRIS + Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt + [0:0] + read-only + + + + + SSPMIS + 0x0000001c + Masked interrupt status register, SSPMIS on page 3-11 + 0x00000000 + + + TXMIS + Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt + [3:3] + read-only + + + RXMIS + Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt + [2:2] + read-only + + + RTMIS + Gives the receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt + [1:1] + read-only + + + RORMIS + Gives the receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt + [0:0] + read-only + + + + + SSPICR + 0x00000020 + Interrupt clear register, SSPICR on page 3-11 + 0x00000000 + + + RTIC + Clears the SSPRTINTR interrupt + [1:1] + read-write + oneToClear + + + RORIC + Clears the SSPRORINTR interrupt + [0:0] + read-write + oneToClear + + + + + SSPDMACR + 0x00000024 + DMA control register, SSPDMACR on page 3-12 + 0x00000000 + + + TXDMAE + Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + [1:1] + read-write + + + RXDMAE + Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is enabled. + [0:0] + read-write + + + + + SSPPERIPHID0 + 0x00000fe0 + Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + 0x00000022 + + + PARTNUMBER0 + These bits read back as 0x22 + [7:0] + read-only + + + + + SSPPERIPHID1 + 0x00000fe4 + Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + 0x00000010 + + + DESIGNER0 + These bits read back as 0x1 + [7:4] + read-only + + + PARTNUMBER1 + These bits read back as 0x0 + [3:0] + read-only + + + + + SSPPERIPHID2 + 0x00000fe8 + Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + 0x00000034 + + + REVISION + These bits return the peripheral revision + [7:4] + read-only + + + DESIGNER1 + These bits read back as 0x4 + [3:0] + read-only + + + + + SSPPERIPHID3 + 0x00000fec + Peripheral identification registers, SSPPeriphID0-3 on page 3-13 + 0x00000000 + + + CONFIGURATION + These bits read back as 0x00 + [7:0] + read-only + + + + + SSPPCELLID0 + 0x00000ff0 + PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + 0x0000000d + + + SSPPCELLID0 + These bits read back as 0x0D + [7:0] + read-only + + + + + SSPPCELLID1 + 0x00000ff4 + PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + 0x000000f0 + + + SSPPCELLID1 + These bits read back as 0xF0 + [7:0] + read-only + + + + + SSPPCELLID2 + 0x00000ff8 + PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + 0x00000005 + + + SSPPCELLID2 + These bits read back as 0x05 + [7:0] + read-only + + + + + SSPPCELLID3 + 0x00000ffc + PrimeCell identification registers, SSPPCellID0-3 on page 3-16 + 0x000000b1 + + + SSPPCELLID3 + These bits read back as 0xB1 + [7:0] + read-only + + + + + + + SPI1 + 0x40040000 + + SPI1_IRQ + 19 + + + + PIO0 + Programmable IO block + 0x50200000 + + 0 + 324 + registers + + + PIO0_IRQ_0 + 7 + + + PIO0_IRQ_1 + 8 + + + + CTRL + 0x00000000 + PIO control register + 0x00000000 + + + CLKDIV_RESTART + Restart a state machine's clock divider from an initial phase of 0. Clock dividers are free-running, so once started, their output (including fractional jitter) is completely determined by the integer/fractional divisor configured in SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor are restarted simultaneously, by writing multiple 1 bits to this field, the execution clocks of those state machines will run in precise lockstep. + + Note that setting/clearing SM_ENABLE does not stop the clock divider from running, so once multiple state machines' clocks are synchronised, it is safe to disable/reenable a state machine, whilst keeping the clock dividers in sync. + + Note also that CLKDIV_RESTART can be written to whilst the state machine is running, and this is useful to resynchronise clock dividers after the divisors (SMx_CLKDIV) have been changed on-the-fly. + [11:8] + write-only + + + SM_RESTART + Write 1 to instantly clear internal SM state which may be otherwise difficult to access and will affect future execution. + + Specifically, the following are cleared: input and output shift counters; the contents of the input shift register; the delay counter; the waiting-on-IRQ state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any pin write left asserted due to OUT_STICKY. + + The program counter, the contents of the output shift register and the X/Y scratch registers are not affected. + [7:4] + write-only + + + SM_ENABLE + Enable/disable each of the four state machines by writing 1/0 to each of these four bits. When disabled, a state machine will cease executing instructions, except those written directly to SMx_INSTR by the system. Multiple bits can be set/cleared at once to run/halt multiple state machines simultaneously. + [3:0] + read-write + + + + + FSTAT + 0x00000004 + FIFO status register + 0x0f000f00 + + + TXEMPTY + State machine TX FIFO is empty + [27:24] + read-only + + + TXFULL + State machine TX FIFO is full + [19:16] + read-only + + + RXEMPTY + State machine RX FIFO is empty + [11:8] + read-only + + + RXFULL + State machine RX FIFO is full + [3:0] + read-only + + + + + FDEBUG + 0x00000008 + FIFO debug register + 0x00000000 + + + TXSTALL + State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT with autopull enabled. Write 1 to clear. + [27:24] + read-write + oneToClear + + + TXOVER + TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to clear. Note that write-on-full does not alter the state or contents of the FIFO in any way, but the data that the system attempted to write is dropped, so if this flag is set, your software has quite likely dropped some data on the floor. + [19:16] + read-write + oneToClear + + + RXUNDER + RX FIFO underflow (i.e. read-on-empty by the system) has occurred. Write 1 to clear. Note that read-on-empty does not perturb the state of the FIFO in any way, but the data returned by reading from an empty FIFO is undefined, so this flag generally only becomes set due to some kind of software error. + [11:8] + read-write + oneToClear + + + RXSTALL + State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO took place, in which case the state machine has dropped data. Write 1 to clear. + [3:0] + read-write + oneToClear + + + + + FLEVEL + 0x0000000c + FIFO levels + 0x00000000 + + + RX3 + [31:28] + read-only + + + TX3 + [27:24] + read-only + + + RX2 + [23:20] + read-only + + + TX2 + [19:16] + read-only + + + RX1 + [15:12] + read-only + + + TX1 + [11:8] + read-only + + + RX0 + [7:4] + read-only + + + TX0 + [3:0] + read-only + + + + + TXF0 + 0x00000010 + Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + 0x00000000 + + + TXF0 + [31:0] + write-only + + + + + TXF1 + 0x00000014 + Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + 0x00000000 + + + TXF1 + [31:0] + write-only + + + + + TXF2 + 0x00000018 + Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + 0x00000000 + + + TXF2 + [31:0] + write-only + + + + + TXF3 + 0x0000001c + Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. + 0x00000000 + + + TXF3 + [31:0] + write-only + + + + + RXF0 + 0x00000020 + Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + 0x00000000 + + + RXF0 + [31:0] + read-only + modify + + + + + RXF1 + 0x00000024 + Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + 0x00000000 + + + RXF1 + [31:0] + read-only + modify + + + + + RXF2 + 0x00000028 + Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + 0x00000000 + + + RXF2 + [31:0] + read-only + modify + + + + + RXF3 + 0x0000002c + Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. + 0x00000000 + + + RXF3 + [31:0] + read-only + modify + + + + + IRQ + 0x00000030 + State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag. + + Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE. + 0x00000000 + + + IRQ + [7:0] + read-write + oneToClear + + + + + IRQ_FORCE + 0x00000034 + Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. + 0x00000000 + + + IRQ_FORCE + [7:0] + write-only + + + + + INPUT_SYNC_BYPASS + 0x00000038 + There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. + 0 -> input is synchronized (default) + 1 -> synchronizer is bypassed + If in doubt, leave this register as all zeroes. + 0x00000000 + + + INPUT_SYNC_BYPASS + [31:0] + read-write + + + + + DBG_PADOUT + 0x0000003c + Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + 0x00000000 + + + DBG_PADOUT + [31:0] + read-only + + + + + DBG_PADOE + 0x00000040 + Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. + 0x00000000 + + + DBG_PADOE + [31:0] + read-only + + + + + DBG_CFGINFO + 0x00000044 + The PIO hardware has some free parameters that may vary between chip products. + These should be provided in the chip datasheet, but are also exposed here. + 0x00000000 + + + IMEM_SIZE + The size of the instruction memory, measured in units of one instruction + [21:16] + read-only + + + SM_COUNT + The number of state machines this PIO instance is equipped with. + [11:8] + read-only + + + FIFO_DEPTH + The depth of the state machine TX/RX FIFOs, measured in words. + Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double + this depth. + [5:0] + read-only + + + + + INSTR_MEM0 + 0x00000048 + Write-only access to instruction memory location 0 + 0x00000000 + + + INSTR_MEM0 + [15:0] + write-only + + + + + INSTR_MEM1 + 0x0000004c + Write-only access to instruction memory location 1 + 0x00000000 + + + INSTR_MEM1 + [15:0] + write-only + + + + + INSTR_MEM2 + 0x00000050 + Write-only access to instruction memory location 2 + 0x00000000 + + + INSTR_MEM2 + [15:0] + write-only + + + + + INSTR_MEM3 + 0x00000054 + Write-only access to instruction memory location 3 + 0x00000000 + + + INSTR_MEM3 + [15:0] + write-only + + + + + INSTR_MEM4 + 0x00000058 + Write-only access to instruction memory location 4 + 0x00000000 + + + INSTR_MEM4 + [15:0] + write-only + + + + + INSTR_MEM5 + 0x0000005c + Write-only access to instruction memory location 5 + 0x00000000 + + + INSTR_MEM5 + [15:0] + write-only + + + + + INSTR_MEM6 + 0x00000060 + Write-only access to instruction memory location 6 + 0x00000000 + + + INSTR_MEM6 + [15:0] + write-only + + + + + INSTR_MEM7 + 0x00000064 + Write-only access to instruction memory location 7 + 0x00000000 + + + INSTR_MEM7 + [15:0] + write-only + + + + + INSTR_MEM8 + 0x00000068 + Write-only access to instruction memory location 8 + 0x00000000 + + + INSTR_MEM8 + [15:0] + write-only + + + + + INSTR_MEM9 + 0x0000006c + Write-only access to instruction memory location 9 + 0x00000000 + + + INSTR_MEM9 + [15:0] + write-only + + + + + INSTR_MEM10 + 0x00000070 + Write-only access to instruction memory location 10 + 0x00000000 + + + INSTR_MEM10 + [15:0] + write-only + + + + + INSTR_MEM11 + 0x00000074 + Write-only access to instruction memory location 11 + 0x00000000 + + + INSTR_MEM11 + [15:0] + write-only + + + + + INSTR_MEM12 + 0x00000078 + Write-only access to instruction memory location 12 + 0x00000000 + + + INSTR_MEM12 + [15:0] + write-only + + + + + INSTR_MEM13 + 0x0000007c + Write-only access to instruction memory location 13 + 0x00000000 + + + INSTR_MEM13 + [15:0] + write-only + + + + + INSTR_MEM14 + 0x00000080 + Write-only access to instruction memory location 14 + 0x00000000 + + + INSTR_MEM14 + [15:0] + write-only + + + + + INSTR_MEM15 + 0x00000084 + Write-only access to instruction memory location 15 + 0x00000000 + + + INSTR_MEM15 + [15:0] + write-only + + + + + INSTR_MEM16 + 0x00000088 + Write-only access to instruction memory location 16 + 0x00000000 + + + INSTR_MEM16 + [15:0] + write-only + + + + + INSTR_MEM17 + 0x0000008c + Write-only access to instruction memory location 17 + 0x00000000 + + + INSTR_MEM17 + [15:0] + write-only + + + + + INSTR_MEM18 + 0x00000090 + Write-only access to instruction memory location 18 + 0x00000000 + + + INSTR_MEM18 + [15:0] + write-only + + + + + INSTR_MEM19 + 0x00000094 + Write-only access to instruction memory location 19 + 0x00000000 + + + INSTR_MEM19 + [15:0] + write-only + + + + + INSTR_MEM20 + 0x00000098 + Write-only access to instruction memory location 20 + 0x00000000 + + + INSTR_MEM20 + [15:0] + write-only + + + + + INSTR_MEM21 + 0x0000009c + Write-only access to instruction memory location 21 + 0x00000000 + + + INSTR_MEM21 + [15:0] + write-only + + + + + INSTR_MEM22 + 0x000000a0 + Write-only access to instruction memory location 22 + 0x00000000 + + + INSTR_MEM22 + [15:0] + write-only + + + + + INSTR_MEM23 + 0x000000a4 + Write-only access to instruction memory location 23 + 0x00000000 + + + INSTR_MEM23 + [15:0] + write-only + + + + + INSTR_MEM24 + 0x000000a8 + Write-only access to instruction memory location 24 + 0x00000000 + + + INSTR_MEM24 + [15:0] + write-only + + + + + INSTR_MEM25 + 0x000000ac + Write-only access to instruction memory location 25 + 0x00000000 + + + INSTR_MEM25 + [15:0] + write-only + + + + + INSTR_MEM26 + 0x000000b0 + Write-only access to instruction memory location 26 + 0x00000000 + + + INSTR_MEM26 + [15:0] + write-only + + + + + INSTR_MEM27 + 0x000000b4 + Write-only access to instruction memory location 27 + 0x00000000 + + + INSTR_MEM27 + [15:0] + write-only + + + + + INSTR_MEM28 + 0x000000b8 + Write-only access to instruction memory location 28 + 0x00000000 + + + INSTR_MEM28 + [15:0] + write-only + + + + + INSTR_MEM29 + 0x000000bc + Write-only access to instruction memory location 29 + 0x00000000 + + + INSTR_MEM29 + [15:0] + write-only + + + + + INSTR_MEM30 + 0x000000c0 + Write-only access to instruction memory location 30 + 0x00000000 + + + INSTR_MEM30 + [15:0] + write-only + + + + + INSTR_MEM31 + 0x000000c4 + Write-only access to instruction memory location 31 + 0x00000000 + + + INSTR_MEM31 + [15:0] + write-only + + + + + SM0_CLKDIV + 0x000000c8 + Clock divisor register for state machine 0 + Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + 0x00010000 + + + INT + Effective frequency is sysclk/(int + frac/256). + Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + [31:16] + read-write + + + FRAC + Fractional part of clock divisor + [15:8] + read-write + + + + + SM0_EXECCTRL + 0x000000cc + Execution/behavioural settings for state machine 0 + 0x0001f000 + + + EXEC_STALLED + If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + [31:31] + read-only + + + SIDE_EN + If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + [30:30] + read-write + + + SIDE_PINDIR + If 1, side-set data is asserted to pin directions, instead of pin values + [29:29] + read-write + + + JMP_PIN + The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + [28:24] + read-write + + + OUT_EN_SEL + Which data bit to use for inline OUT enable + [23:19] + read-write + + + INLINE_OUT_EN + If 1, use a bit of OUT data as an auxiliary write enable + When used in conjunction with OUT_STICKY, writes with an enable of 0 will + deassert the latest pin write. This can create useful masking/override behaviour + due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + [18:18] + read-write + + + OUT_STICKY + Continuously assert the most recent OUT/SET to the pins + [17:17] + read-write + + + WRAP_TOP + After reaching this address, execution is wrapped to wrap_bottom. + If the instruction is a jump, and the jump condition is true, the jump takes priority. + [16:12] + read-write + + + WRAP_BOTTOM + After reaching wrap_top, execution is wrapped to this address. + [11:7] + read-write + + + STATUS_SEL + Comparison used for the MOV x, STATUS instruction. + [4:4] + read-write + + + TXLEVEL + 0 + All-ones if TX FIFO level < N, otherwise all-zeroes + + + RXLEVEL + 1 + All-ones if RX FIFO level < N, otherwise all-zeroes + + + + + STATUS_N + Comparison level for the MOV x, STATUS instruction + [3:0] + read-write + + + + + SM0_SHIFTCTRL + 0x000000d0 + Control behaviour of the input/output shift registers for state machine 0 + 0x000c0000 + + + FJOIN_RX + When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + TX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [31:31] + read-write + + + FJOIN_TX + When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + RX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [30:30] + read-write + + + PULL_THRESH + Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + Write 0 for value of 32. + [29:25] + read-write + + + PUSH_THRESH + Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + Write 0 for value of 32. + [24:20] + read-write + + + OUT_SHIFTDIR + 1 = shift out of output shift register to right. 0 = to left. + [19:19] + read-write + + + IN_SHIFTDIR + 1 = shift input shift register to right (data enters from left). 0 = to left. + [18:18] + read-write + + + AUTOPULL + Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + [17:17] + read-write + + + AUTOPUSH + Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + [16:16] + read-write + + + + + SM0_ADDR + 0x000000d4 + Current instruction address of state machine 0 + 0x00000000 + + + SM0_ADDR + [4:0] + read-only + + + + + SM0_INSTR + 0x000000d8 + Read to see the instruction currently addressed by state machine 0's program counter + Write to execute an instruction immediately (including jumps) and then resume execution. + 0x00000000 + + + SM0_INSTR + [15:0] + read-write + + + + + SM0_PINCTRL + 0x000000dc + State machine pin control + 0x14000000 + + + SIDESET_COUNT + The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + [31:29] + read-write + + + SET_COUNT + The number of pins asserted by a SET. In the range 0 to 5 inclusive. + [28:26] + read-write + + + OUT_COUNT + The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + [25:20] + read-write + + + IN_BASE + The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + [19:15] + read-write + + + SIDESET_BASE + The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + [14:10] + read-write + + + SET_BASE + The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + [9:5] + read-write + + + OUT_BASE + The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + [4:0] + read-write + + + + + SM1_CLKDIV + 0x000000e0 + Clock divisor register for state machine 1 + Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + 0x00010000 + + + INT + Effective frequency is sysclk/(int + frac/256). + Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + [31:16] + read-write + + + FRAC + Fractional part of clock divisor + [15:8] + read-write + + + + + SM1_EXECCTRL + 0x000000e4 + Execution/behavioural settings for state machine 1 + 0x0001f000 + + + EXEC_STALLED + If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + [31:31] + read-only + + + SIDE_EN + If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + [30:30] + read-write + + + SIDE_PINDIR + If 1, side-set data is asserted to pin directions, instead of pin values + [29:29] + read-write + + + JMP_PIN + The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + [28:24] + read-write + + + OUT_EN_SEL + Which data bit to use for inline OUT enable + [23:19] + read-write + + + INLINE_OUT_EN + If 1, use a bit of OUT data as an auxiliary write enable + When used in conjunction with OUT_STICKY, writes with an enable of 0 will + deassert the latest pin write. This can create useful masking/override behaviour + due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + [18:18] + read-write + + + OUT_STICKY + Continuously assert the most recent OUT/SET to the pins + [17:17] + read-write + + + WRAP_TOP + After reaching this address, execution is wrapped to wrap_bottom. + If the instruction is a jump, and the jump condition is true, the jump takes priority. + [16:12] + read-write + + + WRAP_BOTTOM + After reaching wrap_top, execution is wrapped to this address. + [11:7] + read-write + + + STATUS_SEL + Comparison used for the MOV x, STATUS instruction. + [4:4] + read-write + + + TXLEVEL + 0 + All-ones if TX FIFO level < N, otherwise all-zeroes + + + RXLEVEL + 1 + All-ones if RX FIFO level < N, otherwise all-zeroes + + + + + STATUS_N + Comparison level for the MOV x, STATUS instruction + [3:0] + read-write + + + + + SM1_SHIFTCTRL + 0x000000e8 + Control behaviour of the input/output shift registers for state machine 1 + 0x000c0000 + + + FJOIN_RX + When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + TX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [31:31] + read-write + + + FJOIN_TX + When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + RX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [30:30] + read-write + + + PULL_THRESH + Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + Write 0 for value of 32. + [29:25] + read-write + + + PUSH_THRESH + Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + Write 0 for value of 32. + [24:20] + read-write + + + OUT_SHIFTDIR + 1 = shift out of output shift register to right. 0 = to left. + [19:19] + read-write + + + IN_SHIFTDIR + 1 = shift input shift register to right (data enters from left). 0 = to left. + [18:18] + read-write + + + AUTOPULL + Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + [17:17] + read-write + + + AUTOPUSH + Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + [16:16] + read-write + + + + + SM1_ADDR + 0x000000ec + Current instruction address of state machine 1 + 0x00000000 + + + SM1_ADDR + [4:0] + read-only + + + + + SM1_INSTR + 0x000000f0 + Read to see the instruction currently addressed by state machine 1's program counter + Write to execute an instruction immediately (including jumps) and then resume execution. + 0x00000000 + + + SM1_INSTR + [15:0] + read-write + + + + + SM1_PINCTRL + 0x000000f4 + State machine pin control + 0x14000000 + + + SIDESET_COUNT + The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + [31:29] + read-write + + + SET_COUNT + The number of pins asserted by a SET. In the range 0 to 5 inclusive. + [28:26] + read-write + + + OUT_COUNT + The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + [25:20] + read-write + + + IN_BASE + The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + [19:15] + read-write + + + SIDESET_BASE + The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + [14:10] + read-write + + + SET_BASE + The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + [9:5] + read-write + + + OUT_BASE + The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + [4:0] + read-write + + + + + SM2_CLKDIV + 0x000000f8 + Clock divisor register for state machine 2 + Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + 0x00010000 + + + INT + Effective frequency is sysclk/(int + frac/256). + Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + [31:16] + read-write + + + FRAC + Fractional part of clock divisor + [15:8] + read-write + + + + + SM2_EXECCTRL + 0x000000fc + Execution/behavioural settings for state machine 2 + 0x0001f000 + + + EXEC_STALLED + If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + [31:31] + read-only + + + SIDE_EN + If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + [30:30] + read-write + + + SIDE_PINDIR + If 1, side-set data is asserted to pin directions, instead of pin values + [29:29] + read-write + + + JMP_PIN + The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + [28:24] + read-write + + + OUT_EN_SEL + Which data bit to use for inline OUT enable + [23:19] + read-write + + + INLINE_OUT_EN + If 1, use a bit of OUT data as an auxiliary write enable + When used in conjunction with OUT_STICKY, writes with an enable of 0 will + deassert the latest pin write. This can create useful masking/override behaviour + due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + [18:18] + read-write + + + OUT_STICKY + Continuously assert the most recent OUT/SET to the pins + [17:17] + read-write + + + WRAP_TOP + After reaching this address, execution is wrapped to wrap_bottom. + If the instruction is a jump, and the jump condition is true, the jump takes priority. + [16:12] + read-write + + + WRAP_BOTTOM + After reaching wrap_top, execution is wrapped to this address. + [11:7] + read-write + + + STATUS_SEL + Comparison used for the MOV x, STATUS instruction. + [4:4] + read-write + + + TXLEVEL + 0 + All-ones if TX FIFO level < N, otherwise all-zeroes + + + RXLEVEL + 1 + All-ones if RX FIFO level < N, otherwise all-zeroes + + + + + STATUS_N + Comparison level for the MOV x, STATUS instruction + [3:0] + read-write + + + + + SM2_SHIFTCTRL + 0x00000100 + Control behaviour of the input/output shift registers for state machine 2 + 0x000c0000 + + + FJOIN_RX + When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + TX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [31:31] + read-write + + + FJOIN_TX + When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + RX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [30:30] + read-write + + + PULL_THRESH + Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + Write 0 for value of 32. + [29:25] + read-write + + + PUSH_THRESH + Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + Write 0 for value of 32. + [24:20] + read-write + + + OUT_SHIFTDIR + 1 = shift out of output shift register to right. 0 = to left. + [19:19] + read-write + + + IN_SHIFTDIR + 1 = shift input shift register to right (data enters from left). 0 = to left. + [18:18] + read-write + + + AUTOPULL + Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + [17:17] + read-write + + + AUTOPUSH + Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + [16:16] + read-write + + + + + SM2_ADDR + 0x00000104 + Current instruction address of state machine 2 + 0x00000000 + + + SM2_ADDR + [4:0] + read-only + + + + + SM2_INSTR + 0x00000108 + Read to see the instruction currently addressed by state machine 2's program counter + Write to execute an instruction immediately (including jumps) and then resume execution. + 0x00000000 + + + SM2_INSTR + [15:0] + read-write + + + + + SM2_PINCTRL + 0x0000010c + State machine pin control + 0x14000000 + + + SIDESET_COUNT + The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + [31:29] + read-write + + + SET_COUNT + The number of pins asserted by a SET. In the range 0 to 5 inclusive. + [28:26] + read-write + + + OUT_COUNT + The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + [25:20] + read-write + + + IN_BASE + The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + [19:15] + read-write + + + SIDESET_BASE + The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + [14:10] + read-write + + + SET_BASE + The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + [9:5] + read-write + + + OUT_BASE + The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + [4:0] + read-write + + + + + SM3_CLKDIV + 0x00000110 + Clock divisor register for state machine 3 + Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + 0x00010000 + + + INT + Effective frequency is sysclk/(int + frac/256). + Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0. + [31:16] + read-write + + + FRAC + Fractional part of clock divisor + [15:8] + read-write + + + + + SM3_EXECCTRL + 0x00000114 + Execution/behavioural settings for state machine 3 + 0x0001f000 + + + EXEC_STALLED + If 1, an instruction written to SMx_INSTR is stalled, and latched by the state machine. Will clear to 0 once this instruction completes. + [31:31] + read-only + + + SIDE_EN + If 1, the MSB of the Delay/Side-set instruction field is used as side-set enable, rather than a side-set data bit. This allows instructions to perform side-set optionally, rather than on every instruction, but the maximum possible side-set width is reduced from 5 to 4. Note that the value of PINCTRL_SIDESET_COUNT is inclusive of this enable bit. + [30:30] + read-write + + + SIDE_PINDIR + If 1, side-set data is asserted to pin directions, instead of pin values + [29:29] + read-write + + + JMP_PIN + The GPIO number to use as condition for JMP PIN. Unaffected by input mapping. + [28:24] + read-write + + + OUT_EN_SEL + Which data bit to use for inline OUT enable + [23:19] + read-write + + + INLINE_OUT_EN + If 1, use a bit of OUT data as an auxiliary write enable + When used in conjunction with OUT_STICKY, writes with an enable of 0 will + deassert the latest pin write. This can create useful masking/override behaviour + due to the priority ordering of state machine pin writes (SM0 < SM1 < ...) + [18:18] + read-write + + + OUT_STICKY + Continuously assert the most recent OUT/SET to the pins + [17:17] + read-write + + + WRAP_TOP + After reaching this address, execution is wrapped to wrap_bottom. + If the instruction is a jump, and the jump condition is true, the jump takes priority. + [16:12] + read-write + + + WRAP_BOTTOM + After reaching wrap_top, execution is wrapped to this address. + [11:7] + read-write + + + STATUS_SEL + Comparison used for the MOV x, STATUS instruction. + [4:4] + read-write + + + TXLEVEL + 0 + All-ones if TX FIFO level < N, otherwise all-zeroes + + + RXLEVEL + 1 + All-ones if RX FIFO level < N, otherwise all-zeroes + + + + + STATUS_N + Comparison level for the MOV x, STATUS instruction + [3:0] + read-write + + + + + SM3_SHIFTCTRL + 0x00000118 + Control behaviour of the input/output shift registers for state machine 3 + 0x000c0000 + + + FJOIN_RX + When 1, RX FIFO steals the TX FIFO's storage, and becomes twice as deep. + TX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [31:31] + read-write + + + FJOIN_TX + When 1, TX FIFO steals the RX FIFO's storage, and becomes twice as deep. + RX FIFO is disabled as a result (always reads as both full and empty). + FIFOs are flushed when this bit is changed. + [30:30] + read-write + + + PULL_THRESH + Number of bits shifted out of OSR before autopull, or conditional pull (PULL IFEMPTY), will take place. + Write 0 for value of 32. + [29:25] + read-write + + + PUSH_THRESH + Number of bits shifted into ISR before autopush, or conditional push (PUSH IFFULL), will take place. + Write 0 for value of 32. + [24:20] + read-write + + + OUT_SHIFTDIR + 1 = shift out of output shift register to right. 0 = to left. + [19:19] + read-write + + + IN_SHIFTDIR + 1 = shift input shift register to right (data enters from left). 0 = to left. + [18:18] + read-write + + + AUTOPULL + Pull automatically when the output shift register is emptied, i.e. on or following an OUT instruction which causes the output shift counter to reach or exceed PULL_THRESH. + [17:17] + read-write + + + AUTOPUSH + Push automatically when the input shift register is filled, i.e. on an IN instruction which causes the input shift counter to reach or exceed PUSH_THRESH. + [16:16] + read-write + + + + + SM3_ADDR + 0x0000011c + Current instruction address of state machine 3 + 0x00000000 + + + SM3_ADDR + [4:0] + read-only + + + + + SM3_INSTR + 0x00000120 + Read to see the instruction currently addressed by state machine 3's program counter + Write to execute an instruction immediately (including jumps) and then resume execution. + 0x00000000 + + + SM3_INSTR + [15:0] + read-write + + + + + SM3_PINCTRL + 0x00000124 + State machine pin control + 0x14000000 + + + SIDESET_COUNT + The number of MSBs of the Delay/Side-set instruction field which are used for side-set. Inclusive of the enable bit, if present. Minimum of 0 (all delay bits, no side-set) and maximum of 5 (all side-set, no delay). + [31:29] + read-write + + + SET_COUNT + The number of pins asserted by a SET. In the range 0 to 5 inclusive. + [28:26] + read-write + + + OUT_COUNT + The number of pins asserted by an OUT PINS, OUT PINDIRS or MOV PINS instruction. In the range 0 to 32 inclusive. + [25:20] + read-write + + + IN_BASE + The pin which is mapped to the least-significant bit of a state machine's IN data bus. Higher-numbered pins are mapped to consecutively more-significant data bits, with a modulo of 32 applied to pin number. + [19:15] + read-write + + + SIDESET_BASE + The lowest-numbered pin that will be affected by a side-set operation. The MSBs of an instruction's side-set/delay field (up to 5, determined by SIDESET_COUNT) are used for side-set data, with the remaining LSBs used for delay. The least-significant bit of the side-set portion is the bit written to this pin, with more-significant bits written to higher-numbered pins. + [14:10] + read-write + + + SET_BASE + The lowest-numbered pin that will be affected by a SET PINS or SET PINDIRS instruction. The data written to this pin is the least-significant bit of the SET data. + [9:5] + read-write + + + OUT_BASE + The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. + [4:0] + read-write + + + + + INTR + 0x00000128 + Raw Interrupts + 0x00000000 + + + SM3 + [11:11] + read-only + + + SM2 + [10:10] + read-only + + + SM1 + [9:9] + read-only + + + SM0 + [8:8] + read-only + + + SM3_TXNFULL + [7:7] + read-only + + + SM2_TXNFULL + [6:6] + read-only + + + SM1_TXNFULL + [5:5] + read-only + + + SM0_TXNFULL + [4:4] + read-only + + + SM3_RXNEMPTY + [3:3] + read-only + + + SM2_RXNEMPTY + [2:2] + read-only + + + SM1_RXNEMPTY + [1:1] + read-only + + + SM0_RXNEMPTY + [0:0] + read-only + + + + + IRQ0_INTE + 0x0000012c + Interrupt Enable for irq0 + 0x00000000 + + + SM3 + [11:11] + read-write + + + SM2 + [10:10] + read-write + + + SM1 + [9:9] + read-write + + + SM0 + [8:8] + read-write + + + SM3_TXNFULL + [7:7] + read-write + + + SM2_TXNFULL + [6:6] + read-write + + + SM1_TXNFULL + [5:5] + read-write + + + SM0_TXNFULL + [4:4] + read-write + + + SM3_RXNEMPTY + [3:3] + read-write + + + SM2_RXNEMPTY + [2:2] + read-write + + + SM1_RXNEMPTY + [1:1] + read-write + + + SM0_RXNEMPTY + [0:0] + read-write + + + + + IRQ0_INTF + 0x00000130 + Interrupt Force for irq0 + 0x00000000 + + + SM3 + [11:11] + read-write + + + SM2 + [10:10] + read-write + + + SM1 + [9:9] + read-write + + + SM0 + [8:8] + read-write + + + SM3_TXNFULL + [7:7] + read-write + + + SM2_TXNFULL + [6:6] + read-write + + + SM1_TXNFULL + [5:5] + read-write + + + SM0_TXNFULL + [4:4] + read-write + + + SM3_RXNEMPTY + [3:3] + read-write + + + SM2_RXNEMPTY + [2:2] + read-write + + + SM1_RXNEMPTY + [1:1] + read-write + + + SM0_RXNEMPTY + [0:0] + read-write + + + + + IRQ0_INTS + 0x00000134 + Interrupt status after masking & forcing for irq0 + 0x00000000 + + + SM3 + [11:11] + read-only + + + SM2 + [10:10] + read-only + + + SM1 + [9:9] + read-only + + + SM0 + [8:8] + read-only + + + SM3_TXNFULL + [7:7] + read-only + + + SM2_TXNFULL + [6:6] + read-only + + + SM1_TXNFULL + [5:5] + read-only + + + SM0_TXNFULL + [4:4] + read-only + + + SM3_RXNEMPTY + [3:3] + read-only + + + SM2_RXNEMPTY + [2:2] + read-only + + + SM1_RXNEMPTY + [1:1] + read-only + + + SM0_RXNEMPTY + [0:0] + read-only + + + + + IRQ1_INTE + 0x00000138 + Interrupt Enable for irq1 + 0x00000000 + + + SM3 + [11:11] + read-write + + + SM2 + [10:10] + read-write + + + SM1 + [9:9] + read-write + + + SM0 + [8:8] + read-write + + + SM3_TXNFULL + [7:7] + read-write + + + SM2_TXNFULL + [6:6] + read-write + + + SM1_TXNFULL + [5:5] + read-write + + + SM0_TXNFULL + [4:4] + read-write + + + SM3_RXNEMPTY + [3:3] + read-write + + + SM2_RXNEMPTY + [2:2] + read-write + + + SM1_RXNEMPTY + [1:1] + read-write + + + SM0_RXNEMPTY + [0:0] + read-write + + + + + IRQ1_INTF + 0x0000013c + Interrupt Force for irq1 + 0x00000000 + + + SM3 + [11:11] + read-write + + + SM2 + [10:10] + read-write + + + SM1 + [9:9] + read-write + + + SM0 + [8:8] + read-write + + + SM3_TXNFULL + [7:7] + read-write + + + SM2_TXNFULL + [6:6] + read-write + + + SM1_TXNFULL + [5:5] + read-write + + + SM0_TXNFULL + [4:4] + read-write + + + SM3_RXNEMPTY + [3:3] + read-write + + + SM2_RXNEMPTY + [2:2] + read-write + + + SM1_RXNEMPTY + [1:1] + read-write + + + SM0_RXNEMPTY + [0:0] + read-write + + + + + IRQ1_INTS + 0x00000140 + Interrupt status after masking & forcing for irq1 + 0x00000000 + + + SM3 + [11:11] + read-only + + + SM2 + [10:10] + read-only + + + SM1 + [9:9] + read-only + + + SM0 + [8:8] + read-only + + + SM3_TXNFULL + [7:7] + read-only + + + SM2_TXNFULL + [6:6] + read-only + + + SM1_TXNFULL + [5:5] + read-only + + + SM0_TXNFULL + [4:4] + read-only + + + SM3_RXNEMPTY + [3:3] + read-only + + + SM2_RXNEMPTY + [2:2] + read-only + + + SM1_RXNEMPTY + [1:1] + read-only + + + SM0_RXNEMPTY + [0:0] + read-only + + + + + + + PIO1 + 0x50300000 + + PIO1_IRQ_0 + 9 + + + PIO1_IRQ_1 + 10 + + + + BUSCTRL + Register block for busfabric control signals and performance counters + 0x40030000 + + 0 + 40 + registers + + + + BUS_PRIORITY + 0x00000000 + Set the priority of each master for bus arbitration. + 0x00000000 + + + DMA_W + 0 - low priority, 1 - high priority + [12:12] + read-write + + + DMA_R + 0 - low priority, 1 - high priority + [8:8] + read-write + + + PROC1 + 0 - low priority, 1 - high priority + [4:4] + read-write + + + PROC0 + 0 - low priority, 1 - high priority + [0:0] + read-write + + + + + BUS_PRIORITY_ACK + 0x00000004 + Bus priority acknowledge + 0x00000000 + + + BUS_PRIORITY_ACK + Goes to 1 once all arbiters have registered the new global priority levels. + Arbiters update their local priority when servicing a new nonsequential access. + In normal circumstances this will happen almost immediately. + [0:0] + read-only + + + + + PERFCTR0 + 0x00000008 + Bus fabric performance counter 0 + 0x00000000 + + + PERFCTR0 + Busfabric saturating performance counter 0 + Count some event signal from the busfabric arbiters. + Write any value to clear. Select an event to count using PERFSEL0 + [23:0] + read-write + oneToClear + + + + + PERFSEL0 + 0x0000000c + Bus fabric performance event select for PERFCTR0 + 0x0000001f + + + PERFSEL0 + Select an event for PERFCTR0. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + [4:0] + read-write + + + apb_contested + 0 + + + apb + 1 + + + fastperi_contested + 2 + + + fastperi + 3 + + + sram5_contested + 4 + + + sram5 + 5 + + + sram4_contested + 6 + + + sram4 + 7 + + + sram3_contested + 8 + + + sram3 + 9 + + + sram2_contested + 10 + + + sram2 + 11 + + + sram1_contested + 12 + + + sram1 + 13 + + + sram0_contested + 14 + + + sram0 + 15 + + + xip_main_contested + 16 + + + xip_main + 17 + + + rom_contested + 18 + + + rom + 19 + + + + + + + PERFCTR1 + 0x00000010 + Bus fabric performance counter 1 + 0x00000000 + + + PERFCTR1 + Busfabric saturating performance counter 1 + Count some event signal from the busfabric arbiters. + Write any value to clear. Select an event to count using PERFSEL1 + [23:0] + read-write + oneToClear + + + + + PERFSEL1 + 0x00000014 + Bus fabric performance event select for PERFCTR1 + 0x0000001f + + + PERFSEL1 + Select an event for PERFCTR1. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + [4:0] + read-write + + + apb_contested + 0 + + + apb + 1 + + + fastperi_contested + 2 + + + fastperi + 3 + + + sram5_contested + 4 + + + sram5 + 5 + + + sram4_contested + 6 + + + sram4 + 7 + + + sram3_contested + 8 + + + sram3 + 9 + + + sram2_contested + 10 + + + sram2 + 11 + + + sram1_contested + 12 + + + sram1 + 13 + + + sram0_contested + 14 + + + sram0 + 15 + + + xip_main_contested + 16 + + + xip_main + 17 + + + rom_contested + 18 + + + rom + 19 + + + + + + + PERFCTR2 + 0x00000018 + Bus fabric performance counter 2 + 0x00000000 + + + PERFCTR2 + Busfabric saturating performance counter 2 + Count some event signal from the busfabric arbiters. + Write any value to clear. Select an event to count using PERFSEL2 + [23:0] + read-write + oneToClear + + + + + PERFSEL2 + 0x0000001c + Bus fabric performance event select for PERFCTR2 + 0x0000001f + + + PERFSEL2 + Select an event for PERFCTR2. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + [4:0] + read-write + + + apb_contested + 0 + + + apb + 1 + + + fastperi_contested + 2 + + + fastperi + 3 + + + sram5_contested + 4 + + + sram5 + 5 + + + sram4_contested + 6 + + + sram4 + 7 + + + sram3_contested + 8 + + + sram3 + 9 + + + sram2_contested + 10 + + + sram2 + 11 + + + sram1_contested + 12 + + + sram1 + 13 + + + sram0_contested + 14 + + + sram0 + 15 + + + xip_main_contested + 16 + + + xip_main + 17 + + + rom_contested + 18 + + + rom + 19 + + + + + + + PERFCTR3 + 0x00000020 + Bus fabric performance counter 3 + 0x00000000 + + + PERFCTR3 + Busfabric saturating performance counter 3 + Count some event signal from the busfabric arbiters. + Write any value to clear. Select an event to count using PERFSEL3 + [23:0] + read-write + oneToClear + + + + + PERFSEL3 + 0x00000024 + Bus fabric performance event select for PERFCTR3 + 0x0000001f + + + PERFSEL3 + Select an event for PERFCTR3. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + [4:0] + read-write + + + apb_contested + 0 + + + apb + 1 + + + fastperi_contested + 2 + + + fastperi + 3 + + + sram5_contested + 4 + + + sram5 + 5 + + + sram4_contested + 6 + + + sram4 + 7 + + + sram3_contested + 8 + + + sram3 + 9 + + + sram2_contested + 10 + + + sram2 + 11 + + + sram1_contested + 12 + + + sram1 + 13 + + + sram0_contested + 14 + + + sram0 + 15 + + + xip_main_contested + 16 + + + xip_main + 17 + + + rom_contested + 18 + + + rom + 19 + + + + + + + + + SIO + Single-cycle IO block + Provides core-local and inter-core hardware for the two processors, with single-cycle access. + 0xd0000000 + + 0 + 384 + registers + + + SIO_IRQ_PROC0 + 15 + + + SIO_IRQ_PROC1 + 16 + + + + CPUID + 0x00000000 + Processor core identifier + 0x00000000 + + + CPUID + Value is 0 when read from processor core 0, and 1 when read from processor core 1. + [31:0] + read-only + + + + + GPIO_IN + 0x00000004 + Input value for GPIO pins + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_HI_IN + 0x00000008 + Input value for QSPI pins + 0x00000000 + + + GPIO_HI_IN + Input value on QSPI IO in order 0..5: SCLK, SSn, SD0, SD1, SD2, SD3 + [5:0] + read-only + + + + + GPIO_OUT + 0x00000010 + GPIO output value: Set output level (1/0 -> high/low) for GPIO0...29. + Reading back gives the last value written, NOT the input value from the pins. + If core 0 and core 1 both write to GPIO_OUT simultaneously (or to a SET/CLR/XOR alias), + the result is as though the write from core 0 took place first, + and the write from core 1 was then applied to that intermediate result. + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OUT_SET + 0x00000014 + GPIO output value set: Perform an atomic bit-set on GPIO_OUT, i.e. `GPIO_OUT |= wdata` + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OUT_CLR + 0x00000018 + GPIO output value clear + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OUT_XOR + 0x0000001c + GPIO output value XOR + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OE + 0x00000020 + GPIO output enable: Set output enable (1/0 -> output/input) for GPIO0...29. + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OE_SET + 0x00000024 + GPIO output enable set: Perform an atomic bit-set on GPIO_OE, i.e. `GPIO_OE |= wdata` + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OE_CLR + 0x00000028 + GPIO output enable clear: Perform an atomic bit-clear on GPIO_OE, i.e. `GPIO_OE &= ~wdata` + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_OE_XOR + 0x0000002c + GPIO output enable XOR: Perform an atomic bitwise XOR on GPIO_OE, i.e. `GPIO_OE ^= wdata` + 0x00000000 + + IO0[0:0] + IO1[1:1] + IO2[2:2] + IO3[3:3] + IO4[4:4] + IO5[5:5] + IO6[6:6] + IO7[7:7] + IO8[8:8] + IO9[9:9] + IO10[10:10] + IO11[11:11] + IO12[12:12] + IO13[13:13] + IO14[14:14] + IO15[15:15] + IO16[16:16] + IO17[17:17] + IO18[18:18] + IO19[19:19] + IO20[20:20] + IO21[21:21] + IO22[22:22] + IO23[23:23] + IO24[24:24] + IO25[25:25] + IO26[26:26] + IO27[27:27] + IO28[28:28] + IO29[29:29] + _reserved[31:30] + + + + GPIO_HI_OUT + 0x00000030 + QSPI output value + 0x00000000 + + + GPIO_HI_OUT + Set output level (1/0 -> high/low) for QSPI IO0...5. + Reading back gives the last value written, NOT the input value from the pins. + If core 0 and core 1 both write to GPIO_HI_OUT simultaneously (or to a SET/CLR/XOR alias), + the result is as though the write from core 0 took place first, + and the write from core 1 was then applied to that intermediate result. + [5:0] + read-write + + + + + GPIO_HI_OUT_SET + 0x00000034 + QSPI output value set + 0x00000000 + + + GPIO_HI_OUT_SET + Perform an atomic bit-set on GPIO_HI_OUT, i.e. `GPIO_HI_OUT |= wdata` + [5:0] + write-only + + + + + GPIO_HI_OUT_CLR + 0x00000038 + QSPI output value clear + 0x00000000 + + + GPIO_HI_OUT_CLR + Perform an atomic bit-clear on GPIO_HI_OUT, i.e. `GPIO_HI_OUT &= ~wdata` + [5:0] + write-only + + + + + GPIO_HI_OUT_XOR + 0x0000003c + QSPI output value XOR + 0x00000000 + + + GPIO_HI_OUT_XOR + Perform an atomic bitwise XOR on GPIO_HI_OUT, i.e. `GPIO_HI_OUT ^= wdata` + [5:0] + write-only + + + + + GPIO_HI_OE + 0x00000040 + QSPI output enable + 0x00000000 + + + GPIO_HI_OE + Set output enable (1/0 -> output/input) for QSPI IO0...5. + Reading back gives the last value written. + If core 0 and core 1 both write to GPIO_HI_OE simultaneously (or to a SET/CLR/XOR alias), + the result is as though the write from core 0 took place first, + and the write from core 1 was then applied to that intermediate result. + [5:0] + read-write + + + + + GPIO_HI_OE_SET + 0x00000044 + QSPI output enable set + 0x00000000 + + + GPIO_HI_OE_SET + Perform an atomic bit-set on GPIO_HI_OE, i.e. `GPIO_HI_OE |= wdata` + [5:0] + write-only + + + + + GPIO_HI_OE_CLR + 0x00000048 + QSPI output enable clear + 0x00000000 + + + GPIO_HI_OE_CLR + Perform an atomic bit-clear on GPIO_HI_OE, i.e. `GPIO_HI_OE &= ~wdata` + [5:0] + write-only + + + + + GPIO_HI_OE_XOR + 0x0000004c + QSPI output enable XOR + 0x00000000 + + + GPIO_HI_OE_XOR + Perform an atomic bitwise XOR on GPIO_HI_OE, i.e. `GPIO_HI_OE ^= wdata` + [5:0] + write-only + + + + + FIFO_ST + 0x00000050 + Status register for inter-core FIFOs (mailboxes). + There is one FIFO in the core 0 -> core 1 direction, and one core 1 -> core 0. Both are 32 bits wide and 8 words deep. + Core 0 can see the read side of the 1->0 FIFO (RX), and the write side of 0->1 FIFO (TX). + Core 1 can see the read side of the 0->1 FIFO (RX), and the write side of 1->0 FIFO (TX). + The SIO IRQ for each core is the logical OR of the VLD, WOF and ROE fields of its FIFO_ST register. + 0x00000002 + + + ROE + Sticky flag indicating the RX FIFO was read when empty. This read was ignored by the FIFO. + [3:3] + read-write + oneToClear + + + WOF + Sticky flag indicating the TX FIFO was written when full. This write was ignored by the FIFO. + [2:2] + read-write + oneToClear + + + RDY + Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more data) + [1:1] + read-only + + + VLD + Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid) + [0:0] + read-only + + + + + FIFO_WR + 0x00000054 + Write access to this core's TX FIFO + 0x00000000 + + + FIFO_WR + [31:0] + write-only + + + + + FIFO_RD + 0x00000058 + Read access to this core's RX FIFO + 0x00000000 + + + FIFO_RD + [31:0] + read-only + modify + + + + + SPINLOCK_ST + 0x0000005c + Spinlock state + A bitmap containing the state of all 32 spinlocks (1=locked). + Mainly intended for debugging. + 0x00000000 + + + SPINLOCK_ST + [31:0] + read-only + + + + + DIV_UDIVIDEND + 0x00000060 + Divider unsigned dividend + Write to the DIVIDEND operand of the divider, i.e. the p in `p / q`. + Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. + UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias starts an + unsigned calculation, and the S alias starts a signed calculation. + 0x00000000 + + + DIV_UDIVIDEND + [31:0] + read-write + + + + + DIV_UDIVISOR + 0x00000064 + Divider unsigned divisor + Write to the DIVISOR operand of the divider, i.e. the q in `p / q`. + Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. + UDIVISOR/SDIVISOR are aliases of the same internal register. The U alias starts an + unsigned calculation, and the S alias starts a signed calculation. + 0x00000000 + + + DIV_UDIVISOR + [31:0] + read-write + + + + + DIV_SDIVIDEND + 0x00000068 + Divider signed dividend + The same as UDIVIDEND, but starts a signed calculation, rather than unsigned. + 0x00000000 + + + DIV_SDIVIDEND + [31:0] + read-write + + + + + DIV_SDIVISOR + 0x0000006c + Divider signed divisor + The same as UDIVISOR, but starts a signed calculation, rather than unsigned. + 0x00000000 + + + DIV_SDIVISOR + [31:0] + read-write + + + + + DIV_QUOTIENT + 0x00000070 + Divider result quotient + The result of `DIVIDEND / DIVISOR` (division). Contents undefined while CSR_READY is low. + For signed calculations, QUOTIENT is negative when the signs of DIVIDEND and DIVISOR differ. + This register can be written to directly, for context save/restore purposes. This halts any + in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. + Reading from QUOTIENT clears the CSR_DIRTY flag, so should read results in the order + REMAINDER, QUOTIENT if CSR_DIRTY is used. + 0x00000000 + + + DIV_QUOTIENT + [31:0] + read-write + + + + + DIV_REMAINDER + 0x00000074 + Divider result remainder + The result of `DIVIDEND % DIVISOR` (modulo). Contents undefined while CSR_READY is low. + For signed calculations, REMAINDER is negative only when DIVIDEND is negative. + This register can be written to directly, for context save/restore purposes. This halts any + in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. + 0x00000000 + + + DIV_REMAINDER + [31:0] + read-write + + + + + DIV_CSR + 0x00000078 + Control and status register for divider. + 0x00000001 + + + DIRTY + Changes to 1 when any register is written, and back to 0 when QUOTIENT is read. + Software can use this flag to make save/restore more efficient (skip if not DIRTY). + If the flag is used in this way, it's recommended to either read QUOTIENT only, + or REMAINDER and then QUOTIENT, to prevent data loss on context switch. + [1:1] + read-only + + + READY + Reads as 0 when a calculation is in progress, 1 otherwise. + Writing an operand (xDIVIDEND, xDIVISOR) will immediately start a new calculation, no + matter if one is already in progress. + Writing to a result register will immediately terminate any in-progress calculation + and set the READY and DIRTY flags. + [0:0] + read-only + + + + + INTERP0_ACCUM0 + 0x00000080 + Read/write access to accumulator 0 + 0x00000000 + + + INTERP0_ACCUM0 + [31:0] + read-write + + + + + INTERP0_ACCUM1 + 0x00000084 + Read/write access to accumulator 1 + 0x00000000 + + + INTERP0_ACCUM1 + [31:0] + read-write + + + + + INTERP0_BASE0 + 0x00000088 + Read/write access to BASE0 register. + 0x00000000 + + + INTERP0_BASE0 + [31:0] + read-write + + + + + INTERP0_BASE1 + 0x0000008c + Read/write access to BASE1 register. + 0x00000000 + + + INTERP0_BASE1 + [31:0] + read-write + + + + + INTERP0_BASE2 + 0x00000090 + Read/write access to BASE2 register. + 0x00000000 + + + INTERP0_BASE2 + [31:0] + read-write + + + + + INTERP0_POP_LANE0 + 0x00000094 + Read LANE0 result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP0_POP_LANE0 + [31:0] + read-only + + + + + INTERP0_POP_LANE1 + 0x00000098 + Read LANE1 result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP0_POP_LANE1 + [31:0] + read-only + + + + + INTERP0_POP_FULL + 0x0000009c + Read FULL result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP0_POP_FULL + [31:0] + read-only + + + + + INTERP0_PEEK_LANE0 + 0x000000a0 + Read LANE0 result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP0_PEEK_LANE0 + [31:0] + read-only + + + + + INTERP0_PEEK_LANE1 + 0x000000a4 + Read LANE1 result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP0_PEEK_LANE1 + [31:0] + read-only + + + + + INTERP0_PEEK_FULL + 0x000000a8 + Read FULL result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP0_PEEK_FULL + [31:0] + read-only + + + + + INTERP0_CTRL_LANE0 + 0x000000ac + Control register for lane 0 + 0x00000000 + + + OVERF + Set if either OVERF0 or OVERF1 is set. + [25:25] + read-only + + + OVERF1 + Indicates if any masked-off MSBs in ACCUM1 are set. + [24:24] + read-only + + + OVERF0 + Indicates if any masked-off MSBs in ACCUM0 are set. + [23:23] + read-only + + + BLEND + Only present on INTERP0 on each core. If BLEND mode is enabled: + - LANE1 result is a linear interpolation between BASE0 and BASE1, controlled + by the 8 LSBs of lane 1 shift and mask value (a fractional number between + 0 and 255/256ths) + - LANE0 result does not have BASE0 added (yields only the 8 LSBs of lane 1 shift+mask value) + - FULL result does not have lane 1 shift+mask value added (BASE2 + lane 0 shift+mask) + LANE1 SIGNED flag controls whether the interpolation is signed or unsigned. + [21:21] + read-write + + + FORCE_MSB + ORed into bits 29:28 of the lane result presented to the processor on the bus. + No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + of pointers into flash or SRAM. + [20:19] + read-write + + + ADD_RAW + If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. + [18:18] + read-write + + + CROSS_RESULT + If 1, feed the opposite lane's result into this lane's accumulator on POP. + [17:17] + read-write + + + CROSS_INPUT + If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + [16:16] + read-write + + + SIGNED + If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. + [15:15] + read-write + + + MASK_MSB + The most-significant bit allowed to pass by the mask (inclusive) + Setting MSB < LSB may cause chip to turn inside-out + [14:10] + read-write + + + MASK_LSB + The least-significant bit allowed to pass by the mask (inclusive) + [9:5] + read-write + + + SHIFT + Logical right-shift applied to accumulator before masking + [4:0] + read-write + + + + + INTERP0_CTRL_LANE1 + 0x000000b0 + Control register for lane 1 + 0x00000000 + + + FORCE_MSB + ORed into bits 29:28 of the lane result presented to the processor on the bus. + No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + of pointers into flash or SRAM. + [20:19] + read-write + + + ADD_RAW + If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. + [18:18] + read-write + + + CROSS_RESULT + If 1, feed the opposite lane's result into this lane's accumulator on POP. + [17:17] + read-write + + + CROSS_INPUT + If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + [16:16] + read-write + + + SIGNED + If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. + [15:15] + read-write + + + MASK_MSB + The most-significant bit allowed to pass by the mask (inclusive) + Setting MSB < LSB may cause chip to turn inside-out + [14:10] + read-write + + + MASK_LSB + The least-significant bit allowed to pass by the mask (inclusive) + [9:5] + read-write + + + SHIFT + Logical right-shift applied to accumulator before masking + [4:0] + read-write + + + + + INTERP0_ACCUM0_ADD + 0x000000b4 + Values written here are atomically added to ACCUM0 + Reading yields lane 0's raw shift and mask value (BASE0 not added). + 0x00000000 + + + INTERP0_ACCUM0_ADD + [23:0] + read-write + + + + + INTERP0_ACCUM1_ADD + 0x000000b8 + Values written here are atomically added to ACCUM1 + Reading yields lane 1's raw shift and mask value (BASE1 not added). + 0x00000000 + + + INTERP0_ACCUM1_ADD + [23:0] + read-write + + + + + INTERP0_BASE_1AND0 + 0x000000bc + On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. + Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + 0x00000000 + + + INTERP0_BASE_1AND0 + [31:0] + write-only + + + + + INTERP1_ACCUM0 + 0x000000c0 + Read/write access to accumulator 0 + 0x00000000 + + + INTERP1_ACCUM0 + [31:0] + read-write + + + + + INTERP1_ACCUM1 + 0x000000c4 + Read/write access to accumulator 1 + 0x00000000 + + + INTERP1_ACCUM1 + [31:0] + read-write + + + + + INTERP1_BASE0 + 0x000000c8 + Read/write access to BASE0 register. + 0x00000000 + + + INTERP1_BASE0 + [31:0] + read-write + + + + + INTERP1_BASE1 + 0x000000cc + Read/write access to BASE1 register. + 0x00000000 + + + INTERP1_BASE1 + [31:0] + read-write + + + + + INTERP1_BASE2 + 0x000000d0 + Read/write access to BASE2 register. + 0x00000000 + + + INTERP1_BASE2 + [31:0] + read-write + + + + + INTERP1_POP_LANE0 + 0x000000d4 + Read LANE0 result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP1_POP_LANE0 + [31:0] + read-only + + + + + INTERP1_POP_LANE1 + 0x000000d8 + Read LANE1 result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP1_POP_LANE1 + [31:0] + read-only + + + + + INTERP1_POP_FULL + 0x000000dc + Read FULL result, and simultaneously write lane results to both accumulators (POP). + 0x00000000 + + + INTERP1_POP_FULL + [31:0] + read-only + + + + + INTERP1_PEEK_LANE0 + 0x000000e0 + Read LANE0 result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP1_PEEK_LANE0 + [31:0] + read-only + + + + + INTERP1_PEEK_LANE1 + 0x000000e4 + Read LANE1 result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP1_PEEK_LANE1 + [31:0] + read-only + + + + + INTERP1_PEEK_FULL + 0x000000e8 + Read FULL result, without altering any internal state (PEEK). + 0x00000000 + + + INTERP1_PEEK_FULL + [31:0] + read-only + + + + + INTERP1_CTRL_LANE0 + 0x000000ec + Control register for lane 0 + 0x00000000 + + + OVERF + Set if either OVERF0 or OVERF1 is set. + [25:25] + read-only + + + OVERF1 + Indicates if any masked-off MSBs in ACCUM1 are set. + [24:24] + read-only + + + OVERF0 + Indicates if any masked-off MSBs in ACCUM0 are set. + [23:23] + read-only + + + CLAMP + Only present on INTERP1 on each core. If CLAMP mode is enabled: + - LANE0 result is shifted and masked ACCUM0, clamped by a lower bound of + BASE0 and an upper bound of BASE1. + - Signedness of these comparisons is determined by LANE0_CTRL_SIGNED + [22:22] + read-write + + + FORCE_MSB + ORed into bits 29:28 of the lane result presented to the processor on the bus. + No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + of pointers into flash or SRAM. + [20:19] + read-write + + + ADD_RAW + If 1, mask + shift is bypassed for LANE0 result. This does not affect FULL result. + [18:18] + read-write + + + CROSS_RESULT + If 1, feed the opposite lane's result into this lane's accumulator on POP. + [17:17] + read-write + + + CROSS_INPUT + If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + [16:16] + read-write + + + SIGNED + If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + before adding to BASE0, and LANE0 PEEK/POP appear extended to 32 bits when read by processor. + [15:15] + read-write + + + MASK_MSB + The most-significant bit allowed to pass by the mask (inclusive) + Setting MSB < LSB may cause chip to turn inside-out + [14:10] + read-write + + + MASK_LSB + The least-significant bit allowed to pass by the mask (inclusive) + [9:5] + read-write + + + SHIFT + Logical right-shift applied to accumulator before masking + [4:0] + read-write + + + + + INTERP1_CTRL_LANE1 + 0x000000f0 + Control register for lane 1 + 0x00000000 + + + FORCE_MSB + ORed into bits 29:28 of the lane result presented to the processor on the bus. + No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence + of pointers into flash or SRAM. + [20:19] + read-write + + + ADD_RAW + If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. + [18:18] + read-write + + + CROSS_RESULT + If 1, feed the opposite lane's result into this lane's accumulator on POP. + [17:17] + read-write + + + CROSS_INPUT + If 1, feed the opposite lane's accumulator into this lane's shift + mask hardware. + Takes effect even if ADD_RAW is set (the CROSS_INPUT mux is before the shift+mask bypass) + [16:16] + read-write + + + SIGNED + If SIGNED is set, the shifted and masked accumulator value is sign-extended to 32 bits + before adding to BASE1, and LANE1 PEEK/POP appear extended to 32 bits when read by processor. + [15:15] + read-write + + + MASK_MSB + The most-significant bit allowed to pass by the mask (inclusive) + Setting MSB < LSB may cause chip to turn inside-out + [14:10] + read-write + + + MASK_LSB + The least-significant bit allowed to pass by the mask (inclusive) + [9:5] + read-write + + + SHIFT + Logical right-shift applied to accumulator before masking + [4:0] + read-write + + + + + INTERP1_ACCUM0_ADD + 0x000000f4 + Values written here are atomically added to ACCUM0 + Reading yields lane 0's raw shift and mask value (BASE0 not added). + 0x00000000 + + + INTERP1_ACCUM0_ADD + [23:0] + read-write + + + + + INTERP1_ACCUM1_ADD + 0x000000f8 + Values written here are atomically added to ACCUM1 + Reading yields lane 1's raw shift and mask value (BASE1 not added). + 0x00000000 + + + INTERP1_ACCUM1_ADD + [23:0] + read-write + + + + + INTERP1_BASE_1AND0 + 0x000000fc + On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. + Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. + 0x00000000 + + + INTERP1_BASE_1AND0 + [31:0] + write-only + + + + + SPINLOCK0 + 0x00000100 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK0 + [31:0] + read-write + modify + + + + + SPINLOCK1 + 0x00000104 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK1 + [31:0] + read-write + modify + + + + + SPINLOCK2 + 0x00000108 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK2 + [31:0] + read-write + modify + + + + + SPINLOCK3 + 0x0000010c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK3 + [31:0] + read-write + modify + + + + + SPINLOCK4 + 0x00000110 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK4 + [31:0] + read-write + modify + + + + + SPINLOCK5 + 0x00000114 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK5 + [31:0] + read-write + modify + + + + + SPINLOCK6 + 0x00000118 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK6 + [31:0] + read-write + modify + + + + + SPINLOCK7 + 0x0000011c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK7 + [31:0] + read-write + modify + + + + + SPINLOCK8 + 0x00000120 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK8 + [31:0] + read-write + modify + + + + + SPINLOCK9 + 0x00000124 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK9 + [31:0] + read-write + modify + + + + + SPINLOCK10 + 0x00000128 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK10 + [31:0] + read-write + modify + + + + + SPINLOCK11 + 0x0000012c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK11 + [31:0] + read-write + modify + + + + + SPINLOCK12 + 0x00000130 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK12 + [31:0] + read-write + modify + + + + + SPINLOCK13 + 0x00000134 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK13 + [31:0] + read-write + modify + + + + + SPINLOCK14 + 0x00000138 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK14 + [31:0] + read-write + modify + + + + + SPINLOCK15 + 0x0000013c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK15 + [31:0] + read-write + modify + + + + + SPINLOCK16 + 0x00000140 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK16 + [31:0] + read-write + modify + + + + + SPINLOCK17 + 0x00000144 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK17 + [31:0] + read-write + modify + + + + + SPINLOCK18 + 0x00000148 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK18 + [31:0] + read-write + modify + + + + + SPINLOCK19 + 0x0000014c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK19 + [31:0] + read-write + modify + + + + + SPINLOCK20 + 0x00000150 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK20 + [31:0] + read-write + modify + + + + + SPINLOCK21 + 0x00000154 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK21 + [31:0] + read-write + modify + + + + + SPINLOCK22 + 0x00000158 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK22 + [31:0] + read-write + modify + + + + + SPINLOCK23 + 0x0000015c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK23 + [31:0] + read-write + modify + + + + + SPINLOCK24 + 0x00000160 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK24 + [31:0] + read-write + modify + + + + + SPINLOCK25 + 0x00000164 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK25 + [31:0] + read-write + modify + + + + + SPINLOCK26 + 0x00000168 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK26 + [31:0] + read-write + modify + + + + + SPINLOCK27 + 0x0000016c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK27 + [31:0] + read-write + modify + + + + + SPINLOCK28 + 0x00000170 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK28 + [31:0] + read-write + modify + + + + + SPINLOCK29 + 0x00000174 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK29 + [31:0] + read-write + modify + + + + + SPINLOCK30 + 0x00000178 + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK30 + [31:0] + read-write + modify + + + + + SPINLOCK31 + 0x0000017c + Reading from a spinlock address will: + - Return 0 if lock is already locked + - Otherwise return nonzero, and simultaneously claim the lock + + Writing (any value) releases the lock. + If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. + The value returned on success is 0x1 << lock number. + 0x00000000 + + + SPINLOCK31 + [31:0] + read-write + modify + + + + + + + USB + USB FS/LS controller device registers + 0x50110000 + + 0 + 156 + registers + + + USBCTRL_IRQ + 5 + + + + ADDR_ENDP + 0x00000000 + Device address and endpoint control + 0x00000000 + + + ENDPOINT + Device endpoint to send data to. Only valid for HOST mode. + [19:16] + read-write + + + ADDRESS + In device mode, the address that the device should respond to. Set in response to a SET_ADDR setup packet from the host. In host mode set to the address of the device to communicate with. + [6:0] + read-write + + + + + ADDR_ENDP1 + 0x00000004 + Interrupt endpoint 1. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP2 + 0x00000008 + Interrupt endpoint 2. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP3 + 0x0000000c + Interrupt endpoint 3. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP4 + 0x00000010 + Interrupt endpoint 4. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP5 + 0x00000014 + Interrupt endpoint 5. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP6 + 0x00000018 + Interrupt endpoint 6. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP7 + 0x0000001c + Interrupt endpoint 7. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP8 + 0x00000020 + Interrupt endpoint 8. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP9 + 0x00000024 + Interrupt endpoint 9. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP10 + 0x00000028 + Interrupt endpoint 10. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP11 + 0x0000002c + Interrupt endpoint 11. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP12 + 0x00000030 + Interrupt endpoint 12. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP13 + 0x00000034 + Interrupt endpoint 13. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP14 + 0x00000038 + Interrupt endpoint 14. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + ADDR_ENDP15 + 0x0000003c + Interrupt endpoint 15. Only valid for HOST mode. + 0x00000000 + + + INTEP_PREAMBLE + Interrupt EP requires preamble (is a low speed device on a full speed hub) + [26:26] + read-write + + + INTEP_DIR + Direction of the interrupt endpoint. In=0, Out=1 + [25:25] + read-write + + + ENDPOINT + Endpoint number of the interrupt endpoint + [19:16] + read-write + + + ADDRESS + Device address + [6:0] + read-write + + + + + MAIN_CTRL + 0x00000040 + Main control register + 0x00000000 + + + SIM_TIMING + Reduced timings for simulation + [31:31] + read-write + + + HOST_NDEVICE + Device mode = 0, Host mode = 1 + [1:1] + read-write + + + CONTROLLER_EN + Enable controller + [0:0] + read-write + + + + + SOF_WR + 0x00000044 + Set the SOF (Start of Frame) frame number in the host controller. The SOF packet is sent every 1ms and the host will increment the frame number by 1 each time. + 0x00000000 + + + COUNT + [10:0] + write-only + + + + + SOF_RD + 0x00000048 + Read the last SOF (Start of Frame) frame number seen. In device mode the last SOF received from the host. In host mode the last SOF sent by the host. + 0x00000000 + + + COUNT + [10:0] + read-only + + + + + SIE_CTRL + 0x0000004c + SIE control register + 0x00000000 + + + EP0_INT_STALL + Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a STALL + [31:31] + read-write + + + EP0_DOUBLE_BUF + Device: EP0 single buffered = 0, double buffered = 1 + [30:30] + read-write + + + EP0_INT_1BUF + Device: Set bit in BUFF_STATUS for every buffer completed on EP0 + [29:29] + read-write + + + EP0_INT_2BUF + Device: Set bit in BUFF_STATUS for every 2 buffers completed on EP0 + [28:28] + read-write + + + EP0_INT_NAK + Device: Set bit in EP_STATUS_STALL_NAK when EP0 sends a NAK + [27:27] + read-write + + + DIRECT_EN + Direct bus drive enable + [26:26] + read-write + + + DIRECT_DP + Direct control of DP + [25:25] + read-write + + + DIRECT_DM + Direct control of DM + [24:24] + read-write + + + TRANSCEIVER_PD + Power down bus transceiver + [18:18] + read-write + + + RPU_OPT + Device: Pull-up strength (0=1K2, 1=2k3) + [17:17] + read-write + + + PULLUP_EN + Device: Enable pull up resistor + [16:16] + read-write + + + PULLDOWN_EN + Host: Enable pull down resistors + [15:15] + read-write + + + RESET_BUS + Host: Reset bus + [13:13] + write-only + + + RESUME + Device: Remote wakeup. Device can initiate its own resume after suspend. + [12:12] + write-only + + + VBUS_EN + Host: Enable VBUS + [11:11] + read-write + + + KEEP_ALIVE_EN + Host: Enable keep alive packet (for low speed bus) + [10:10] + read-write + + + SOF_EN + Host: Enable SOF generation (for full speed bus) + [9:9] + read-write + + + SOF_SYNC + Host: Delay packet(s) until after SOF + [8:8] + read-write + + + PREAMBLE_EN + Host: Preable enable for LS device on FS hub + [6:6] + read-write + + + STOP_TRANS + Host: Stop transaction + [4:4] + write-only + + + RECEIVE_DATA + Host: Receive transaction (IN to host) + [3:3] + read-write + + + SEND_DATA + Host: Send transaction (OUT from host) + [2:2] + read-write + + + SEND_SETUP + Host: Send Setup packet + [1:1] + read-write + + + START_TRANS + Host: Start transaction + [0:0] + write-only + + + + + SIE_STATUS + 0x00000050 + SIE status register + 0x00000000 + + + DATA_SEQ_ERROR + Data Sequence Error. + + The device can raise a sequence error in the following conditions: + + * A SETUP packet is received followed by a DATA1 packet (data phase should always be DATA0) * An OUT packet is received from the host but doesn't match the data pid in the buffer control register read from DPSRAM + + The host can raise a data sequence error in the following conditions: + + * An IN packet from the device has the wrong data PID + [31:31] + read-write + oneToClear + + + ACK_REC + ACK received. Raised by both host and device. + [30:30] + read-write + oneToClear + + + STALL_REC + Host: STALL received + [29:29] + read-write + oneToClear + + + NAK_REC + Host: NAK received + [28:28] + read-write + oneToClear + + + RX_TIMEOUT + RX timeout is raised by both the host and device if an ACK is not received in the maximum time specified by the USB spec. + [27:27] + read-write + oneToClear + + + RX_OVERFLOW + RX overflow is raised by the Serial RX engine if the incoming data is too fast. + [26:26] + read-write + oneToClear + + + BIT_STUFF_ERROR + Bit Stuff Error. Raised by the Serial RX engine. + [25:25] + read-write + oneToClear + + + CRC_ERROR + CRC Error. Raised by the Serial RX engine. + [24:24] + read-write + oneToClear + + + BUS_RESET + Device: bus reset received + [19:19] + read-write + oneToClear + + + TRANS_COMPLETE + Transaction complete. + + Raised by device if: + + * An IN or OUT packet is sent with the `LAST_BUFF` bit set in the buffer control register + + Raised by host if: + + * A setup packet is sent when no data in or data out transaction follows * An IN packet is received and the `LAST_BUFF` bit is set in the buffer control register * An IN packet is received with zero length * An OUT packet is sent and the `LAST_BUFF` bit is set + [18:18] + read-write + oneToClear + + + SETUP_REC + Device: Setup packet received + [17:17] + read-write + oneToClear + + + CONNECTED + Device: connected + [16:16] + read-only + + + RESUME + Host: Device has initiated a remote resume. Device: host has initiated a resume. + [11:11] + read-write + oneToClear + + + VBUS_OVER_CURR + VBUS over current detected + [10:10] + read-only + + + SPEED + Host: device speed. Disconnected = 00, LS = 01, FS = 10 + [9:8] + read-only + + + SUSPENDED + Bus in suspended state. Valid for device and host. Host and device will go into suspend if neither Keep Alive / SOF frames are enabled. + [4:4] + read-only + + + LINE_STATE + USB bus line state + [3:2] + read-only + + + VBUS_DETECTED + Device: VBUS Detected + [0:0] + read-only + + + + + INT_EP_CTRL + 0x00000054 + interrupt endpoint control register + 0x00000000 + + + INT_EP_ACTIVE + Host: Enable interrupt endpoint 1 => 15 + [15:1] + read-write + + + + + BUFF_STATUS + 0x00000058 + Buffer status register. A bit set here indicates that a buffer has completed on the endpoint (if the buffer interrupt is enabled). It is possible for 2 buffers to be completed, so clearing the buffer status bit may instantly re set it on the next clock cycle. + 0x00000000 + + + EP15_OUT + [31:31] + read-write + oneToClear + + + EP15_IN + [30:30] + read-write + oneToClear + + + EP14_OUT + [29:29] + read-write + oneToClear + + + EP14_IN + [28:28] + read-write + oneToClear + + + EP13_OUT + [27:27] + read-write + oneToClear + + + EP13_IN + [26:26] + read-write + oneToClear + + + EP12_OUT + [25:25] + read-write + oneToClear + + + EP12_IN + [24:24] + read-write + oneToClear + + + EP11_OUT + [23:23] + read-write + oneToClear + + + EP11_IN + [22:22] + read-write + oneToClear + + + EP10_OUT + [21:21] + read-write + oneToClear + + + EP10_IN + [20:20] + read-write + oneToClear + + + EP9_OUT + [19:19] + read-write + oneToClear + + + EP9_IN + [18:18] + read-write + oneToClear + + + EP8_OUT + [17:17] + read-write + oneToClear + + + EP8_IN + [16:16] + read-write + oneToClear + + + EP7_OUT + [15:15] + read-write + oneToClear + + + EP7_IN + [14:14] + read-write + oneToClear + + + EP6_OUT + [13:13] + read-write + oneToClear + + + EP6_IN + [12:12] + read-write + oneToClear + + + EP5_OUT + [11:11] + read-write + oneToClear + + + EP5_IN + [10:10] + read-write + oneToClear + + + EP4_OUT + [9:9] + read-write + oneToClear + + + EP4_IN + [8:8] + read-write + oneToClear + + + EP3_OUT + [7:7] + read-write + oneToClear + + + EP3_IN + [6:6] + read-write + oneToClear + + + EP2_OUT + [5:5] + read-write + oneToClear + + + EP2_IN + [4:4] + read-write + oneToClear + + + EP1_OUT + [3:3] + read-write + oneToClear + + + EP1_IN + [2:2] + read-write + oneToClear + + + EP0_OUT + [1:1] + read-write + oneToClear + + + EP0_IN + [0:0] + read-write + oneToClear + + + + + BUFF_CPU_SHOULD_HANDLE + 0x0000005c + Which of the double buffers should be handled. Only valid if using an interrupt per buffer (i.e. not per 2 buffers). Not valid for host interrupt endpoint polling because they are only single buffered. + 0x00000000 + + + EP15_OUT + [31:31] + read-only + + + EP15_IN + [30:30] + read-only + + + EP14_OUT + [29:29] + read-only + + + EP14_IN + [28:28] + read-only + + + EP13_OUT + [27:27] + read-only + + + EP13_IN + [26:26] + read-only + + + EP12_OUT + [25:25] + read-only + + + EP12_IN + [24:24] + read-only + + + EP11_OUT + [23:23] + read-only + + + EP11_IN + [22:22] + read-only + + + EP10_OUT + [21:21] + read-only + + + EP10_IN + [20:20] + read-only + + + EP9_OUT + [19:19] + read-only + + + EP9_IN + [18:18] + read-only + + + EP8_OUT + [17:17] + read-only + + + EP8_IN + [16:16] + read-only + + + EP7_OUT + [15:15] + read-only + + + EP7_IN + [14:14] + read-only + + + EP6_OUT + [13:13] + read-only + + + EP6_IN + [12:12] + read-only + + + EP5_OUT + [11:11] + read-only + + + EP5_IN + [10:10] + read-only + + + EP4_OUT + [9:9] + read-only + + + EP4_IN + [8:8] + read-only + + + EP3_OUT + [7:7] + read-only + + + EP3_IN + [6:6] + read-only + + + EP2_OUT + [5:5] + read-only + + + EP2_IN + [4:4] + read-only + + + EP1_OUT + [3:3] + read-only + + + EP1_IN + [2:2] + read-only + + + EP0_OUT + [1:1] + read-only + + + EP0_IN + [0:0] + read-only + + + + + EP_ABORT + 0x00000060 + Device only: Can be set to ignore the buffer control register for this endpoint in case you would like to revoke a buffer. A NAK will be sent for every access to the endpoint until this bit is cleared. A corresponding bit in `EP_ABORT_DONE` is set when it is safe to modify the buffer control register. + 0x00000000 + + + EP15_OUT + [31:31] + read-write + + + EP15_IN + [30:30] + read-write + + + EP14_OUT + [29:29] + read-write + + + EP14_IN + [28:28] + read-write + + + EP13_OUT + [27:27] + read-write + + + EP13_IN + [26:26] + read-write + + + EP12_OUT + [25:25] + read-write + + + EP12_IN + [24:24] + read-write + + + EP11_OUT + [23:23] + read-write + + + EP11_IN + [22:22] + read-write + + + EP10_OUT + [21:21] + read-write + + + EP10_IN + [20:20] + read-write + + + EP9_OUT + [19:19] + read-write + + + EP9_IN + [18:18] + read-write + + + EP8_OUT + [17:17] + read-write + + + EP8_IN + [16:16] + read-write + + + EP7_OUT + [15:15] + read-write + + + EP7_IN + [14:14] + read-write + + + EP6_OUT + [13:13] + read-write + + + EP6_IN + [12:12] + read-write + + + EP5_OUT + [11:11] + read-write + + + EP5_IN + [10:10] + read-write + + + EP4_OUT + [9:9] + read-write + + + EP4_IN + [8:8] + read-write + + + EP3_OUT + [7:7] + read-write + + + EP3_IN + [6:6] + read-write + + + EP2_OUT + [5:5] + read-write + + + EP2_IN + [4:4] + read-write + + + EP1_OUT + [3:3] + read-write + + + EP1_IN + [2:2] + read-write + + + EP0_OUT + [1:1] + read-write + + + EP0_IN + [0:0] + read-write + + + + + EP_ABORT_DONE + 0x00000064 + Device only: Used in conjunction with `EP_ABORT`. Set once an endpoint is idle so the programmer knows it is safe to modify the buffer control register. + 0x00000000 + + + EP15_OUT + [31:31] + read-write + oneToClear + + + EP15_IN + [30:30] + read-write + oneToClear + + + EP14_OUT + [29:29] + read-write + oneToClear + + + EP14_IN + [28:28] + read-write + oneToClear + + + EP13_OUT + [27:27] + read-write + oneToClear + + + EP13_IN + [26:26] + read-write + oneToClear + + + EP12_OUT + [25:25] + read-write + oneToClear + + + EP12_IN + [24:24] + read-write + oneToClear + + + EP11_OUT + [23:23] + read-write + oneToClear + + + EP11_IN + [22:22] + read-write + oneToClear + + + EP10_OUT + [21:21] + read-write + oneToClear + + + EP10_IN + [20:20] + read-write + oneToClear + + + EP9_OUT + [19:19] + read-write + oneToClear + + + EP9_IN + [18:18] + read-write + oneToClear + + + EP8_OUT + [17:17] + read-write + oneToClear + + + EP8_IN + [16:16] + read-write + oneToClear + + + EP7_OUT + [15:15] + read-write + oneToClear + + + EP7_IN + [14:14] + read-write + oneToClear + + + EP6_OUT + [13:13] + read-write + oneToClear + + + EP6_IN + [12:12] + read-write + oneToClear + + + EP5_OUT + [11:11] + read-write + oneToClear + + + EP5_IN + [10:10] + read-write + oneToClear + + + EP4_OUT + [9:9] + read-write + oneToClear + + + EP4_IN + [8:8] + read-write + oneToClear + + + EP3_OUT + [7:7] + read-write + oneToClear + + + EP3_IN + [6:6] + read-write + oneToClear + + + EP2_OUT + [5:5] + read-write + oneToClear + + + EP2_IN + [4:4] + read-write + oneToClear + + + EP1_OUT + [3:3] + read-write + oneToClear + + + EP1_IN + [2:2] + read-write + oneToClear + + + EP0_OUT + [1:1] + read-write + oneToClear + + + EP0_IN + [0:0] + read-write + oneToClear + + + + + EP_STALL_ARM + 0x00000068 + Device: this bit must be set in conjunction with the `STALL` bit in the buffer control register to send a STALL on EP0. The device controller clears these bits when a SETUP packet is received because the USB spec requires that a STALL condition is cleared when a SETUP packet is received. + 0x00000000 + + + EP0_OUT + [1:1] + read-write + + + EP0_IN + [0:0] + read-write + + + + + NAK_POLL + 0x0000006c + Used by the host controller. Sets the wait time in microseconds before trying again if the device replies with a NAK. + 0x00100010 + + + DELAY_FS + NAK polling interval for a full speed device + [25:16] + read-write + + + DELAY_LS + NAK polling interval for a low speed device + [9:0] + read-write + + + + + EP_STATUS_STALL_NAK + 0x00000070 + Device: bits are set when the `IRQ_ON_NAK` or `IRQ_ON_STALL` bits are set. For EP0 this comes from `SIE_CTRL`. For all other endpoints it comes from the endpoint control register. + 0x00000000 + + + EP15_OUT + [31:31] + read-write + oneToClear + + + EP15_IN + [30:30] + read-write + oneToClear + + + EP14_OUT + [29:29] + read-write + oneToClear + + + EP14_IN + [28:28] + read-write + oneToClear + + + EP13_OUT + [27:27] + read-write + oneToClear + + + EP13_IN + [26:26] + read-write + oneToClear + + + EP12_OUT + [25:25] + read-write + oneToClear + + + EP12_IN + [24:24] + read-write + oneToClear + + + EP11_OUT + [23:23] + read-write + oneToClear + + + EP11_IN + [22:22] + read-write + oneToClear + + + EP10_OUT + [21:21] + read-write + oneToClear + + + EP10_IN + [20:20] + read-write + oneToClear + + + EP9_OUT + [19:19] + read-write + oneToClear + + + EP9_IN + [18:18] + read-write + oneToClear + + + EP8_OUT + [17:17] + read-write + oneToClear + + + EP8_IN + [16:16] + read-write + oneToClear + + + EP7_OUT + [15:15] + read-write + oneToClear + + + EP7_IN + [14:14] + read-write + oneToClear + + + EP6_OUT + [13:13] + read-write + oneToClear + + + EP6_IN + [12:12] + read-write + oneToClear + + + EP5_OUT + [11:11] + read-write + oneToClear + + + EP5_IN + [10:10] + read-write + oneToClear + + + EP4_OUT + [9:9] + read-write + oneToClear + + + EP4_IN + [8:8] + read-write + oneToClear + + + EP3_OUT + [7:7] + read-write + oneToClear + + + EP3_IN + [6:6] + read-write + oneToClear + + + EP2_OUT + [5:5] + read-write + oneToClear + + + EP2_IN + [4:4] + read-write + oneToClear + + + EP1_OUT + [3:3] + read-write + oneToClear + + + EP1_IN + [2:2] + read-write + oneToClear + + + EP0_OUT + [1:1] + read-write + oneToClear + + + EP0_IN + [0:0] + read-write + oneToClear + + + + + USB_MUXING + 0x00000074 + Where to connect the USB controller. Should be to_phy by default. + 0x00000000 + + + SOFTCON + [3:3] + read-write + + + TO_DIGITAL_PAD + [2:2] + read-write + + + TO_EXTPHY + [1:1] + read-write + + + TO_PHY + [0:0] + read-write + + + + + USB_PWR + 0x00000078 + Overrides for the power signals in the event that the VBUS signals are not hooked up to GPIO. Set the value of the override and then the override enable so switch over to the override value. + 0x00000000 + + + OVERCURR_DETECT_EN + [5:5] + read-write + + + OVERCURR_DETECT + [4:4] + read-write + + + VBUS_DETECT_OVERRIDE_EN + [3:3] + read-write + + + VBUS_DETECT + [2:2] + read-write + + + VBUS_EN_OVERRIDE_EN + [1:1] + read-write + + + VBUS_EN + [0:0] + read-write + + + + + USBPHY_DIRECT + 0x0000007c + Note that most functions are driven directly from usb_fsls controller. This register allows more detailed control/status from the USB PHY. Useful for debug but not expected to be used in normal operation + Use in conjunction with usbphy_direct_override register + 0x00000000 + + + DM_OVV + Status bit from USB PHY + [22:22] + read-only + + + DP_OVV + Status bit from USB PHY + [21:21] + read-only + + + DM_OVCN + Status bit from USB PHY + [20:20] + read-only + + + DP_OVCN + Status bit from USB PHY + [19:19] + read-only + + + RX_DM + Status bit from USB PHY + DPM pin state + [18:18] + read-only + + + RX_DP + Status bit from USB PHY + DPP pin state + [17:17] + read-only + + + RX_DD + Status bit from USB PHY + RX Diff data + [16:16] + read-only + + + TX_DIFFMODE + [15:15] + read-write + + + TX_FSSLEW + [14:14] + read-write + + + TX_PD + [13:13] + read-write + + + RX_PD + [12:12] + read-write + + + TX_DM + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + TX_SEMODE=0, Ignored + TX_SEMODE=1, Drives DPM only. TX_DM_OE=1 to enable drive. DPM=TX_DM + [11:11] + read-write + + + TX_DP + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + TX_SEMODE=0, Drives DPP/DPM diff pair. TX_DP_OE=1 to enable drive. DPP=TX_DP, DPM=~TX_DP + TX_SEMODE=1, Drives DPP only. TX_DP_OE=1 to enable drive. DPP=TX_DP + [10:10] + read-write + + + TX_DM_OE + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + TX_SEMODE=0, Ignored. + TX_SEMODE=1, OE for DPM only. 0 - DPM in Hi-Z state; 1 - DPM driving + [9:9] + read-write + + + TX_DP_OE + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + TX_SEMODE=0, OE for DPP/DPM diff pair. 0 - DPP/DPM in Hi-Z state; 1 - DPP/DPM driving + TX_SEMODE=1, OE for DPP only. 0 - DPP in Hi-Z state; 1 - DPP driving + [8:8] + read-write + + + DM_PULLDN_EN + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + 1 - Enable Rpd on DPM + [6:6] + read-write + + + DM_PULLUP_EN + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + 1 - Enable Rpu on DPM + [5:5] + read-write + + + DM_PULLUP_HISEL + when dm_pullup_en is set high, this enables second resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + [4:4] + read-write + + + DP_PULLDN_EN + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + 1 - Enable Rpd on DPP + [2:2] + read-write + + + DP_PULLUP_EN + Value to drive to USB PHY when override enable is set (which will override the default value or value driven from USB controller + [1:1] + read-write + + + DP_PULLUP_HISEL + when dp_pullup_en is set high, this enables second resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 + [0:0] + read-write + + + + + USBPHY_DIRECT_OVERRIDE + 0x00000080 + 0x00000000 + + + TX_DIFFMODE_OVERRIDE_EN + [15:15] + read-write + + + DM_PULLUP_OVERRIDE_EN + [12:12] + read-write + + + TX_FSSLEW_OVERRIDE_EN + [11:11] + read-write + + + TX_PD_OVERRIDE_EN + [10:10] + read-write + + + RX_PD_OVERRIDE_EN + [9:9] + read-write + + + TX_DM_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [8:8] + read-write + + + TX_DP_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [7:7] + read-write + + + TX_DM_OE_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [6:6] + read-write + + + TX_DP_OE_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [5:5] + read-write + + + DM_PULLDN_EN_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [4:4] + read-write + + + DP_PULLDN_EN_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [3:3] + read-write + + + DP_PULLUP_EN_OVERRIDE_EN + Override default value or value driven from USB Controller to PHY + [2:2] + read-write + + + DM_PULLUP_HISEL_OVERRIDE_EN + [1:1] + read-write + + + DP_PULLUP_HISEL_OVERRIDE_EN + [0:0] + read-write + + + + + USBPHY_TRIM + 0x00000084 + Note that most functions are driven directly from usb_fsls controller. This register allows more detailed control/status from the USB PHY. Useful for debug but not expected to be used in normal operation + 0x00001f1f + + + DM_PULLDN_TRIM + Value to drive to USB PHY + DM pulldown resistor trim control + Experimental data suggests that the reset value will work, but this register allows adjustment if required + [12:8] + read-write + + + DP_PULLDN_TRIM + Value to drive to USB PHY + DP pulldown resistor trim control + Experimental data suggests that the reset value will work, but this register allows adjustment if required + [4:0] + read-write + + + + + INTR + 0x0000008c + Raw Interrupts + 0x00000000 + + + EP_STALL_NAK + Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + [19:19] + read-only + + + ABORT_DONE + Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + [18:18] + read-only + + + DEV_SOF + Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + [17:17] + read-only + + + SETUP_REQ + Device. Source: SIE_STATUS.SETUP_REC + [16:16] + read-only + + + DEV_RESUME_FROM_HOST + Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [15:15] + read-only + + + DEV_SUSPEND + Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + [14:14] + read-only + + + DEV_CONN_DIS + Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + [13:13] + read-only + + + BUS_RESET + Source: SIE_STATUS.BUS_RESET + [12:12] + read-only + + + VBUS_DETECT + Source: SIE_STATUS.VBUS_DETECT + [11:11] + read-only + + + STALL + Source: SIE_STATUS.STALL_REC + [10:10] + read-only + + + ERROR_CRC + Source: SIE_STATUS.CRC_ERROR + [9:9] + read-only + + + ERROR_BIT_STUFF + Source: SIE_STATUS.BIT_STUFF_ERROR + [8:8] + read-only + + + ERROR_RX_OVERFLOW + Source: SIE_STATUS.RX_OVERFLOW + [7:7] + read-only + + + ERROR_RX_TIMEOUT + Source: SIE_STATUS.RX_TIMEOUT + [6:6] + read-only + + + ERROR_DATA_SEQ + Source: SIE_STATUS.DATA_SEQ_ERROR + [5:5] + read-only + + + BUFF_STATUS + Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + [4:4] + read-only + + + TRANS_COMPLETE + Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + [3:3] + read-only + + + HOST_SOF + Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + [2:2] + read-only + + + HOST_RESUME + Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [1:1] + read-only + + + HOST_CONN_DIS + Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + [0:0] + read-only + + + + + INTE + 0x00000090 + Interrupt Enable + 0x00000000 + + + EP_STALL_NAK + Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + [19:19] + read-write + + + ABORT_DONE + Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + [18:18] + read-write + + + DEV_SOF + Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + [17:17] + read-write + + + SETUP_REQ + Device. Source: SIE_STATUS.SETUP_REC + [16:16] + read-write + + + DEV_RESUME_FROM_HOST + Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [15:15] + read-write + + + DEV_SUSPEND + Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + [14:14] + read-write + + + DEV_CONN_DIS + Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + [13:13] + read-write + + + BUS_RESET + Source: SIE_STATUS.BUS_RESET + [12:12] + read-write + + + VBUS_DETECT + Source: SIE_STATUS.VBUS_DETECT + [11:11] + read-write + + + STALL + Source: SIE_STATUS.STALL_REC + [10:10] + read-write + + + ERROR_CRC + Source: SIE_STATUS.CRC_ERROR + [9:9] + read-write + + + ERROR_BIT_STUFF + Source: SIE_STATUS.BIT_STUFF_ERROR + [8:8] + read-write + + + ERROR_RX_OVERFLOW + Source: SIE_STATUS.RX_OVERFLOW + [7:7] + read-write + + + ERROR_RX_TIMEOUT + Source: SIE_STATUS.RX_TIMEOUT + [6:6] + read-write + + + ERROR_DATA_SEQ + Source: SIE_STATUS.DATA_SEQ_ERROR + [5:5] + read-write + + + BUFF_STATUS + Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + [4:4] + read-write + + + TRANS_COMPLETE + Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + [3:3] + read-write + + + HOST_SOF + Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + [2:2] + read-write + + + HOST_RESUME + Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [1:1] + read-write + + + HOST_CONN_DIS + Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + [0:0] + read-write + + + + + INTF + 0x00000094 + Interrupt Force + 0x00000000 + + + EP_STALL_NAK + Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + [19:19] + read-write + + + ABORT_DONE + Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + [18:18] + read-write + + + DEV_SOF + Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + [17:17] + read-write + + + SETUP_REQ + Device. Source: SIE_STATUS.SETUP_REC + [16:16] + read-write + + + DEV_RESUME_FROM_HOST + Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [15:15] + read-write + + + DEV_SUSPEND + Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + [14:14] + read-write + + + DEV_CONN_DIS + Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + [13:13] + read-write + + + BUS_RESET + Source: SIE_STATUS.BUS_RESET + [12:12] + read-write + + + VBUS_DETECT + Source: SIE_STATUS.VBUS_DETECT + [11:11] + read-write + + + STALL + Source: SIE_STATUS.STALL_REC + [10:10] + read-write + + + ERROR_CRC + Source: SIE_STATUS.CRC_ERROR + [9:9] + read-write + + + ERROR_BIT_STUFF + Source: SIE_STATUS.BIT_STUFF_ERROR + [8:8] + read-write + + + ERROR_RX_OVERFLOW + Source: SIE_STATUS.RX_OVERFLOW + [7:7] + read-write + + + ERROR_RX_TIMEOUT + Source: SIE_STATUS.RX_TIMEOUT + [6:6] + read-write + + + ERROR_DATA_SEQ + Source: SIE_STATUS.DATA_SEQ_ERROR + [5:5] + read-write + + + BUFF_STATUS + Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + [4:4] + read-write + + + TRANS_COMPLETE + Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + [3:3] + read-write + + + HOST_SOF + Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + [2:2] + read-write + + + HOST_RESUME + Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [1:1] + read-write + + + HOST_CONN_DIS + Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + [0:0] + read-write + + + + + INTS + 0x00000098 + Interrupt status after masking & forcing + 0x00000000 + + + EP_STALL_NAK + Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + [19:19] + read-only + + + ABORT_DONE + Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. + [18:18] + read-only + + + DEV_SOF + Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD + [17:17] + read-only + + + SETUP_REQ + Device. Source: SIE_STATUS.SETUP_REC + [16:16] + read-only + + + DEV_RESUME_FROM_HOST + Set when the device receives a resume from the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [15:15] + read-only + + + DEV_SUSPEND + Set when the device suspend state changes. Cleared by writing to SIE_STATUS.SUSPENDED + [14:14] + read-only + + + DEV_CONN_DIS + Set when the device connection state changes. Cleared by writing to SIE_STATUS.CONNECTED + [13:13] + read-only + + + BUS_RESET + Source: SIE_STATUS.BUS_RESET + [12:12] + read-only + + + VBUS_DETECT + Source: SIE_STATUS.VBUS_DETECT + [11:11] + read-only + + + STALL + Source: SIE_STATUS.STALL_REC + [10:10] + read-only + + + ERROR_CRC + Source: SIE_STATUS.CRC_ERROR + [9:9] + read-only + + + ERROR_BIT_STUFF + Source: SIE_STATUS.BIT_STUFF_ERROR + [8:8] + read-only + + + ERROR_RX_OVERFLOW + Source: SIE_STATUS.RX_OVERFLOW + [7:7] + read-only + + + ERROR_RX_TIMEOUT + Source: SIE_STATUS.RX_TIMEOUT + [6:6] + read-only + + + ERROR_DATA_SEQ + Source: SIE_STATUS.DATA_SEQ_ERROR + [5:5] + read-only + + + BUFF_STATUS + Raised when any bit in BUFF_STATUS is set. Clear by clearing all bits in BUFF_STATUS. + [4:4] + read-only + + + TRANS_COMPLETE + Raised every time SIE_STATUS.TRANS_COMPLETE is set. Clear by writing to this bit. + [3:3] + read-only + + + HOST_SOF + Host: raised every time the host sends a SOF (Start of Frame). Cleared by reading SOF_RD + [2:2] + read-only + + + HOST_RESUME + Host: raised when a device wakes up the host. Cleared by writing to SIE_STATUS.RESUME_REMOTE + [1:1] + read-only + + + HOST_CONN_DIS + Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED + [0:0] + read-only + + + + + + + USB_DPRAM + DPRAM layout for USB device. + 0x50100000 + + 0 + 256 + registers + + + + SETUP_PACKET_LOW + 0x00000000 + Bytes 0-3 of the SETUP packet from the host. + 0x00000000 + + + WVALUE + [31:16] + read-write + + + BREQUEST + [15:8] + read-write + + + BMREQUESTTYPE + [7:0] + read-write + + + + + SETUP_PACKET_HIGH + 0x00000004 + Bytes 4-7 of the setup packet from the host. + 0x00000000 + + + WLENGTH + [31:16] + read-write + + + WINDEX + [15:0] + read-write + + + + + EP1_IN_CONTROL + 0x00000008 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP1_OUT_CONTROL + 0x0000000c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP2_IN_CONTROL + 0x00000010 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP2_OUT_CONTROL + 0x00000014 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP3_IN_CONTROL + 0x00000018 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP3_OUT_CONTROL + 0x0000001c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP4_IN_CONTROL + 0x00000020 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP4_OUT_CONTROL + 0x00000024 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP5_IN_CONTROL + 0x00000028 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP5_OUT_CONTROL + 0x0000002c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP6_IN_CONTROL + 0x00000030 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP6_OUT_CONTROL + 0x00000034 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP7_IN_CONTROL + 0x00000038 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP7_OUT_CONTROL + 0x0000003c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP8_IN_CONTROL + 0x00000040 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP8_OUT_CONTROL + 0x00000044 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP9_IN_CONTROL + 0x00000048 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP9_OUT_CONTROL + 0x0000004c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP10_IN_CONTROL + 0x00000050 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP10_OUT_CONTROL + 0x00000054 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP11_IN_CONTROL + 0x00000058 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP11_OUT_CONTROL + 0x0000005c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP12_IN_CONTROL + 0x00000060 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP12_OUT_CONTROL + 0x00000064 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP13_IN_CONTROL + 0x00000068 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP13_OUT_CONTROL + 0x0000006c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP14_IN_CONTROL + 0x00000070 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP14_OUT_CONTROL + 0x00000074 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP15_IN_CONTROL + 0x00000078 + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP15_OUT_CONTROL + 0x0000007c + 0x00000000 + + + ENABLE + Enable this endpoint. The device will not reply to any packets for this endpoint if this bit is not set. + [31:31] + read-write + + + DOUBLE_BUFFERED + This endpoint is double buffered. + [30:30] + read-write + + + INTERRUPT_PER_BUFF + Trigger an interrupt each time a buffer is done. + [29:29] + read-write + + + INTERRUPT_PER_DOUBLE_BUFF + Trigger an interrupt each time both buffers are done. Only valid in double buffered mode. + [28:28] + read-write + + + ENDPOINT_TYPE + [27:26] + read-write + + + Control + 0 + + + Isochronous + 1 + + + Bulk + 2 + + + Interrupt + 3 + + + + + INTERRUPT_ON_STALL + Trigger an interrupt if a STALL is sent. Intended for debug only. + [17:17] + read-write + + + INTERRUPT_ON_NAK + Trigger an interrupt if a NAK is sent. Intended for debug only. + [16:16] + read-write + + + BUFFER_ADDRESS + 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. + [15:0] + read-write + + + + + EP0_IN_BUFFER_CONTROL + 0x00000080 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP0_OUT_BUFFER_CONTROL + 0x00000084 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP1_IN_BUFFER_CONTROL + 0x00000088 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP1_OUT_BUFFER_CONTROL + 0x0000008c + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP2_IN_BUFFER_CONTROL + 0x00000090 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP2_OUT_BUFFER_CONTROL + 0x00000094 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP3_IN_BUFFER_CONTROL + 0x00000098 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP3_OUT_BUFFER_CONTROL + 0x0000009c + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP4_IN_BUFFER_CONTROL + 0x000000a0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP4_OUT_BUFFER_CONTROL + 0x000000a4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP5_IN_BUFFER_CONTROL + 0x000000a8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP5_OUT_BUFFER_CONTROL + 0x000000ac + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP6_IN_BUFFER_CONTROL + 0x000000b0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP6_OUT_BUFFER_CONTROL + 0x000000b4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP7_IN_BUFFER_CONTROL + 0x000000b8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP7_OUT_BUFFER_CONTROL + 0x000000bc + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP8_IN_BUFFER_CONTROL + 0x000000c0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP8_OUT_BUFFER_CONTROL + 0x000000c4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP9_IN_BUFFER_CONTROL + 0x000000c8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP9_OUT_BUFFER_CONTROL + 0x000000cc + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP10_IN_BUFFER_CONTROL + 0x000000d0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP10_OUT_BUFFER_CONTROL + 0x000000d4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP11_IN_BUFFER_CONTROL + 0x000000d8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP11_OUT_BUFFER_CONTROL + 0x000000dc + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP12_IN_BUFFER_CONTROL + 0x000000e0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP12_OUT_BUFFER_CONTROL + 0x000000e4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP13_IN_BUFFER_CONTROL + 0x000000e8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP13_OUT_BUFFER_CONTROL + 0x000000ec + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP14_IN_BUFFER_CONTROL + 0x000000f0 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP14_OUT_BUFFER_CONTROL + 0x000000f4 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP15_IN_BUFFER_CONTROL + 0x000000f8 + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + EP15_OUT_BUFFER_CONTROL + 0x000000fc + Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. + Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. + 0x00000000 + + + FULL_1 + Buffer 1 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [31:31] + read-write + + + LAST_1 + Buffer 1 is the last buffer of the transfer. + [30:30] + read-write + + + PID_1 + The data pid of buffer 1. + [29:29] + read-write + + + DOUBLE_BUFFER_ISO_OFFSET + The number of bytes buffer 1 is offset from buffer 0 in Isochronous mode. Only valid in double buffered mode for an Isochronous endpoint. + For a non Isochronous endpoint the offset is always 64 bytes. + [28:27] + read-write + + + 128 + 0 + + + 256 + 1 + + + 512 + 2 + + + 1024 + 3 + + + + + AVAILABLE_1 + Buffer 1 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [26:26] + read-write + + + LENGTH_1 + The length of the data in buffer 1. + [25:16] + read-write + + + FULL_0 + Buffer 0 is full. For an IN transfer (TX to the host) the bit is set to indicate the data is valid. For an OUT transfer (RX from the host) this bit should be left as a 0. The host will set it when it has filled the buffer with data. + [15:15] + read-write + + + LAST_0 + Buffer 0 is the last buffer of the transfer. + [14:14] + read-write + + + PID_0 + The data pid of buffer 0. + [13:13] + read-write + + + RESET + Reset the buffer selector to buffer 0. + [12:12] + read-write + + + STALL + Reply with a stall (valid for both buffers). + [11:11] + read-write + + + AVAILABLE_0 + Buffer 0 is available. This bit is set to indicate the buffer can be used by the controller. The controller clears the available bit when writing the status back. + [10:10] + read-write + + + LENGTH_0 + The length of the data in buffer 0. + [9:0] + read-write + + + + + + + TBMAN + Testbench manager. Allows the programmer to know what platform their software is running on. + 0x4006c000 + + 0 + 4 + registers + + + + PLATFORM + 0x00000000 + Indicates the type of platform in use + 0x00000005 + + + FPGA + Indicates the platform is an FPGA + [1:1] + read-only + + + ASIC + Indicates the platform is an ASIC + [0:0] + read-only + + + + + + + VREG_AND_CHIP_RESET + control and status for on-chip voltage regulator and chip level reset subsystem + 0x40064000 + + 0 + 12 + registers + + + + VREG + 0x00000000 + Voltage regulator control and status + 0x000000b1 + + + ROK + regulation status + 0=not in regulation, 1=in regulation + [12:12] + read-only + + + VSEL + output voltage select + 0000 to 0101 - 0.80V + 0110 - 0.85V + 0111 - 0.90V + 1000 - 0.95V + 1001 - 1.00V + 1010 - 1.05V + 1011 - 1.10V (default) + 1100 - 1.15V + 1101 - 1.20V + 1110 - 1.25V + 1111 - 1.30V + [7:4] + read-write + + + HIZ + high impedance mode select + 0=not in high impedance mode, 1=in high impedance mode + [1:1] + read-write + + + EN + enable + 0=not enabled, 1=enabled + [0:0] + read-write + + + + + BOD + 0x00000004 + brown-out detection control + 0x00000091 + + + VSEL + threshold select + 0000 - 0.473V + 0001 - 0.516V + 0010 - 0.559V + 0011 - 0.602V + 0100 - 0.645V + 0101 - 0.688V + 0110 - 0.731V + 0111 - 0.774V + 1000 - 0.817V + 1001 - 0.860V (default) + 1010 - 0.903V + 1011 - 0.946V + 1100 - 0.989V + 1101 - 1.032V + 1110 - 1.075V + 1111 - 1.118V + [7:4] + read-write + + + EN + enable + 0=not enabled, 1=enabled + [0:0] + read-write + + + + + CHIP_RESET + 0x00000008 + Chip reset control and status + 0x00000000 + + + PSM_RESTART_FLAG + This is set by psm_restart from the debugger. + Its purpose is to branch bootcode to a safe mode when the debugger has issued a psm_restart in order to recover from a boot lock-up. + In the safe mode the debugger can repair the boot code, clear this flag then reboot the processor. + [24:24] + read-write + oneToClear + + + HAD_PSM_RESTART + Last reset was from the debug port + [20:20] + read-only + + + HAD_RUN + Last reset was from the RUN pin + [16:16] + read-only + + + HAD_POR + Last reset was from the power-on reset or brown-out detection blocks + [8:8] + read-only + + + + + + + RTC + Register block to control RTC + 0x4005c000 + + 0 + 48 + registers + + + RTC_IRQ + 25 + + + + CLKDIV_M1 + 0x00000000 + Divider minus 1 for the 1 second counter. Safe to change the value when RTC is not enabled. + 0x00000000 + + + CLKDIV_M1 + [15:0] + read-write + + + + + SETUP_0 + 0x00000004 + RTC setup register 0 + 0x00000000 + + + YEAR + Year + [23:12] + read-write + + + MONTH + Month (1..12) + [11:8] + read-write + + + DAY + Day of the month (1..31) + [4:0] + read-write + + + + + SETUP_1 + 0x00000008 + RTC setup register 1 + 0x00000000 + + + DOTW + Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7 + [26:24] + read-write + + + HOUR + Hours + [20:16] + read-write + + + MIN + Minutes + [13:8] + read-write + + + SEC + Seconds + [5:0] + read-write + + + + + CTRL + 0x0000000c + RTC Control and status + 0x00000000 + + + FORCE_NOTLEAPYEAR + If set, leapyear is forced off. + Useful for years divisible by 100 but not by 400 + [8:8] + read-write + + + LOAD + Load RTC + [4:4] + write-only + + + RTC_ACTIVE + RTC enabled (running) + [1:1] + read-only + + + RTC_ENABLE + Enable RTC + [0:0] + read-write + + + + + IRQ_SETUP_0 + 0x00000010 + Interrupt setup register 0 + 0x00000000 + + + MATCH_ACTIVE + [29:29] + read-only + + + MATCH_ENA + Global match enable. Don't change any other value while this one is enabled + [28:28] + read-write + + + YEAR_ENA + Enable year matching + [26:26] + read-write + + + MONTH_ENA + Enable month matching + [25:25] + read-write + + + DAY_ENA + Enable day matching + [24:24] + read-write + + + YEAR + Year + [23:12] + read-write + + + MONTH + Month (1..12) + [11:8] + read-write + + + DAY + Day of the month (1..31) + [4:0] + read-write + + + + + IRQ_SETUP_1 + 0x00000014 + Interrupt setup register 1 + 0x00000000 + + + DOTW_ENA + Enable day of the week matching + [31:31] + read-write + + + HOUR_ENA + Enable hour matching + [30:30] + read-write + + + MIN_ENA + Enable minute matching + [29:29] + read-write + + + SEC_ENA + Enable second matching + [28:28] + read-write + + + DOTW + Day of the week + [26:24] + read-write + + + HOUR + Hours + [20:16] + read-write + + + MIN + Minutes + [13:8] + read-write + + + SEC + Seconds + [5:0] + read-write + + + + + RTC_1 + 0x00000018 + RTC register 1. + 0x00000000 + + + YEAR + Year + [23:12] + read-only + + + MONTH + Month (1..12) + [11:8] + read-only + + + DAY + Day of the month (1..31) + [4:0] + read-only + + + + + RTC_0 + 0x0000001c + RTC register 0 + Read this before RTC 1! + 0x00000000 + + + DOTW + Day of the week + [26:24] + read-only + modify + + + HOUR + Hours + [20:16] + read-only + modify + + + MIN + Minutes + [13:8] + read-only + modify + + + SEC + Seconds + [5:0] + read-only + modify + + + + + INTR + 0x00000020 + Raw Interrupts + 0x00000000 + + + RTC + [0:0] + read-only + + + + + INTE + 0x00000024 + Interrupt Enable + 0x00000000 + + + RTC + [0:0] + read-write + + + + + INTF + 0x00000028 + Interrupt Force + 0x00000000 + + + RTC + [0:0] + read-write + + + + + INTS + 0x0000002c + Interrupt status after masking & forcing + 0x00000000 + + + RTC + [0:0] + read-only + + + + + + + diff --git a/lib/arch/svd2rob.py b/lib/arch/svd2rob.py new file mode 100644 index 0000000..851aced --- /dev/null +++ b/lib/arch/svd2rob.py @@ -0,0 +1,263 @@ +# +# This program converts a svd file +# into the types needed to programm +# the board using the Robotics Language +# +# Author: Thiago Borges de Oliveira +# Date: 24-Jun-2024 +# + +import sys +import re +import xml.etree.ElementTree as ET + +tree = ET.parse(sys.argv[1]) +root = tree.getroot() + +header = """ +/* + * Part of the Robotics Language Standard Library, under the + * Apache License v2.0. + * + * This file was machine generated from %s. Don't edit. + */ +""" % sys.argv[1] +print(header) + +peripheral_header = """ +/* Types and registers for {name} {desc} */ +""" + +template_type = """\ + type {type}_t {{ +{fields} + }} +""" + +template_register = """\ + // {prefix_desc}{description} + register {type}_t {prefix_name}{name} at {addr}; +""" + +template_field = "\t{name: 0: + fsize = 0 + if size == 1: + ftype = "false;" + fsize = 1 + elif size in [2,3,4,5,6,7,8]: + ftype = "uint%d(0);" % size + fsize = size + elif size >= 32: + ftype = "uint32(0);" + fsize = 32 + elif size >= 16: + ftype = "uint16(0);" + fsize = 16 + elif size > 8: + ftype = "uint8(0);" + fsize = 8 + fres = {} + fres['name'] = '_res%d' % resnum + if first: + fres['description'] = 'Reserved, %d bits' % (orig_size,) + first = False + else: + fres['description'] = '' + fres['type'] = ftype + fres['start'] = start + start = start + fsize + size = size - fsize + resnum = resnum + 1; + reservedfields.append(fres) + return resnum + + +def get_fields_str(fields_node, size): + if fields_node == None: + return "" + + fields = [] + for field_node in fields_node.iter('field'): + bitRange = field_node.find('bitRange') + if bitRange == None: + bitOffset = field_node.find('bitOffset').text + bitWidth = field_node.find('bitWidth').text + bitRange = "[%d:%s]" % (int(bitOffset) + int(bitWidth)-1, bitOffset) + else: + bitRange = bitRange.text + field = get_field_for_type(bitRange) + field['name'] = field_node.find('name').text + + field['description'] = '' + description_node = field_node.find('description') + if description_node is not None: + field['description'] = clear_description(description_node.text) + + fields.append(field) + + fields = sorted(fields, key=lambda field: field['start']) + + # add missing fields as reserved + reservedfields = [] + i = 0 + resnum = 1 + for f in fields: + if f['start'] > i: + #print("start: %d, i: %d\n" % (f['start'], i)) + resnum = add_reserved(reservedfields, i, f['start']-i, resnum) + i = f['end'] + 1 + + # missing bits at end + if i < size: + add_reserved(reservedfields, i-1, size-i, resnum) + + fields = fields + reservedfields + maxlen = max([len(f['name']) for f in fields]) + custom_template_field = template_field.replace('xxlenxx', str(maxlen)) + fields = sorted(fields, key=lambda field: field['start']) + return "\n".join([custom_template_field.format(**f) for f in fields]) + + +# map dependencies to generate peripherals prefixes +derived = {} +for peripheral in root.iterfind('.//peripheral[@derivedFrom]'): + name = peripheral.find('name').text + derivedFrom = peripheral.attrib['derivedFrom'] + derived[name] = derivedFrom + # register the inherited peripheral to prefix it latter + derived[derivedFrom] = derivedFrom + + +# map repeated register names +repeated_regs = {} +for register in root.iterfind('.//register'): + name = register.find('name').text + if name in repeated_regs: + repeated_regs[name] = True + else: + repeated_regs[name] = False + + +# generate code! +def print_tags(tags): + for t in tags: + node = root.find(t) + if node is not None: + print("\t%s: %s" % (t, node.text)) + +print("/*") +print_tags(['vendor', 'name', 'series', 'version', 'description']) +print("*/") + +for peripheral in root.iter('peripheral'): + # peripheral name + pname = peripheral.find('name').text + + # peripheral description + pdesc_node = peripheral.find('description') + pdesc = '' + if pdesc_node is not None: + pdesc = "\n " + clear_description(pdesc_node.text) + "\n" + + # peripheral base address + baseAddr = peripheral.find('baseAddress').text + + # print peripheral header + print(peripheral_header.format(name=pname,desc=pdesc)) + + # prefix base and derived peripherals registers + prefix_name = '' + prefix_desc = '' + if pname in derived: + prefix_name = pname + "_" + prefix_desc = pname + " " + + # loop through base registers + registers = None + isDerived = False + if (pname in derived) and (derived[pname] != pname): + isDerived = True + # change the peripheral to the inherited one + peripheral = root.find(".//peripheral[name = '%s']" % derived[pname]) + + for register in peripheral.iter('register'): + regdata = {} + regdata['prefix_desc'] = prefix_desc + regdata['prefix_name'] = prefix_name + regdata['name'] = register.find('name').text + + if repeated_regs[regdata['name']] and not isDerived: + # The register being created exists in more than one peripheral + # Thus, we prefix it with the peripheral name + regdata['name'] = pname + '_' + regdata['name'] + + if isDerived: + original_register = register.find('name').text + inherited_name = '' + if repeated_regs[original_register]: + inherited_name = peripheral.find('name').text + "_" + regdata['type'] = inherited_name + register.find('name').text + else: + regdata['type'] = regdata['name'] + + regdata['description'] = '' + description_node = register.find('description') + if description_node is not None: + regdata['description'] = clear_description(description_node.text) + + offset = register.find('addressOffset').text + intoffset = int(offset, 16) + if intoffset == 0: + regdata['addr'] = "%s" % (baseAddr) + else: + intaddr = int(baseAddr, 16) + intoffset + regdata['addr'] = "%#x" % (intaddr) + + # print register tree + size = 0 + size_node = register.find('size') + if size_node is not None: + size = int(size_node.text, 0) + + fields = register.find('fields') + if fields == None: + regdata['type'] = get_type_for_size(size) + print(template_register.format(**regdata)) + else: + if not isDerived: + regdata['fields'] = get_fields_str(fields, size) + print(template_type.format(**regdata)) + print(template_register.format(**regdata)) + diff --git a/src/BackLLVM.cpp b/src/BackLLVM.cpp index f557522..43c9977 100644 --- a/src/BackLLVM.cpp +++ b/src/BackLLVM.cpp @@ -62,6 +62,8 @@ TargetInfo supportedTargets[__last_target] = { {rb_avr, "atmega1284p", "avr", "atmega1284p", "+avr51", tint16}, {rb_arm, "stm32f1", "thumbv7m-none-eabi", "cortex-m3", "", tint32}, + + {rb_arm, "rp2040", "thumbv6m-none-eabi", "cortex-m0plus", "+soft-float", tint32}, {rb_xtensa, "esp32", "xtensa", "", "", tint32}, }; diff --git a/src/BackLLVM.h b/src/BackLLVM.h index 82e8ea5..dc1cb49 100644 --- a/src/BackLLVM.h +++ b/src/BackLLVM.h @@ -32,6 +32,9 @@ enum SupportedTargets { // stm32 st_stm32f1, + + // raspberry pico + st_rp2040, // awaiting backend goes mainstream st_esp32, diff --git a/src/BuildTypes.cpp b/src/BuildTypes.cpp index 5977d59..40dc609 100644 --- a/src/BuildTypes.cpp +++ b/src/BuildTypes.cpp @@ -33,8 +33,28 @@ BuildTypes::BuildTypes(DataType targetPointerType, Program *program) : tinfo[tint7u] = {"uint7", 7, Type::getIntNTy(global_context, 7), dwarf::DW_ATE_unsigned}; tinfo[tint8u] = {"uint8", 8, Type::getInt8Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tint9u] = {"uint9", 9, Type::getIntNTy(global_context, 9), dwarf::DW_ATE_unsigned}; + tinfo[tint10u] = {"uint10", 10, Type::getIntNTy(global_context, 10),dwarf::DW_ATE_unsigned}; + tinfo[tint11u] = {"uint11", 11, Type::getIntNTy(global_context, 11),dwarf::DW_ATE_unsigned}; tinfo[tint12u] = {"uint12", 12, Type::getIntNTy(global_context, 12),dwarf::DW_ATE_unsigned}; + tinfo[tint13u] = {"uint13", 13, Type::getIntNTy(global_context, 13),dwarf::DW_ATE_unsigned}; + tinfo[tint14u] = {"uint14", 14, Type::getIntNTy(global_context, 14),dwarf::DW_ATE_unsigned}; + tinfo[tint15u] = {"uint15", 15, Type::getIntNTy(global_context, 15),dwarf::DW_ATE_unsigned}; tinfo[tint16u] = {"uint16", 16, Type::getInt16Ty(global_context), dwarf::DW_ATE_unsigned}; + tinfo[tint17u] = {"uint17", 17, Type::getIntNTy(global_context, 17),dwarf::DW_ATE_unsigned}; + tinfo[tint18u] = {"uint18", 18, Type::getIntNTy(global_context, 18),dwarf::DW_ATE_unsigned}; + tinfo[tint19u] = {"uint19", 19, Type::getIntNTy(global_context, 19),dwarf::DW_ATE_unsigned}; + tinfo[tint20u] = {"uint20", 20, Type::getIntNTy(global_context, 20),dwarf::DW_ATE_unsigned}; + tinfo[tint21u] = {"uint21", 21, Type::getIntNTy(global_context, 21),dwarf::DW_ATE_unsigned}; + tinfo[tint22u] = {"uint22", 22, Type::getIntNTy(global_context, 22),dwarf::DW_ATE_unsigned}; + tinfo[tint23u] = {"uint23", 23, Type::getIntNTy(global_context, 23),dwarf::DW_ATE_unsigned}; + tinfo[tint24u] = {"uint24", 24, Type::getIntNTy(global_context, 24),dwarf::DW_ATE_unsigned}; + tinfo[tint25u] = {"uint25", 25, Type::getIntNTy(global_context, 25),dwarf::DW_ATE_unsigned}; + tinfo[tint26u] = {"uint26", 26, Type::getIntNTy(global_context, 26),dwarf::DW_ATE_unsigned}; + tinfo[tint27u] = {"uint27", 27, Type::getIntNTy(global_context, 27),dwarf::DW_ATE_unsigned}; + tinfo[tint28u] = {"uint28", 28, Type::getIntNTy(global_context, 28),dwarf::DW_ATE_unsigned}; + tinfo[tint29u] = {"uint29", 29, Type::getIntNTy(global_context, 29),dwarf::DW_ATE_unsigned}; + tinfo[tint30u] = {"uint30", 30, Type::getIntNTy(global_context, 30),dwarf::DW_ATE_unsigned}; + tinfo[tint31u] = {"uint31", 31, Type::getIntNTy(global_context, 31),dwarf::DW_ATE_unsigned}; tinfo[tint32u] = {"uint32", 32, Type::getInt32Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tint64u] = {"uint64", 64, Type::getInt64Ty(global_context), dwarf::DW_ATE_unsigned}; tinfo[tfloat] = {"float", 32, Type::getFloatTy(global_context), dwarf::DW_ATE_float}; diff --git a/src/BuildTypes.h b/src/BuildTypes.h index b546d50..2310322 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -12,8 +12,11 @@ typedef int DataType; */ enum BasicDataType {tvoid, tbool, tchar, tint8, tint16, tint32, tint64, - tint2u, tint3u, tint4u, tint5u, tint6u, tint7u, - tint8u, tint9u, tint12u, tint16u, tint32u, tint64u, + tint2u, tint3u, tint4u, tint5u, tint6u, tint7u, tint8u, + tint9u, tint10u, tint11u, tint12u, tint13u, tint14u, tint15u, tint16u, + tint17u, tint18u, tint19u, tint20u, tint21u, tint22u, tint23u, tint24u, + tint25u, tint26u, tint27u, tint28u, tint29u, tint30u, tint31u, tint32u, + tint64u, tfloat, tdouble, tldouble, /* new types here! */ tobject, diff --git a/test/rp2040/Makefile b/test/rp2040/Makefile new file mode 100644 index 0000000..b9d2d99 --- /dev/null +++ b/test/rp2040/Makefile @@ -0,0 +1,57 @@ +ALL=$(patsubst %.rob,out/%,$(wildcard *.rob)) +ALL_LL=$(patsubst %.rob,out/%.ll,$(wildcard *.rob)) +ALL_TT=$(patsubst %.rob,%.tt,$(wildcard *.rob)) +ALL_OO=$(patsubst %.rob,out/%.o,$(wildcard *.rob)) out/stm32f1.o + +TOOL_OPEN_OCD_FOLDER=~/.platformio/packages/tool-openocd +ROBCMP=../../build/robcmp +INCLUDES=-I ../../lib + +ifndef OPT +#OPT=-g -O0 +OPT=-Oz +endif + +LD_FLAGS=-nostdlib -entry=main -L../../lib -Tarch/rp/rp2040/rp2040.ld +LD_FLAGS+=-Bstatic +LD_FLAGS+=--gc-sections +LD_FLAGS+=--lto=thin + +DEPENDS=${ROBCMP} Makefile +LINK_DEPENDS=out/init.o ../../lib/arch/rp/rp2040/boot2.o + +all: out test + +out: + mkdir -p out + +out/init.o : ../../lib/arch/rp/rp2040/init.rob ${DEPENDS} + ${ROBCMP} -a rp2040 ${OPT} -o $@ $< + +out/init.ll : ../../lib/arch/rp/rp2040/init.rob ${DEPENDS} + ${ROBCMP} -a stm32f1 ${OPT} $< > $@ + +out/%.o : %.rob out/init.o ${DEPENDS} + ${ROBCMP} -bdep -a rp2040 ${OPT} ${INCLUDES} -o $@ $< + +out/%.ll : %.rob ${DEPENDS} + ${ROBCMP} -bdep -a rp2040 ${OPT} ${INCLUDES} $< > $@ + +%.tt : %.rob ${DEPENDS} + @-./runtest.sh $< $(patsubst %.rob,out/%,$<) + +out/%.uf2 : out/% + ./elf2uf2/elf2uf2 -v $< $@ + +out/% : out/%.o ${LINK_DEPENDS} + ld.lld ${LD_FLAGS} $^ -o $@ + +%.up : out/%.uf2 + cp out/blink.uf2 /Volumes/RPI-RP2 + +test: ${ALL_TT} + +clean: + @rm -f ${ALL} ${ALL_LL} ${ALL_OO} + @rm out/* + diff --git a/test/rp2040/blink.rob b/test/rp2040/blink.rob new file mode 100644 index 0000000..3f49b6f --- /dev/null +++ b/test/rp2040/blink.rob @@ -0,0 +1,20 @@ +/* + * Blinks the board default led + */ + +use intfs.ports; +use arch.rp.rp2040.mcu; + +int16 main() { + mmcu = rp2040mcu(); + led = mmcu.io25; + + led.mode(port_mode.output); + + loop { + led.set(true); + mmcu.wait_ms(100); + led.set(false); + mmcu.wait_ms(100); + } +} diff --git a/test/rp2040/runtest.sh b/test/rp2040/runtest.sh new file mode 100755 index 0000000..5676a41 --- /dev/null +++ b/test/rp2040/runtest.sh @@ -0,0 +1,27 @@ +#!/bin/bash +#CMD="./robcmp-simavr-debug -c 16000000 -m atmega328p -f $2" +CMD="echo \"no simulator for stm32f1 yet.\"" + +GREEN="\033[0;32m" +RED="\033[0;31m" +NC="\033[0m" + +echo -n " $1 " +make -s $2 +if [ "$?" -eq 0 ]; then + if [ "$V" = "1" ]; then + ${CMD} + else + timeout 10s ${CMD} &> /dev/null + fi + STATUS=$? + #if [ "${STATUS}" -eq 0 ]; then + # echo -e \\r${GREEN}[PASS]\\t\\t${NC} + #else + # echo -e \\r${RED}[FAILED] ${STATUS}\\t${NC} + #fi + ${CMD} +else + echo -e \\r${RED}[BUILD FAILED]\\t${NC} +fi + From fdafb7ff8bb2e6d06201f681533fe232dfe2ee6e Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Sun, 22 Jun 2025 21:17:21 -0300 Subject: [PATCH 111/117] Fix the usage of the same var name in multiple contexts --- src/Load.cpp | 2 ++ src/Program.cpp | 6 +++++- src/Scalar.cpp | 18 ++++++++++-------- src/semantic/PropagateTypes.cpp | 9 ++++++++- test/general/scalar-in-two-contexts.rob | 12 +++++++----- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/Load.cpp b/src/Load.cpp index 3b1eca3..634fb2b 100644 --- a/src/Load.cpp +++ b/src/Load.cpp @@ -134,6 +134,8 @@ Value* Load::getRecursiveField(Identifier &ident, Node *scope, FunctionImpl *fun Node *first = symbols.front(); symbols.pop_front(); Value *alloc = first->getLLVMValue(func); + assert(alloc && "Can't get a field of an unallocated symbol."); + Type *udt = buildTypes->llvmType(first->getDataType()); if (first->isPointerToPointer()) { alloc = Builder->CreateLoad(PointerType::getUnqual(udt), alloc, "deref"); diff --git a/src/Program.cpp b/src/Program.cpp index 02cc660..a7faac4 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -183,7 +183,10 @@ void Program::declareBuiltins() { addSymbol(typeid_decl); } -void Program::generateBuiltins() { +void Program::generateBuiltins() { + auto SavedLoc = Builder->getCurrentDebugLocation(); + Builder->SetCurrentDebugLocation(DebugLoc()); + // generate the typeid declaration Node *decl = findSymbol("typeid"); Value *typeidValue = decl->generate(NULL, NULL, global_alloc); @@ -214,6 +217,7 @@ void Program::generateBuiltins() { Builder->SetInsertPoint(body); Builder->CreateCondBr(CmpVoid, returnVoid, returnTypeid); + Builder->SetCurrentDebugLocation(SavedLoc); } extern bool parseIsCompleted; diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 3859cff..4196aac 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -22,7 +22,9 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc if (!symbol) return NULL; + RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); + Pointer *reg = NULL; Node *stem = NULL; if (ident.isComplex()) { @@ -61,7 +63,10 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc if (hasQualifier(qconst)) return exprv; + // expr->generate changes the location and block + RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); + if (!alloc) alloc = symbol->getLLVMValue(func); @@ -70,9 +75,6 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Value *ret = NULL; setDataType(exprv_dt); - auto sp = RobDbgInfo.currScope(); - auto funit = RobDbgInfo.currFile(); - if (allocblock == global_alloc) { Constant *exprvc = dyn_cast(exprv); if (exprvc == NULL) @@ -94,15 +96,17 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc RobDbgInfo.declareGlobalVar(expr, gv, allocblock); } } else { - RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(allocblock); - AllocaInst *temp = Builder->CreateAlloca(exprv->getType(), dataAddrSpace, 0, name); - alloc = temp; + alloc = Builder->CreateAlloca(exprv->getType(), dataAddrSpace, 0, name); Builder->SetInsertPoint(block); ret = Builder->CreateStore(exprv, alloc, symbol->hasQualifier(qvolatile)); if (debug_info) RobDbgInfo.declareVar(this, alloc, allocblock); + + // the symbol is in another scope + if (alloc && this != symbol) + symbol->setAlloca(alloc); } return ret; @@ -135,7 +139,6 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc if (pm == pm_pointer) currty = PointerType::getUnqual(currty); - RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(allocblock == global_alloc ? global_alloc : block); Value *nvalue = NULL; @@ -175,7 +178,6 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc } if (nvalue != alloc) { - RobDbgInfo.emitLocation(this); const DataLayout &DL = mainmodule->getDataLayout(); Align align = DL.getABITypeAlign(nvalue->getType()); return Builder->CreateAlignedStore(nvalue, alloc, align, symbol->hasQualifier(qvolatile)); diff --git a/src/semantic/PropagateTypes.cpp b/src/semantic/PropagateTypes.cpp index 89679be..bf58113 100644 --- a/src/semantic/PropagateTypes.cpp +++ b/src/semantic/PropagateTypes.cpp @@ -374,6 +374,8 @@ Node* PropagateTypes::visit(FunctionCall& fc) { } Node* PropagateTypes::visit(Matrix& n) { + PropagateTypes::visit((Variable&)n); + // visit elements to propagate their types for(MatrixElement *me : n.getMatrixElements()) { for(ArrayElement *k: me->array->getElements()) { @@ -398,6 +400,8 @@ Node* PropagateTypes::visit(Matrix& n) { } Node* PropagateTypes::visit(Array& n) { + PropagateTypes::visit((Variable&)n); + // visit elements to propagate their types for(ArrayElement *ae : n.getElements()) { Node *aux = ae->value->accept(*this); @@ -481,7 +485,7 @@ Node* PropagateTypes::visit(Variable& n) { destDt != BuildTypes::undefinedType && ndt != destDt) { // the var was first defined as destDt. - // we coherce the right hand side to match it + // try to coherce the right hand side to match it checkCoercion = true; } } @@ -492,6 +496,9 @@ Node* PropagateTypes::visit(Variable& n) { // this can occur when using types, e.g. usertype.x = newvalue; destDt = n.getDataType(); checkCoercion = true; + } else if (!expr) { + // for array and matrix, getExpr returns null + expr = &n; } if (checkCoercion) { diff --git a/test/general/scalar-in-two-contexts.rob b/test/general/scalar-in-two-contexts.rob index b61d538..1b5ffd0 100644 --- a/test/general/scalar-in-two-contexts.rob +++ b/test/general/scalar-in-two-contexts.rob @@ -1,17 +1,19 @@ int8 main() { - block = {true:2}; + block = {false:2}; i = 2; while (i > 0) { row = i; - block[row] = false; + block[row] = true; + i--; } row = 0; while row < block.size { - block[row] = true; + block[row] = false; + row++; } - - return 0; + + return block[0]; } From 679d65f8aa0e7e5cf468c43d1edd0101320d056f Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Tue, 24 Jun 2025 21:20:32 -0300 Subject: [PATCH 112/117] Improves AST printing --- src/Header.h | 1 + src/semantic/PrintAstVisitor.cpp | 25 ++++++++++++++++++++++++- src/semantic/PrintAstVisitor.h | 4 ++++ src/semantic/Visitor.h | 2 ++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Header.h b/src/Header.h index 0a09466..beb987c 100644 --- a/src/Header.h +++ b/src/Header.h @@ -54,3 +54,4 @@ #include "BackLLVM.h" #include "NamedConst.h" #include "BitCast.h" +#include "semantic/PropagateTypes.h" \ No newline at end of file diff --git a/src/semantic/PrintAstVisitor.cpp b/src/semantic/PrintAstVisitor.cpp index 57eefb9..2ebb9c5 100644 --- a/src/semantic/PrintAstVisitor.cpp +++ b/src/semantic/PrintAstVisitor.cpp @@ -88,7 +88,9 @@ const string PrintAstVisitor::getOperatorName(int op) { case GT_OP: return ">"; case TOK_AND : return "and"; case TOK_OR : return "or"; - default: return std::to_string(op); + case TOK_LSHIFT: return "<<"; + case TOK_RSHIFT: return ">>"; + default: return string(1, (char)op); } } @@ -121,3 +123,24 @@ Node* PrintAstVisitor::visit(Scalar& n) { visit_children(n); return NULL; } + +Node* PrintAstVisitor::visit(NamedNode& n) { + this->os << "N" << std::hex << (uint64_t)&n + << "[label=\"" << get_typename(n) << "(" << n.getName() << ")\"];\n"; + visit_children(n); + return NULL; +} + +Node* PrintAstVisitor::visit(FunctionCall& n) { + this->os << "N" << std::hex << (uint64_t)&n + << "[label=\"" << get_typename(n) << "(" << n.getIdent().getFullName() << ")\"];\n"; + visit_children(n); + return NULL; +} + +Node* PrintAstVisitor::visit(CoercionBase& n) { + this->os << "N" << std::hex << (uint64_t)&n + << "[label=\"" << get_typename(n) << "(" << buildTypes->name(n.getDataType()) << ")\"];\n"; + visit_children(n); + return NULL; +} \ No newline at end of file diff --git a/src/semantic/PrintAstVisitor.h b/src/semantic/PrintAstVisitor.h index 9a8eaa6..ea5bf31 100644 --- a/src/semantic/PrintAstVisitor.h +++ b/src/semantic/PrintAstVisitor.h @@ -27,6 +27,10 @@ class PrintAstVisitor: public RecursiveVisitor { virtual Node* visit(Load& n) override; virtual Node* visit(Scalar& n) override; + virtual Node* visit(NamedNode& n) override; + virtual Node* visit(FunctionCall& n) override; + virtual Node* visit(CoercionBase& n) override; + virtual bool before(Program& p) override; virtual void after(Program& p) override; }; diff --git a/src/semantic/Visitor.h b/src/semantic/Visitor.h index f27ed6c..519ec0f 100644 --- a/src/semantic/Visitor.h +++ b/src/semantic/Visitor.h @@ -37,6 +37,7 @@ class NamedConst; class MemCopy; class Enum; class BitCast; +class CoercionBase; #define VISITOR_DECLAREP(T, P) \ virtual Node *visit(T& n) { return visit((P&)n); } \ @@ -89,6 +90,7 @@ class Visitor { VISITOR_DECLARE(Enum) VISITOR_DECLARE(UpdateArray) VISITOR_DECLARE(BitCast) + VISITOR_DECLARE(CoercionBase) }; From 8468a9847b9a74a136e3ac67272b227933683fe2 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Tue, 24 Jun 2025 21:27:00 -0300 Subject: [PATCH 113/117] Improves and fixes grammar for boolean short circuit evaluation --- src/BinaryOp.cpp | 30 +++-- src/BuildTypes.h | 4 +- src/CmpOp.cpp | 6 +- src/CmpOp.h | 5 +- src/FlipOp.cpp | 2 +- src/FunctionCall.cpp | 14 +-- src/If.cpp | 8 +- src/Language.l | 15 ++- src/Language.y | 187 +++++++++++++++++--------------- src/Node.cpp | 35 ++++-- src/Node.h | 11 +- src/Program.cpp | 3 +- src/Scalar.cpp | 8 +- src/Scanner.cpp | 8 +- src/StringConst.cpp | 2 +- src/UpdateArray.cpp | 4 +- src/While.cpp | 8 +- src/main.cpp | 2 +- src/semantic/PropagateTypes.cpp | 93 +++++++++------- src/semantic/PropagateTypes.h | 37 +++++-- test/general/bool_scircuit.rob | 19 ++++ test/general/bool_scircuit2.rob | 30 +++++ 22 files changed, 313 insertions(+), 218 deletions(-) create mode 100644 test/general/bool_scircuit.rob create mode 100644 test/general/bool_scircuit2.rob diff --git a/src/BinaryOp.cpp b/src/BinaryOp.cpp index 008cbee..f661787 100644 --- a/src/BinaryOp.cpp +++ b/src/BinaryOp.cpp @@ -17,18 +17,10 @@ Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, // See https://en.wikipedia.org/wiki/Short-circuit_evaluation // left - Value *lhs = lhsn()->generate(func, block, allocblock); - auto lhsi = dyn_cast(lhs); - BasicBlock *newlblock; - if (lhsi) - newlblock = lhsi->getParent(); - else { - // if lhsi is null, lhs has no parent (e.g. a global variable/constant). - // use block as newlbblock - newlblock = block; - } - + BasicBlock *newlblock = block; + Value *lhs = lhsn()->generateNewBlock(func, &newlblock, allocblock); Type *lhsty = lhs->getType(); + BasicBlock *fullev = BasicBlock::Create(global_context, "fullev", func->getLLVMFunction()); BasicBlock *phiblock = BasicBlock::Create(global_context, "phiblock", func->getLLVMFunction()); PHINode *phi = PHINode::Create(lhsty, 0, "phi", phiblock); @@ -40,15 +32,17 @@ Value *BinaryOp::logical_operator(enum Instruction::BinaryOps op, BranchInst::Create(fullev, phiblock, lhs, newlblock); // right - Value *rhs = rhsn()->generate(func, fullev, allocblock); - BasicBlock *newrblock = dyn_cast(rhs)->getParent(); + BasicBlock *newrblock = fullev; + Value *rhs = rhsn()->generateNewBlock(func, &newrblock, allocblock); Builder->SetInsertPoint(newrblock); Value *binop = Builder->CreateBinOp(op, lhs, rhs, "logicop"); BranchInst::Create(phiblock, newrblock); phi->addIncoming(binop, newrblock); - if (!lhsty->isIntegerTy() || !(lhsty->getIntegerBitWidth() == 1)) + if (!lhsty->isIntegerTy() || !(lhsty->getIntegerBitWidth() == 1)) { + errs() << "Left: " << *lhsty << "\n"; yyerrorcpp("The left side of the logical expression is not boolean.", this); + } Type *rhsty = rhs->getType(); if (!rhsty->isIntegerTy() || !(rhsty->getIntegerBitWidth() == 1)) @@ -62,9 +56,11 @@ Value *BinaryOp::binary_operator(enum Instruction::BinaryOps opint, DataType lty = lhsn()->getDataType(); DataType rty = rhsn()->getDataType(); - - Value *lhs = lhsn()->generate(func, block, allocblock); - Value *rhs = rhsn()->generate(func, block, allocblock); + + // Generate left and right side + Value *lhs = lhsn()->generateNewBlock(func, &block, allocblock); + Value *rhs = rhsn()->generateNewBlock(func, &block, allocblock); + if (lhs == NULL || rhs == NULL) return NULL; diff --git a/src/BuildTypes.h b/src/BuildTypes.h index 2310322..931688d 100644 --- a/src/BuildTypes.h +++ b/src/BuildTypes.h @@ -146,11 +146,11 @@ class BuildTypes { } bool isSignedDataType(DataType tid) const { - return (tid >= tint8 && tid <= tint64) || (tid == tbool); + return (tid >= tint8 && tid <= tint64); } bool isUnsignedDataType(DataType tid) const { - return (tid >= tint2u && tid <= tint64u) || (tid == tchar); + return (tid >= tint2u && tid <= tint64u) || (tid == tchar) || (tid == tbool); } bool isFloatDataType(DataType tid) const { diff --git a/src/CmpOp.cpp b/src/CmpOp.cpp index 64e267b..477045b 100644 --- a/src/CmpOp.cpp +++ b/src/CmpOp.cpp @@ -3,7 +3,7 @@ #include "FlexDependencies.h" #include "Language_gen_y.hpp" -CmpOp::CmpOp (Node *l, int op, Node *r): Node(l->getLoc()) { +CmpOp::CmpOp (Node *l, int op, Node *r, location_t loc): Node(loc) { this->op = op; this->dt = tbool; addChild(l); @@ -13,8 +13,8 @@ CmpOp::CmpOp (Node *l, int op, Node *r): Node(l->getLoc()) { Value *CmpOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { CmpInst::Predicate predicate; - Value *lexp = lexpn()->generate(func, block, allocblock); - Value *rexp = rexpn()->generate(func, block, allocblock); + Value *lexp = lexpn()->generateNewBlock(func, &block, allocblock); + Value *rexp = rexpn()->generateNewBlock(func, &block, allocblock); if (rexp == NULL || lexp == NULL) // can't generate values, error message emitted during generate. return ConstantInt::get(Type::getInt1Ty(global_context), 1); // error recovery diff --git a/src/CmpOp.h b/src/CmpOp.h index 23e52ef..a20a7a6 100644 --- a/src/CmpOp.h +++ b/src/CmpOp.h @@ -1,4 +1,4 @@ -#pragma oncd +#pragma once #include "Node.h" #include "semantic/Visitor.h" @@ -8,7 +8,7 @@ class CmpOp: public Node { int op; public: - CmpOp (Node *l, int op, Node *r); + CmpOp (Node *l, int op, Node *r, location_t loc); int getOperator() const { return op; }; virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override; Node *lexpn() { @@ -17,7 +17,6 @@ class CmpOp: public Node { Node *rexpn() { return node_children[1]; } - Node* accept(Visitor &v) override { return v.visit(*this); } diff --git a/src/FlipOp.cpp b/src/FlipOp.cpp index da75554..69315f0 100644 --- a/src/FlipOp.cpp +++ b/src/FlipOp.cpp @@ -7,7 +7,7 @@ FlipOp::FlipOp(Node *value) : Node(value->getLoc()), value(value) { Value *FlipOp::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { // generate code to produce the value to flip - Value *exprv = value->generate(func, block, allocblock); + Value *exprv = value->generateNewBlock(func, &block, allocblock); if (exprv == NULL) return NULL; if (Constant *c = dyn_cast(exprv)) diff --git a/src/FunctionCall.cpp b/src/FunctionCall.cpp index 0d8397b..0ac21b4 100644 --- a/src/FunctionCall.cpp +++ b/src/FunctionCall.cpp @@ -90,18 +90,12 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock DataType def_dt = fsymbol->getParameters().getParamType(paramId); string argName = fsymbol->getParameters().getParamName(paramId); - Value *valor = param->generate(func, block, allocblock); + Value *valor = param->generateNewBlock(func, &block, allocblock); if (!valor) { yyerrorcpp(string_format("The value for argument %s is undefined.", argName.c_str()), param); return NULL; - } else { - // A distinct block can return from boolean short-circuit evaluation - Instruction* instr = dyn_cast(valor); - if (instr && instr->getParent() != allocblock) { - block = instr->getParent(); - Builder->SetInsertPoint(block); - } } + Builder->SetInsertPoint(block); if (buildTypes->isArrayOrMatrix(call_dt)) { // we pass the address of the first element @@ -130,14 +124,14 @@ Value *FunctionCall::generate(FunctionImpl *func, BasicBlock *block, BasicBlock Node *size = param->findMember("size"); if (size) { coerced = PropagateTypes::coerceTo(size, tint32u); - value = coerced->generate(func, block, allocblock); + value = coerced->generateNewBlock(func, &block, allocblock); } if (!value) { string pname = param->getName() + p; Load ld(Identifier(pname, param->getLoc())); ld.setScope(func); coerced = PropagateTypes::coerceTo(&ld, tint32u); - value = coerced->generate(func, block, allocblock); + value = coerced->generateNewBlock(func, &block, allocblock); } assert(value != NULL && "must pass the array size."); args.push_back(value); diff --git a/src/If.cpp b/src/If.cpp index 110bd5f..7ba9148 100644 --- a/src/If.cpp +++ b/src/If.cpp @@ -17,7 +17,8 @@ If::If(Node *e, vector &&tst, vector &&est, location_t loc): If(e, Value *If::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { - Value *exprv = expr->generate(func, block, allocblock); + BasicBlock *newblock = block; + Value *exprv = expr->generateNewBlock(func, &newblock, allocblock); if (!exprv) { // This occurs when loading a var still not defined, so // we let it be False to recovery from the error @@ -35,11 +36,6 @@ Value *If::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbloc elsenewb = elsest->generateChildren(func, elseb, allocblock); } - BasicBlock *newblock = block; - // A distinct block can return from boolean short-circuit evaluation - Instruction* instr = dyn_cast(exprv); - if (instr) - newblock = instr->getParent(); BranchInst::Create(thenb, elseb, exprv, newblock); BasicBlock *mergb = BasicBlock::Create(global_context, "if_cont", diff --git a/src/Language.l b/src/Language.l index 259437e..541fa60 100644 --- a/src/Language.l +++ b/src/Language.l @@ -75,9 +75,12 @@ EXP ([Ee][-+]?[0-9]+)? "<<" { return TOK_LSHIFT; } ">>" { return TOK_RSHIFT; } -"!" { return '!'; } -"<" { return '<'; } -">" { return '>'; } +"==" { return EQ_OP; } +"!=" { return NE_OP; } +"<=" { return LE_OP; } +">=" { return GE_OP; } +"<" { return LT_OP; } +">" { return GT_OP; } "[" { return '['; } "]" { return ']'; } @@ -99,6 +102,7 @@ EXP ([Ee][-+]?[0-9]+)? "&" { return '&'; } "^" { return '^'; } "~" { return '~'; } +"!" { return '!'; } ":" { return ':'; } "." { return '.'; } @@ -128,6 +132,11 @@ EXP ([Ee][-+]?[0-9]+)? return TOK_LDOUBLE; } "0x"[0-9a-fA-F]+ { char *aux = strndup(yytext, yyleng); + yylval->nint = strtoll(aux, NULL, 16); + free(aux); + return TOK_INTEGER; } + +"0x"[0-9a-fA-F]+[Uu] { char *aux = strndup(yytext, yyleng); yylval->unint = strtoull(aux, NULL, 16); free(aux); return TOK_UINTEGER; } diff --git a/src/Language.y b/src/Language.y index ab51a72..d41044b 100644 --- a/src/Language.y +++ b/src/Language.y @@ -7,6 +7,7 @@ #define YY_DECL int MAINlex(YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner) YY_DECL; void yyerror(YYLTYPE *yyloc, yyscan_t yyscanner, const char *msg); + Node* get_compound_node(Node *load, char op, Node *right); } %type globals type_stmts enum_items interface_decls @@ -15,9 +16,9 @@ %type function function_decl function_impl returnblock %type enum enum_item interface_impl %type simplevar_decl call_or_cast complexvar_set -%type term term2 expr factor stmt condblock whileblock logicexpr -%type logicterm logicfactor TOK_AND TOK_OR event unary logicunary -%type bind asminline +%type expr factor stmt condblock whileblock +%type TOK_AND TOK_OR event +%type bind asminline compound_left %type type_impls %type element @@ -40,6 +41,20 @@ %type function_attributes %type function_attribute +/* operator precedences */ +%left TOK_OR +%left TOK_AND +%left '|' +%left '^' +%left '&' +%left EQ_OP NE_OP +%left LT_OP GT_OP LE_OP GE_OP +%left TOK_LSHIFT TOK_RSHIFT +%left '+' '-' +%left '*' '/' '%' +%right UMINUS '!' '~' +/*%left '(' ')'*/ + %% programa : %empty @@ -262,7 +277,7 @@ type_stmt : simplevar_decl ';' | interface_impl | enum -simplevar_decl : TOK_IDENTIFIER[id] '=' logicexpr { $$ = new Scalar($id, $logicexpr); $$->setLocation(@id); } +simplevar_decl : TOK_IDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } simplevar_decl : TOK_IDENTIFIER[id] '=' array { $$ = new Array($id, $array, @id); } simplevar_decl : TOK_IDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix, @id); } @@ -317,26 +332,31 @@ stmts_rec : stmt { $stmt->setLocation(@stmt); } -stmt : ident_or_xident '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '+', new Int8(1, @1))); } - | ident_or_xident '-' '-' ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '-', new Int8(1, @1))); } - | ident_or_xident '+' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '+', $4)); } - | ident_or_xident '-' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '-', $4)); } - | ident_or_xident '*' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '*', $4)); } - | ident_or_xident '/' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '/', $4)); } - | ident_or_xident '|' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '|', $4)); } - | ident_or_xident '&' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '&', $4)); } - | ident_or_xident '^' '=' expr ';' { $$ = new Scalar($1, new BinaryOp(new Load($1, @1), '^', $4)); } - | ident_or_xident '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6, @1);} +compound_left : ident_or_xident[id] { + $$ = new Load($id, @id); +} + +compound_left : ident_or_xident[id] '[' expr ']' { + $$ = new LoadArray($id, $expr, @id); +} + +compound_left : ident_or_xident[id] '[' expr[e1] ']' '[' expr[e2] ']' { + $$ = new LoadMatrix($id, $e1, $e2, @id); +} + +stmt : compound_left[cl] '+' '+' ';' { $$ = get_compound_node($cl, '+', new Int8(1, @cl)); } + | compound_left[cl] '-' '-' ';' { $$ = get_compound_node($cl, '-', new Int8(1, @cl)); } + | compound_left[cl] '+' '=' expr ';' { $$ = get_compound_node($cl, '+', $expr); } + | compound_left[cl] '-' '=' expr ';' { $$ = get_compound_node($cl, '-', $expr); } + | compound_left[cl] '*' '=' expr ';' { $$ = get_compound_node($cl, '*', $expr); } + | compound_left[cl] '/' '=' expr ';' { $$ = get_compound_node($cl, '/', $expr); } + | compound_left[cl] '|' '=' expr ';' { $$ = get_compound_node($cl, '|', $expr); } + | compound_left[cl] '&' '=' expr ';' { $$ = get_compound_node($cl, '&', $expr); } + | compound_left[cl] '^' '=' expr ';' { $$ = get_compound_node($cl, '^', $expr); } + | ident_or_xident '[' expr ']' '=' expr ';' { $$ = new UpdateArray($1, $3, $6, @1);} | ident_or_xident '[' expr ']' '[' expr ']' '=' expr ';' { $$ = new UpdateMatrix($1, $3, $6, $9, @1); } - | ident_or_xident[id] '[' expr[e1] ']' '[' expr[e2] ']' '&' '=' expr[e3] ';' { - Node *bop = new BinaryOp(new LoadMatrix($id, $e1, $e2, @id), '&', $e3); - $$ = new UpdateMatrix($id, $e1, $e2, bop, @1); - } - | ident_or_xident[id] '[' expr[e1] ']' '[' expr[e2] ']' '|' '=' expr[e3] ';' { - Node *bop = new BinaryOp(new LoadMatrix($id, $e1, $e2, @id), '|', $e3); - $$ = new UpdateMatrix($id, $e1, $e2, bop, @1); - } + | asminline ';' { $$ = $1; } | qualifier simplevar_decl ';' { $$ = $2; $$->setQualifier((DataQualifier)$1); } | simplevar_decl ';' @@ -345,26 +365,25 @@ stmt : ident_or_xident '+' '+' ';' { $$ = new Scalar($1, new BinaryOp(new Lo | call_or_cast ';' | condblock | whileblock - | interface_impl -complexvar_set : TOK_XIDENTIFIER[id] '=' logicexpr { $$ = new Scalar($id, $logicexpr); $$->setLocation(@id); } +complexvar_set : TOK_XIDENTIFIER[id] '=' expr { $$ = new Scalar($id, $expr); $$->setLocation(@id); } complexvar_set : TOK_XIDENTIFIER[id] '=' array { $$ = new Array($id, $array, @id); } complexvar_set : TOK_XIDENTIFIER[id] '=' matrix { $$ = new Matrix($id, $matrix, @id); } -returnblock : TOK_RETURN logicexpr { $$ = new Return($2); } +returnblock : TOK_RETURN expr { $$ = new Return($2); } returnblock : TOK_RETURN { $$ = new Return(@1); } /* * Conditional */ -condblock : TOK_IF logicexpr '{' stmts '}' { - $logicexpr->setLocation(@logicexpr); - $$ = new If($logicexpr, std::move(*$stmts), @TOK_IF); +condblock : TOK_IF expr '{' stmts '}' { + $expr->setLocation(@expr); + $$ = new If($expr, std::move(*$stmts), @TOK_IF); } -condblock : TOK_IF logicexpr '{' stmts '}' elseblock { - $logicexpr->setLocation(@logicexpr); - $$ = new If($logicexpr, std::move(*$stmts), std::move(*$elseblock), @TOK_IF); +condblock : TOK_IF expr '{' stmts '}' elseblock { + $expr->setLocation(@expr); + $$ = new If($expr, std::move(*$stmts), std::move(*$elseblock), @TOK_IF); } elseblock : TOK_ELSE '{' stmts '}' { $$ = $stmts; } @@ -378,14 +397,14 @@ elseblock : TOK_ELSE condblock { * Repetition */ -whileblock : TOK_WHILE logicexpr '{' stmts '}' { - $logicexpr->setLocation(@logicexpr); - $$ = new While($logicexpr, std::move(*$stmts), @TOK_WHILE); +whileblock : TOK_WHILE expr '{' stmts '}' { + $expr->setLocation(@expr); + $$ = new While($expr, std::move(*$stmts), @TOK_WHILE); } -whileblock : TOK_WHILE logicexpr ';' { - $logicexpr->setLocation(@logicexpr); - $$ = new While($logicexpr, @TOK_WHILE); +whileblock : TOK_WHILE expr ';' { + $expr->setLocation(@expr); + $$ = new While($expr, @TOK_WHILE); } whileblock : TOK_LOOP '{' stmts '}' { @@ -393,54 +412,36 @@ whileblock : TOK_LOOP '{' stmts '}' { } /* - * Logic + * Logic and Arithmetic */ -logicexpr : logicexpr TOK_OR logicterm { $$ = new BinaryOp($1, TOK_OR, $3); } - | logicterm { $$ = $1; } - ; - -logicterm : logicterm TOK_AND logicfactor { $$ = new BinaryOp($1, TOK_AND, $3); } - | logicfactor { $$ = $1; } - ; - -logicfactor : '(' logicexpr ')' { $$ = $2; } - | expr '=''=' expr { $$ = new CmpOp($1, EQ_OP, $4); } - | expr '!''=' expr { $$ = new CmpOp($1, NE_OP, $4); } - | expr '<''=' expr { $$ = new CmpOp($1, LE_OP, $4); } - | expr '>''=' expr { $$ = new CmpOp($1, GE_OP, $4); } - | expr '<' expr { $$ = new CmpOp($1, LT_OP, $3); } - | expr '>' expr { $$ = new CmpOp($1, GT_OP, $3); } - | expr %expect 1 - | logicunary - ; - -logicunary : '!' logicfactor { $$ = new BinaryOp(new Int1(1, @2), '-', $2); } - -/* - * Arithmetic - */ - -expr : expr '+' term { $$ = new BinaryOp($1, '+', $3); } - | expr '-' term { $$ = new BinaryOp($1, '-', $3); } - | expr '|' term { $$ = new BinaryOp($1, '|', $3); } - | expr TOK_LSHIFT term { $$ = new BinaryOp($1, TOK_LSHIFT, $3); } - | expr TOK_RSHIFT term { $$ = new BinaryOp($1, TOK_RSHIFT, $3); } - | term { $$ = $1; } - ; - -term : term '*' term2 { $$ = new BinaryOp($1, '*', $3); } - | term '/' term2 { $$ = new BinaryOp($1, '/', $3); } - | term '%' term2 { $$ = new BinaryOp($1, '%', $3); } - | term '^' term2 { $$ = new BinaryOp($1, '^', $3); } - | term2 { $$ = $1; } - ; - -term2 : term2 '&' factor { $$ = new BinaryOp($1, '&', $3); } - | factor { $$ = $1; } - ; - -factor : '(' expr ')' { $$ = $2; } +// logic +expr: expr[e1] TOK_AND expr[e2] { $$ = new BinaryOp($e1, TOK_AND, $e2); } +expr: expr[e1] TOK_OR expr[e2] { $$ = new BinaryOp($e1, TOK_OR, $e2); } +expr: expr[e1] EQ_OP expr[e2] { $$ = new CmpOp($e1, EQ_OP, $e2, @EQ_OP); } +expr: expr[e1] NE_OP expr[e2] { $$ = new CmpOp($e1, NE_OP, $e2, @NE_OP); } +expr: expr[e1] LE_OP expr[e2] { $$ = new CmpOp($e1, LE_OP, $e2, @LE_OP); } +expr: expr[e1] GE_OP expr[e2] { $$ = new CmpOp($e1, GE_OP, $e2, @GE_OP); } +expr: expr[e1] LT_OP expr[e2] { $$ = new CmpOp($e1, LT_OP, $e2, @LT_OP); } +expr: expr[e1] GT_OP expr[e2] { $$ = new CmpOp($e1, GT_OP, $e2, @GT_OP); } +expr: '!'[op] expr[e] { $$ = new CmpOp($e, EQ_OP, new Int1(0, @e), @op); } + +// arithmetic +expr: expr[e1] '+' expr[e2] { $$ = new BinaryOp($e1, '+', $e2); } +expr: expr[e1] '-' expr[e2] { $$ = new BinaryOp($e1, '-', $e2); } +expr: expr[e1] '|' expr[e2] { $$ = new BinaryOp($e1, '|', $e2); } +expr: expr[e1] '*' expr[e2] { $$ = new BinaryOp($e1, '*', $e2); } +expr: expr[e1] '/' expr[e2] { $$ = new BinaryOp($e1, '/', $e2); } +expr: expr[e1] '%' expr[e2] { $$ = new BinaryOp($e1, '%', $e2); } +expr: expr[e1] '^' expr[e2] { $$ = new BinaryOp($e1, '^', $e2); } +expr: expr[e1] '&' expr[e2] { $$ = new BinaryOp($e1, '&', $e2); } +expr: expr[e1] TOK_LSHIFT expr[e2] { $$ = new BinaryOp($e1, TOK_LSHIFT, $e2); } +expr: expr[e1] TOK_RSHIFT expr[e2] { $$ = new BinaryOp($e1, TOK_RSHIFT, $e2); } +expr: '-' expr[e] %prec UMINUS { $$ = new BinaryOp($e, '*', getNodeForIntConst(-1, @e)); } +expr: '~' expr[e] { $$ = new FlipOp($e); } +expr: factor + +factor : '(' expr[e] ')' { $$ = $e; } | ident_or_xident { $$ = new Load($1, @1); } | TOK_TRUE { $$ = new Int1(1, @1); } | TOK_FALSE { $$ = new Int1(0, @1); } @@ -454,15 +455,10 @@ factor : '(' expr ')' { $$ = $2; } | ident_or_xident[id] '[' expr ']' { $$ = new LoadArray($1, $3, @id);} | ident_or_xident[id] '[' expr ']' '[' expr ']' { $$ = new LoadMatrix($1, $3, $6, @id);} | call_or_cast - | unary ; ident_or_xident: TOK_IDENTIFIER | TOK_XIDENTIFIER -unary : '-' factor { $$ = new BinaryOp($factor, '*', getNodeForIntConst(-1, @factor)); } - | '~' factor { $$ = new FlipOp($factor); } - ; - call_or_cast : ident_or_xident[id] '(' paramscall ')' { if (strncmp("copy", $id, 4) == 0 && $paramscall->getNumParams() == 1) $$ = new MemCopy($paramscall->getParamElement(0)); @@ -481,12 +477,12 @@ call_or_cast : ident_or_xident[id] '(' paramscall ')' { $$->setLocation(@id); } -paramscall : paramscall ',' logicexpr { +paramscall : paramscall ',' expr { $1->append($3); $$ = $1; } -paramscall : logicexpr { +paramscall : expr { ParamsCall *pc = new ParamsCall(); pc->append($1); $$ = pc; @@ -495,3 +491,14 @@ paramscall : logicexpr { paramscall : %empty { $$ = new ParamsCall(); } %% + +Node *get_compound_node(Node *load, char op, Node *right) { + if (dynamic_cast(load)) + return new Scalar(load->getName(), new BinaryOp(load, op, right)); + else if (LoadArray *la = dynamic_cast(load)) + return new UpdateArray(load->getName(), la->getPosition(), new BinaryOp(load, op, right), load->getLoc()); + else if (LoadMatrix *lm = dynamic_cast(load)) + return new UpdateMatrix(load->getName(), lm->getPosition(), lm->getPosition2(), new BinaryOp(load, op, right), load->getLoc()); + else + assert(false && "Unknown load node."); +} \ No newline at end of file diff --git a/src/Node.cpp b/src/Node.cpp index e88563c..f1159b3 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -93,17 +93,36 @@ Value* Node::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocbl return NULL; } +Value* Node::generateNewBlock(FunctionImpl *func, BasicBlock **block, BasicBlock *allocblock) { + Value *ret = generate(func, *block, allocblock); + + // Check if the last Instruction is in another block + // e.g. a block returned from boolean short-circuit evaluation + if (ret) { + Instruction* instr = dyn_cast(ret); + if (instr && instr->getParent() != allocblock) + *block = instr->getParent(); + } + + return ret; +} + Value* Node::generateChildren(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) { + Node *ret = nullptr; for(Node *n: children()) { - Value *b = n->generate(func, block, allocblock); - if (b) { - if (b->getValueID() == Value::BasicBlockVal) - block = (BasicBlock*)b; - else if (Instruction* instr = dyn_cast(b)) { - // A distinct block can return from boolean short-circuit evaluation - if (instr->getParent() != allocblock) - block = instr->getParent(); + if (!ret) { + Value *b = n->generateNewBlock(func, &block, allocblock); + if (b) { + if (b->getValueID() == Value::BasicBlockVal) + block = (BasicBlock*)b; + + if (isa(b)) + ret = n; } + } else { + // there's instructions after return: warn and don't generate + yywarncpp("Unreachable statement following return.", n); + yywarncpp("The return statement is here.", ret); } } return block; diff --git a/src/Node.h b/src/Node.h index f9027e6..ae4c2a9 100644 --- a/src/Node.h +++ b/src/Node.h @@ -29,11 +29,12 @@ class Node : public SourceLocation { return false; } - virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value* generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value* generateNewBlock(FunctionImpl *func, BasicBlock **block, BasicBlock *allocblock); - virtual Value *generateChildren(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); + virtual Value* generateChildren(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock); - virtual std::vector const& children() const; + virtual std::vector const& children() const; virtual Node* accept(Visitor &); @@ -45,7 +46,7 @@ class Node : public SourceLocation { return ""; } - Node *getScope() { + Node* getScope() { return scope; } @@ -71,7 +72,7 @@ class Node : public SourceLocation { return dt; } - virtual Type *getLLVMType(); + virtual Type* getLLVMType(); void setQualifier(DataQualifier dq) { qualifiers.insert(dq); diff --git a/src/Program.cpp b/src/Program.cpp index a7faac4..932ce8e 100644 --- a/src/Program.cpp +++ b/src/Program.cpp @@ -257,7 +257,8 @@ void Program::generate() { mainFuncIt = symbols.find("__main"); Node *mainFunc = mainFuncIt->second; - generateInjectionGlobals(mainFunc); + if (mainFunc) + generateInjectionGlobals(mainFunc); // build types and global vars first map already_generated; diff --git a/src/Scalar.cpp b/src/Scalar.cpp index 4196aac..f980586 100644 --- a/src/Scalar.cpp +++ b/src/Scalar.cpp @@ -49,15 +49,9 @@ Value *Scalar::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *alloc Node *expr = getExpr(); expr->setLeftValue(symbol); - Value *exprv = expr->generate(func, block, allocblock); + Value *exprv = expr->generateNewBlock(func, &block, allocblock); if (!exprv) return NULL; - else { - // A distinct block can return from boolean short-circuit evaluation - Instruction* instr = dyn_cast(exprv); - if (instr && instr->getParent() != allocblock) - block = instr->getParent(); - } DataType exprv_dt = expr->getDataType(); if (hasQualifier(qconst)) diff --git a/src/Scanner.cpp b/src/Scanner.cpp index 554897c..20b3565 100644 --- a/src/Scanner.cpp +++ b/src/Scanner.cpp @@ -144,12 +144,8 @@ bool parseUseFile(const string& use, location_t loc, bool isPath) { FILE *f = findFile(file_name, file_path); if (f == NULL) { - if (loc.first_line == 0) // spec file - cerr << string_format(file_not_found, file_name.c_str()); - else { - SourceLocation s(loc); - yyerrorcpp(string_format(file_not_found, file_name.c_str()), &s); - } + SourceLocation s(loc); + yyerrorcpp(string_format(file_not_found, file_name.c_str()), &s); return false; } diff --git a/src/StringConst.cpp b/src/StringConst.cpp index 8f02596..ea8dff1 100644 --- a/src/StringConst.cpp +++ b/src/StringConst.cpp @@ -52,7 +52,7 @@ Value* StringConst::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * value = alloc; } } else { - value = Builder->CreateGlobalStringPtr(str, name, 0, mainmodule, false); + value = Builder->CreateGlobalString(str, name, 0, mainmodule, false); leftValue->setAlloca(value); } diff --git a/src/UpdateArray.cpp b/src/UpdateArray.cpp index 3e75c6b..d10a75b 100644 --- a/src/UpdateArray.cpp +++ b/src/UpdateArray.cpp @@ -46,13 +46,13 @@ Value *UpdateArray::generate(FunctionImpl *func, BasicBlock *block, BasicBlock * ty = aux->getValueType(); Node *indn = getElementIndex(symbol); - Value *indice = indn->generate(func, block, allocblock); + Value *indice = indn->generateNewBlock(func, &block, allocblock); if (!indice || !indice->getType()->isIntegerTy()){ yyerrorcpp("Index to update " + ident.getFullName() + " elements must be of type integer.", this); return NULL; } - Value *val = expr->generate(func, block, allocblock); + Value *val = expr->generateNewBlock(func, &block, allocblock); ArrayType *arrayTy = (ArrayType*)buildTypes->llvmType(symbol->getDataType()); RobDbgInfo.emitLocation(this); diff --git a/src/While.cpp b/src/While.cpp index c8182b7..bb57aa6 100644 --- a/src/While.cpp +++ b/src/While.cpp @@ -21,12 +21,8 @@ Value *While::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb Builder->SetInsertPoint(block); Builder->CreateBr(condwhile); - Value *exprv = expr->generate(func, condwhile, allocblock); BasicBlock *endcondwhile = condwhile; - // A distinct block can return from boolean short-circuit evaluation - Instruction* instr = dyn_cast(exprv); - if (instr) - endcondwhile = instr->getParent(); + Value *exprv = expr->generateNewBlock(func, &endcondwhile, allocblock); // check condition RobDbgInfo.emitLocation(expr); @@ -47,7 +43,7 @@ Value *While::generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocb endbody = (BasicBlock*)newb; // if end block already has a terminator, don't generate branch - if (!((BasicBlock*)endbody)->getTerminator()) { + if (!endbody->getTerminator()) { Builder->SetInsertPoint(endbody); Builder->CreateBr(condwhile); } diff --git a/src/main.cpp b/src/main.cpp index 837358a..48ae37c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -85,7 +85,7 @@ int main(int argc, char *argv[]) { spec_filename = argv[++i]; specin = fopen(spec_filename, "r"); if (specin == NULL) { - fprintf(stderr, "Could not open file %s.\n", spec_filename); + fprintf(stderr, "Could not open specification file %s.\n", spec_filename); exit(1); } } diff --git a/src/semantic/PropagateTypes.cpp b/src/semantic/PropagateTypes.cpp index bf58113..7afffbe 100644 --- a/src/semantic/PropagateTypes.cpp +++ b/src/semantic/PropagateTypes.cpp @@ -1,4 +1,7 @@ +#include "FlexDependencies.h" +#include "Language_gen_y.hpp" + #include "PropagateTypes.h" #include "ConstructorCall.h" #include "Scalar.h" @@ -89,7 +92,7 @@ Node* PropagateTypes::coerceTo(Node *n, const DataType destTy, bool warns) { // if destTy is larger, SExtended or ZExtended value if (destBWidth > valueBWidth) { Node *expand; - if (destUnsigned) + if (valueUnsigned) expand = new ZExtInt(n, destTy); else expand = new SExtInt(n, destTy); @@ -182,6 +185,28 @@ DataType PropagateTypes::coerceArithOrCmp(Node &n, Node *lNode, Node *rNode) { uint lBWidth = buildTypes->bitWidth(lTy); uint rBWidth = buildTypes->bitWidth(rTy); + // special cases for BinaryOp (left and right shift, or and and) + if (BinaryOp *bop = dynamic_cast(&n)) { + bool rIsSigned = buildTypes->isSignedDataType(rTy); + bool lIsSigned = buildTypes->isSignedDataType(lTy); + + if (bop->getOperator() == TOK_LSHIFT || bop->getOperator() == TOK_RSHIFT) { + // special case for left and right shift, preserve the left side type + // TODO: C standard promotes left operand to int32 + if (rTy != lTy) + n.node_children[1] = new IntCast(rNode, rIsSigned, lTy); + return lTy; + + } else if (bop->getOperator() == TOK_OR || bop->getOperator() == TOK_AND) { + // special case for or and and: convert to bool (int1) + if (lTy != tbool) + n.node_children[0] = new IntCast(lNode, rIsSigned, tbool); + if (rTy != tbool) + n.node_children[1] = new IntCast(rNode, rIsSigned, tbool); + return tbool; + } + } + // both sides integer if (buildTypes->isIntegerDataType(lTy) && buildTypes->isIntegerDataType(rTy)) { bool lUnsigned = buildTypes->isUnsignedDataType(lTy); @@ -189,46 +214,40 @@ DataType PropagateTypes::coerceArithOrCmp(Node &n, Node *lNode, Node *rNode) { // if we have signed and unsigned operands if (lUnsigned ^ rUnsigned) { - // if one side is constant, convert it to the other side type - bool lIsConstant = lNode->isConstExpr(); - bool rIsConstant = rNode->isConstExpr(); - if (lIsConstant ^ rIsConstant) { - if (lIsConstant) { - lTy = lUnsigned ? buildTypes->unsignedToSigned(lTy) : buildTypes->signedToUnsigned(lTy); - returnTy = rTy; - } else { - rTy = rUnsigned ? buildTypes->unsignedToSigned(rTy) : buildTypes->signedToUnsigned(rTy); - returnTy = lTy; - } - + + if ((lUnsigned && lBWidth >= rBWidth) || + (rUnsigned && rBWidth >= lBWidth)) { + // Unsigned has equal or greater width: promote signed to unsigned + returnTy = lUnsigned ? lTy : rTy; + + } else if (!lUnsigned && lBWidth > rBWidth) { + // l is signed, has greater width, can hold r: promote r to l + returnTy = lTy; + + } else if (!rUnsigned && rBWidth > lBWidth) { + // r is signed, has greater width, can hold l: promote l to r + returnTy = rTy; + } else { - if (lUnsigned) { - //yywarncpp("The left operand was converted to signed.", lNode); - lTy = buildTypes->unsignedToSigned(lTy); - } - else { - //yywarncpp("The right operand was converted to signed.", rNode); - rTy = buildTypes->unsignedToSigned(rTy); - } + // fallback: l or r is signed and smaller than unsigned: convert the + // signed to unsigned version of the wider type + returnTy = lBWidth > rBWidth ? lTy : rTy; // wider + if (buildTypes->isSignedDataType(returnTy)) + returnTy = buildTypes->signedToUnsigned(returnTy); } + + } else { + // same signedness, return wider + returnTy = lBWidth > rBWidth ? lTy : rTy; } - // At this point, rTy has the same signedness of lTy. - // Thus, temporarily set returnTy to check the signedness below - returnTy = rTy; + if (lTy != returnTy) + n.node_children[0] = new IntCast(lNode, !lUnsigned, returnTy); + + if (rTy != returnTy) + n.node_children[1] = new IntCast(rNode, !rUnsigned, returnTy); - // if sizes are distinct, the smaller int is SExtended or ZExtended - if (lBWidth != rBWidth) { - Node *convert = lBWidth < rBWidth ? lNode : rNode; - DataType newTy = lBWidth < rBWidth ? rTy : lTy; - Node *expand; - if (buildTypes->isSignedDataType(returnTy)) - expand = new SExtInt(convert, newTy); - else - expand = new ZExtInt(convert, newTy); - n.node_children[lBWidth < rBWidth ? 0 : 1] = expand; - return newTy; - } + return returnTy; } // both sides float point @@ -375,7 +394,7 @@ Node* PropagateTypes::visit(FunctionCall& fc) { Node* PropagateTypes::visit(Matrix& n) { PropagateTypes::visit((Variable&)n); - + // visit elements to propagate their types for(MatrixElement *me : n.getMatrixElements()) { for(ArrayElement *k: me->array->getElements()) { diff --git a/src/semantic/PropagateTypes.h b/src/semantic/PropagateTypes.h index 27ad9ac..9856122 100644 --- a/src/semantic/PropagateTypes.h +++ b/src/semantic/PropagateTypes.h @@ -40,19 +40,38 @@ class ExpandFloat: public CoercionBase { ExpandFloat(Node *n, DataType newDt): CoercionBase(n, newDt) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - Value *v = node->generate(func, block, allocblock); + Value *v = node->generateNewBlock(func, &block, allocblock); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); return Builder->CreateFPExt(v, buildTypes->llvmType(dt), "fpext"); } }; +class IntCast: public CoercionBase { +private: + bool isSigned; +public: + IntCast(Node *n, bool isSigned, DataType newDt): + CoercionBase(n, newDt), isSigned(isSigned) {} + + virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { + Value *v = node->generateNewBlock(func, &block, allocblock); + RobDbgInfo.emitLocation(this); + Builder->SetInsertPoint(block); + return Builder->CreateIntCast(v, buildTypes->llvmType(dt), isSigned, "intcast"); + } + + Node* accept(Visitor& v) override { + return v.visit(*this); + } +}; + class SExtInt: public CoercionBase { public: SExtInt(Node *n, DataType newDt): CoercionBase(n, newDt) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - Value *v = node->generate(func, block, allocblock); + Value *v = node->generateNewBlock(func, &block, allocblock); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); return Builder->CreateSExt(v, buildTypes->llvmType(dt), "sext"); @@ -64,7 +83,7 @@ class ZExtInt: public CoercionBase { ZExtInt(Node *n, DataType newDt): CoercionBase(n, newDt) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - Value *v = node->generate(func, block, allocblock); + Value *v = node->generateNewBlock(func, &block, allocblock); if (!v) { yyerrorcpp("There is no value to cast from (zext) ", node); return NULL; @@ -81,7 +100,7 @@ class TruncInt: public CoercionBase { TruncInt(Node *n, DataType newDt): CoercionBase(n, newDt) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - Value *v = node->generate(func, block, allocblock); + Value *v = node->generateNewBlock(func, &block, allocblock); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); return Builder->CreateTrunc(v, buildTypes->llvmType(dt), "trunc"); @@ -93,7 +112,7 @@ class ExtendFloat: public CoercionBase { ExtendFloat(Node *n, DataType newDt): CoercionBase(n, newDt) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - Value *v = node->generate(func, block, allocblock); + Value *v = node->generateNewBlock(func, &block, allocblock); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); return Builder->CreateFPExt(v, buildTypes->llvmType(dt), "fpext"); @@ -105,7 +124,7 @@ class TruncFloat: public CoercionBase { TruncFloat(Node *n, DataType newDt): CoercionBase(n, newDt) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - Value *v = node->generate(func, block, allocblock); + Value *v = node->generateNewBlock(func, &block, allocblock); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); return Builder->CreateFPTrunc(v, buildTypes->llvmType(dt), "trunc"); @@ -118,7 +137,7 @@ class FloatToInt: public CoercionBase { CoercionBase(n, newDt) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - Value *v = node->generate(func, block, allocblock); + Value *v = node->generateNewBlock(func, &block, allocblock); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); if (buildTypes->isUnsignedDataType(dt)) @@ -134,7 +153,7 @@ class IntToFloat: public CoercionBase { CoercionBase(n, newDt) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - Value *v = node->generate(func, block, allocblock); + Value *v = node->generateNewBlock(func, &block, allocblock); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); if (buildTypes->isUnsignedDataType(node->getDataType())) @@ -150,7 +169,7 @@ class DeferPointer: public CoercionBase { CoercionBase(n, n->getDataType()) {} virtual Value *generate(FunctionImpl *func, BasicBlock *block, BasicBlock *allocblock) override { - Value *v = node->generate(func, block, allocblock); + Value *v = node->generateNewBlock(func, &block, allocblock); RobDbgInfo.emitLocation(this); Builder->SetInsertPoint(block); return Builder->CreateLoad(buildTypes->llvmType(dt), v, false, "deref"); diff --git a/test/general/bool_scircuit.rob b/test/general/bool_scircuit.rob new file mode 100644 index 0000000..7f85f37 --- /dev/null +++ b/test/general/bool_scircuit.rob @@ -0,0 +1,19 @@ + +int16 main() { + i1 = int16(0x1FC2); + i2 = int32(7); + i3 = int8(0); + + ret = 0; + while ret > -29 { + i1 |= 0U != i3 or (i2 != 0) < i2; + ret--; + } + + if i1 == 0x1FC3 { + return 0; + } + + return i1; +} + diff --git a/test/general/bool_scircuit2.rob b/test/general/bool_scircuit2.rob new file mode 100644 index 0000000..5bdd4b7 --- /dev/null +++ b/test/general/bool_scircuit2.rob @@ -0,0 +1,30 @@ +uint64 safe_sub(uint64 a, uint64 b) { + return a - b; +} + +uint64 safe_add(uint64 a, uint64 b) { + return a + b; +} + +uint16 safe_rshift(uint16 a, uint16 b) { + return a << b; +} + +uint8 safe_div(uint8 a, uint8 b) { + return a/b; +} + +int16 main() { + l_10 = int64(0xD6C3F0BC5021C3A2); + l_11 = int8(1); + l_12 = int32(5); + l_12 = safe_sub( + safe_rshift( + safe_add( + (safe_div(l_10, l_10) != 0) or (0xECC2 != 0) | l_10 ^ l_10 != l_10 ^ l_11 <= 0xC7B7F609B2B534DE, + 0x885EA6EDAD94E8FE), + 5), + 0xCE4B0AD8EA5F34BD); + return l_12; +} + From bc95eb723a07471d5f1db5b5f19445ec66ee7bf2 Mon Sep 17 00:00:00 2001 From: Thiago Borges de Oliveira Date: Wed, 25 Jun 2025 09:51:01 -0300 Subject: [PATCH 114/117] Small fixes and improvements integrating rp2040 --- lib/Makefile | 5 +- lib/arch/avr/avr5mcu.rob | 50 +- lib/arch/rp/rp2040/init.rob | 57 +- lib/arch/rp/rp2040/mcu.rob | 109 +- lib/arch/rp/rp2040/regs.rob | 5899 ++++++++++++++++++++++-- lib/arch/rp/rp2040/rp2040.ld | 15 - lib/arch/svd2rob.py | 102 +- lib/atmega328p.rob | 14 +- lib/avr5.S | 28 + test/atmega328p/bitstruct-field-i5.rob | 2 +- test/debug/platformio.ini | 1 + test/rp2040/Makefile | 6 +- 12 files changed, 5853 insertions(+), 435 deletions(-) diff --git a/lib/Makefile b/lib/Makefile index 47bf19a..797992b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,5 +1,5 @@ -GEN=avr5.o avr51.o cortex-m3-arm-missing.o +GEN=avr5.o avr51.o cortex-m3-arm-missing.o cortex-m0plus-arm-missing.o all: ${GEN} @@ -16,5 +16,8 @@ avr51.o: avr51.S cortex-m3-arm-missing.o: arm-missing.c clang --target=arm-none-eabi -mcpu=cortex-m3 -mthumb -O3 -c $< -o $@ +cortex-m0plus-arm-missing.o: arm-missing.c + clang --target=arm-none-eabi -mcpu=cortex-m0plus -mthumb -O3 -c $< -o $@ + clean: rm -f ${GEN} diff --git a/lib/arch/avr/avr5mcu.rob b/lib/arch/avr/avr5mcu.rob index 43fd235..4684cd4 100644 --- a/lib/arch/avr/avr5mcu.rob +++ b/lib/arch/avr/avr5mcu.rob @@ -86,31 +86,39 @@ type avr5mcu implements mcu { b5.set(s); } - void wait_us(uint16 us) { - volatile uus = us; - while uus > 0 { - __delay_us(); - uus--; - } + void busy_wait_loop1(uint16 count) noopt { + /* trusting that ABI will put the count parameter in r25:r24 + sbiw takes 2 cycles + brne takes 2 cycles when branching, 1 when not + ret +1 cycle */ + asm "1: + sbiw r24, 1 + brne 1b"; // a ret is appended here } void busy_wait_loop5(uint16 count) noopt { - // trusting that ABI will put the count parameter in r25:r24 - // cycles total: 3 + count*5-1 + 3 - // +2 (ldi r25:r24 prior to cal) + count*5 - 1 + 3 - // +1 (ser) - // +count*5-1 (loop) - // +2 (rjmp) - // +1 (ret) + /* trusting that ABI will put the count parameter in r25:r24 + cycles total: 3 + count*5-1 + 3 + +2 (ldi r25:r24 prior to cal) + count*5 - 1 + 3 + +1 (ser) + +count*5-1 (loop) + +2 (rjmp) + +1 (ret) */ asm "ser r18 - loop: subi r18,1 + busy_wait_loop5_loop: + subi r18,1 sbci r24,0 sbci r25,0 - brne loop - rjmp end - end: "; // a ret is appended here + brne busy_wait_loop5_loop + rjmp busy_wait_loop5_end + busy_wait_loop5_end: "; // a ret is appended here } + void wait_us(uint16 us) { + count = uint16(clock() / 4e6) * us - 1; + busy_wait_loop1(count); + } + // secure range 1 -- 5460 void wait_ms(uint16 ms) { count = uint16(clock() / 1280e3) * ms - 1; @@ -282,7 +290,7 @@ type avr5mcu implements mcu { bool start_transaction(uint16 addr) { // write START condition TWCR = ETWCR.TWSTA | ETWCR.TWEN | ETWCR.TWINT; - while TWCR & ETWCR.TWINT == 0; + while (TWCR & ETWCR.TWINT) == 0; if TWSR.TWS != STATUS.START_OK { return false; @@ -291,7 +299,7 @@ type avr5mcu implements mcu { // write SLA addr TWDR = uint8(addr); TWCR = ETWCR.TWEN | ETWCR.TWINT; - while TWCR & ETWCR.TWINT == 0; + while (TWCR & ETWCR.TWINT) == 0; if TWSR.TWS != STATUS.MT_SLA_ACK_OK { return false; @@ -308,7 +316,7 @@ type avr5mcu implements mcu { void write(uint8 b) { TWDR = b; TWCR = ETWCR.TWINT | ETWCR.TWEN; - while TWCR & ETWCR.TWINT == 0; + while (TWCR & ETWCR.TWINT) == 0; } void write_array(int8[] data) { @@ -316,7 +324,7 @@ type avr5mcu implements mcu { while (i < data.size) { TWDR = uint8(data[i]); TWCR = ETWCR.TWEN | ETWCR.TWINT; - while TWCR & ETWCR.TWINT == 0; + while (TWCR & ETWCR.TWINT) == 0; // check if TWSR.TWS != 0x5 // 0x28 >> 3 // data transmited and ack received i++; diff --git a/lib/arch/rp/rp2040/init.rob b/lib/arch/rp/rp2040/init.rob index de469d3..68865a8 100644 --- a/lib/arch/rp/rp2040/init.rob +++ b/lib/arch/rp/rp2040/init.rob @@ -3,7 +3,6 @@ */ use regs; -//use math.limits; int16 main(); @@ -17,11 +16,43 @@ void __system_config() { //WATCHDOG_CTRL.ENABLE = false; //WATCHDOG_CTRL.TIME = 0; - //ROSC_CTRL.ENABLE = 0xfab; - //CLK_SYS_CTRL.SRC = 0x1; // CLKSRC_CLK_SYS_AUX - //CLK_SYS_CTRL.AUXSRC = 0x2; // ROSC_CLKSRC - //while (CLK_SYS_SELECTED.CLK_SYS_SELECTED & 0x7) != 1; + // Configure and Enable XOSC (External Crystal Oscillator) + XOSC_CTRL.ENABLE = XOSC_CTRL_ENABLE.ENABLE; + while !XOSC_STATUS.STABLE; // wait it becomes stable + // Reset pll_sys + RESET.PLL_SYS = false; + while !RESET_DONE.PLL_SYS; + + // Configure PLL_SYS to generate 200MHz from 12MHz XOSC + PLL_SYS_FBDIV_INT.FBDIV_INT = 200; + PLL_SYS_PWR.PD = false; + PLL_SYS_PWR.VCOPD = false; + while !PLL_SYS_PLL_SYS_CS.LOCK; + + // set and turn on the post dividers + PLL_SYS_PRIM.POSTDIV1 = 6; + PLL_SYS_PRIM.POSTDIV2 = 2; + PLL_SYS_PWR.POSTDIVPD = false; + + // Setup clock generators + // Setup clk_ref + CLK_REF_CTRL.SRC = CLK_REF_CTRL_SRC.xosc_clksrc; + while (CLK_REF_SELECTED.CLK_REF_SELECTED & 0b100) != 0b100; + + // Setup clk_sys + CLK_SYS_CTRL.SRC = CLK_SYS_CTRL_SRC.clksrc_clk_sys_aux; + while (CLK_SYS_SELECTED.CLK_SYS_SELECTED & 0b10) != 0b10; + + // disable ROSC + ROSC_CTRL.ENABLE = ROSC_CTRL_ENABLE.DISABLE; + + // Enable 64-bit Timer + WATCHDOG_CTRL.TIME = 12; // 12 or 6? + RESET.TIMER = false; + while !RESET_DONE.TIMER; + + // reset GPIOs RESET.IO_BANK0 = false; RESET.PADS_BANK0 = false; while !RESET_DONE.IO_BANK0; @@ -33,16 +64,14 @@ void __error_handler() { } void __enter_vtable_in_r0() naked { - - //#define PPB_BASE _u(0xe0000000) - //#define M0PLUS_VTOR_OFFSET _u(0x0000ed08) - //ldr r1, =(PPB_BASE + ARM_CPU_PREFIXED(VTOR_OFFSET)) + //read the VTOR offset and send core to vtable previously set in r0 + //PPB_BASE is at _u(0xe0000000) and the M0PLUS_VTOR_OFFSET is 0x0000ed08 + //thus, ldr r1, =(PPB_BASE + M0PLUS_VTOR_OFFSET) asm "ldr r1, =0xe000ed08 str r0, [r1] ldmia r0!, {r1, r2} msr msp, r1 - bx r2 - "; + bx r2"; } void __do_copy_data_and_bss() noinline { @@ -73,9 +102,9 @@ asm } void __isr_reset() naked { - // check if core 1 is sleeping in the bootrom - // xx = (SIO_BASE) 0xd0000000 + SIO_CPUID_OFFSET 0x00000000 - // value of xx is 0 when read from processor core 0, and 1 when read from processor core 1 + // check if (and put) core 1 to sleep in the bootrom + // xx = 0xd0000000 = (SIO_BASE) 0xd0000000 + SIO_CPUID_OFFSET 0x00000000 + // value from [xx] is 0 when read from processor core 0, and 1 when read from processor core 1 asm "ldr r0, =0xd0000000 ldr r0, [r0] cmp r0, #0 diff --git a/lib/arch/rp/rp2040/mcu.rob b/lib/arch/rp/rp2040/mcu.rob index 3cc8e74..f5dbdc0 100644 --- a/lib/arch/rp/rp2040/mcu.rob +++ b/lib/arch/rp/rp2040/mcu.rob @@ -8,8 +8,8 @@ use regs; type rp2040mcu implements mcu { uint32 clock() inline { - // 133Mhz - return 133E6; + // 200Mhz set by init + return 200E6; } void set_interruptions(bool enabled) { @@ -33,8 +33,9 @@ type rp2040mcu implements mcu { } } void set(bool v) { - if (v) { GPIO_OUT_SET.IO24 = true; } - else { GPIO_OUT_CLR.IO24 = true; } + x = uint32(1) << 24; + if (v) { GPIO_OUT_SET_raw = x; } + else { GPIO_OUT_CLR_raw = x; } } bool get() { return GPIO_IN.IO24; } } @@ -56,31 +57,101 @@ type rp2040mcu implements mcu { } } void set(bool v) { - if (v) { GPIO_OUT_SET.IO25 = true; } - else { GPIO_OUT_CLR.IO25 = true; } + x = uint32(1) << 25; + if (v) { GPIO_OUT_SET_raw = x; } + else { GPIO_OUT_CLR_raw = x; } } bool get() { return GPIO_IN.IO25; } } + uint64 micros() { + timeLR = TIMELR_raw; + timeHR = TIMEHR_raw; + return (uint64(timeHR) << 32) | timeLR; + } + + uint64 millis() { + return micros() / 1000; + } + void wait_us(uint16 us) { - volatile x = us; - while x > 0 { - x--; - } + old = micros(); + while micros() - old < us; } void wait_ms(uint16 ms) { - while ms > 0 { - wait_us(1000); - ms--; - } + old = millis(); + while millis() - old < ms; } - uint32 micros() { - return 0; - } + uart0 implements databus { - uint32 millis() { - return micros() / 1000; + void setup(uint32 baud) { + // set uart0 in IO0 (tx) and IO1 (rx) + GPIO0_CTRL.FUNCSEL = GPIO0_CTRL_FUNCSEL.uart0_tx; + GPIO1_CTRL.FUNCSEL = GPIO1_CTRL_FUNCSEL.uart0_rx; + + // set baudrate integer and fraction + // for clock = 133E6 > 125E6, clk_peri automatically switches to 48E6 + common_denominator = baud * 16; + baud_rate_integer = 48E6 / common_denominator; + baud_rate_frac = ((48E6 % common_denominator) * 64) / common_denominator; + UART0_UARTIBRD.BAUD_DIVINT = uint16(baud_rate_integer); + UART0_UARTFBRD.BAUD_DIVFRAC = uint6(baud_rate_frac); + + // 8 bit + UART0_UARTLCR_H.WLEN = 0b11; // 8 bit + UART0_UARTLCR_H.FEN = true; // enable FIFO buffers + UART0_UARTLCR_H.STP2 = false; // 1 stop bit + UART0_UARTLCR_H.PEN = false; // no parity + UART0_UARTLCR_H.BRK = false; // don't send break + + // enable TX and RX + UART0_UARTCR.TXE = true; + UART0_UARTCR.RXE = true; + } + + void async_read_to(interrupt_i8 i) { + //int_usart_rx = i; + //UCSR0B.RXCIE0 = true; + } + + void enable() { + UART0_UARTCR.UARTEN = true; + } + + void disable() { + UART0_UARTCR.UARTEN = false; + } + + void write(uint8 b) inline { + while UART0_UARTFR.TXFF; // wait if transmit fifo is full + UART0_UARTDR.DATA = b; + } + + void write_array(int8[] data) { + i = 0u; + while i < data.size { + write(uint8(data[i])); + i++; + } + } + + uint8 read() inline { + while UART0_UARTFR.RXFE; // wait if receive fifo is empty + return UART0_UARTDR.DATA; + } + + bool has_data() inline { + return !UART0_UARTFR.RXFE; + } + + bool start_transaction(uint16 address) inline { return true; } + void end_transaction() { } + + databus_protocol get_protocol() inline { + return databus_protocol.UART; + } } + } diff --git a/lib/arch/rp/rp2040/regs.rob b/lib/arch/rp/rp2040/regs.rob index 48a058a..262a72e 100644 --- a/lib/arch/rp/rp2040/regs.rob +++ b/lib/arch/rp/rp2040/regs.rob @@ -25,6 +25,8 @@ Temperature sensor Accelerated integer and floating-point libraries on-chip + width: 32 + size: 32 */ /* Types and registers for RESETS */ @@ -55,10 +57,12 @@ UART0 = false; // UART1 = false; // USBCTRL = false; // + _res1 = uint7(0); // Reserved, 7 bits } // Reset control. If a bit is set it means the peripheral is in reset. 0 means the peripheral's reset is deasserted. register RESET_t RESET at 0x4000c000; + register uint32 RESET_raw at 0x4000c000; type RESETS_WDSEL_t { ADC = false; // @@ -86,10 +90,12 @@ UART0 = false; // UART1 = false; // USBCTRL = false; // + _res1 = uint7(0); // Reserved, 7 bits } // Watchdog select. If a bit is set then the watchdog will reset this peripheral when the watchdog fires. register RESETS_WDSEL_t RESETS_WDSEL at 0x4000c004; + register uint32 RESETS_WDSEL_raw at 0x4000c004; type RESET_DONE_t { ADC = false; // @@ -117,10 +123,12 @@ UART0 = false; // UART1 = false; // USBCTRL = false; // + _res1 = uint7(0); // Reserved, 7 bits } // Reset done. If a bit is set then a reset done signal has been returned by the peripheral. This indicates that the peripheral's registers are ready to be accessed. register RESET_DONE_t RESET_DONE at 0x4000c008; + register uint32 RESET_DONE_raw at 0x4000c008; /* Types and registers for PSM */ @@ -143,10 +151,12 @@ SIO = false; // PROC0 = false; // PROC1 = false; // + _res1 = uint15(0); // Reserved, 15 bits } // Force block out of reset (i.e. power it on) register FRCE_ON_t FRCE_ON at 0x40010000; + register uint32 FRCE_ON_raw at 0x40010000; type FRCE_OFF_t { ROSC = false; // @@ -166,10 +176,12 @@ SIO = false; // PROC0 = false; // PROC1 = false; // + _res1 = uint15(0); // Reserved, 15 bits } // Force into reset (i.e. power it off) register FRCE_OFF_t FRCE_OFF at 0x40010004; + register uint32 FRCE_OFF_raw at 0x40010004; type PSM_WDSEL_t { ROSC = false; // @@ -189,10 +201,12 @@ SIO = false; // PROC0 = false; // PROC1 = false; // + _res1 = uint15(0); // Reserved, 15 bits } // Set to 1 if this peripheral should be reset when the watchdog fires. register PSM_WDSEL_t PSM_WDSEL at 0x40010008; + register uint32 PSM_WDSEL_raw at 0x40010008; type DONE_t { ROSC = false; // @@ -212,14 +226,30 @@ SIO = false; // PROC0 = false; // PROC1 = false; // + _res1 = uint15(0); // Reserved, 15 bits } // Indicates the peripheral's registers are ready to access. register DONE_t DONE at 0x4001000c; + register uint32 DONE_raw at 0x4001000c; /* Types and registers for CLOCKS */ + enum CLK_GPOUT0_CTRL_AUXSRC { + clksrc_pll_sys = 0, // + clksrc_gpin0 = 1, // + clksrc_gpin1 = 2, // + clksrc_pll_usb = 3, // + rosc_clksrc = 4, // + xosc_clksrc = 5, // + clk_sys = 6, // + clk_usb = 7, // + clk_adc = 8, // + clk_rtc = 9, // + clk_ref = 10 // + } + type CLK_GPOUT0_CTRL_t { _res1 = uint5(0); // Reserved, 5 bits AUXSRC = uint4(0); // Selects the auxiliary clock source, will glitch when switching @@ -231,10 +261,12 @@ PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect _res4 = uint2(0); // Reserved, 2 bits NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits } // Clock control, can be changed on-the-fly (except for auxsrc) register CLK_GPOUT0_CTRL_t CLK_GPOUT0_CTRL at 0x40008000; + register uint32 CLK_GPOUT0_CTRL_raw at 0x40008000; type CLK_GPOUT0_DIV_t { FRAC = uint8(0); // Fractional component of the divisor @@ -243,6 +275,7 @@ // Clock divisor, can be changed on-the-fly register CLK_GPOUT0_DIV_t CLK_GPOUT0_DIV at 0x40008004; + register uint32 CLK_GPOUT0_DIV_raw at 0x40008004; type CLK_GPOUT0_SELECTED_t { CLK_GPOUT0_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. @@ -250,6 +283,21 @@ // Indicates which SRC is currently selected by the glitchless mux (one-hot). register CLK_GPOUT0_SELECTED_t CLK_GPOUT0_SELECTED at 0x40008008; + register uint32 CLK_GPOUT0_SELECTED_raw at 0x40008008; + + enum CLK_GPOUT1_CTRL_AUXSRC { + clksrc_pll_sys = 0, // + clksrc_gpin0 = 1, // + clksrc_gpin1 = 2, // + clksrc_pll_usb = 3, // + rosc_clksrc = 4, // + xosc_clksrc = 5, // + clk_sys = 6, // + clk_usb = 7, // + clk_adc = 8, // + clk_rtc = 9, // + clk_ref = 10 // + } type CLK_GPOUT1_CTRL_t { _res1 = uint5(0); // Reserved, 5 bits @@ -262,10 +310,12 @@ PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect _res4 = uint2(0); // Reserved, 2 bits NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits } // Clock control, can be changed on-the-fly (except for auxsrc) register CLK_GPOUT1_CTRL_t CLK_GPOUT1_CTRL at 0x4000800c; + register uint32 CLK_GPOUT1_CTRL_raw at 0x4000800c; type CLK_GPOUT1_DIV_t { FRAC = uint8(0); // Fractional component of the divisor @@ -274,6 +324,7 @@ // Clock divisor, can be changed on-the-fly register CLK_GPOUT1_DIV_t CLK_GPOUT1_DIV at 0x40008010; + register uint32 CLK_GPOUT1_DIV_raw at 0x40008010; type CLK_GPOUT1_SELECTED_t { CLK_GPOUT1_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. @@ -281,6 +332,21 @@ // Indicates which SRC is currently selected by the glitchless mux (one-hot). register CLK_GPOUT1_SELECTED_t CLK_GPOUT1_SELECTED at 0x40008014; + register uint32 CLK_GPOUT1_SELECTED_raw at 0x40008014; + + enum CLK_GPOUT2_CTRL_AUXSRC { + clksrc_pll_sys = 0, // + clksrc_gpin0 = 1, // + clksrc_gpin1 = 2, // + clksrc_pll_usb = 3, // + rosc_clksrc_ph = 4, // + xosc_clksrc = 5, // + clk_sys = 6, // + clk_usb = 7, // + clk_adc = 8, // + clk_rtc = 9, // + clk_ref = 10 // + } type CLK_GPOUT2_CTRL_t { _res1 = uint5(0); // Reserved, 5 bits @@ -293,10 +359,12 @@ PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect _res4 = uint2(0); // Reserved, 2 bits NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits } // Clock control, can be changed on-the-fly (except for auxsrc) register CLK_GPOUT2_CTRL_t CLK_GPOUT2_CTRL at 0x40008018; + register uint32 CLK_GPOUT2_CTRL_raw at 0x40008018; type CLK_GPOUT2_DIV_t { FRAC = uint8(0); // Fractional component of the divisor @@ -305,6 +373,7 @@ // Clock divisor, can be changed on-the-fly register CLK_GPOUT2_DIV_t CLK_GPOUT2_DIV at 0x4000801c; + register uint32 CLK_GPOUT2_DIV_raw at 0x4000801c; type CLK_GPOUT2_SELECTED_t { CLK_GPOUT2_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. @@ -312,6 +381,21 @@ // Indicates which SRC is currently selected by the glitchless mux (one-hot). register CLK_GPOUT2_SELECTED_t CLK_GPOUT2_SELECTED at 0x40008020; + register uint32 CLK_GPOUT2_SELECTED_raw at 0x40008020; + + enum CLK_GPOUT3_CTRL_AUXSRC { + clksrc_pll_sys = 0, // + clksrc_gpin0 = 1, // + clksrc_gpin1 = 2, // + clksrc_pll_usb = 3, // + rosc_clksrc_ph = 4, // + xosc_clksrc = 5, // + clk_sys = 6, // + clk_usb = 7, // + clk_adc = 8, // + clk_rtc = 9, // + clk_ref = 10 // + } type CLK_GPOUT3_CTRL_t { _res1 = uint5(0); // Reserved, 5 bits @@ -324,10 +408,12 @@ PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect _res4 = uint2(0); // Reserved, 2 bits NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits } // Clock control, can be changed on-the-fly (except for auxsrc) register CLK_GPOUT3_CTRL_t CLK_GPOUT3_CTRL at 0x40008024; + register uint32 CLK_GPOUT3_CTRL_raw at 0x40008024; type CLK_GPOUT3_DIV_t { FRAC = uint8(0); // Fractional component of the divisor @@ -336,6 +422,7 @@ // Clock divisor, can be changed on-the-fly register CLK_GPOUT3_DIV_t CLK_GPOUT3_DIV at 0x40008028; + register uint32 CLK_GPOUT3_DIV_raw at 0x40008028; type CLK_GPOUT3_SELECTED_t { CLK_GPOUT3_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. @@ -343,23 +430,40 @@ // Indicates which SRC is currently selected by the glitchless mux (one-hot). register CLK_GPOUT3_SELECTED_t CLK_GPOUT3_SELECTED at 0x4000802c; + register uint32 CLK_GPOUT3_SELECTED_raw at 0x4000802c; + + enum CLK_REF_CTRL_AUXSRC { + clksrc_pll_usb = 0, // + clksrc_gpin0 = 1, // + clksrc_gpin1 = 2 // + } + + enum CLK_REF_CTRL_SRC { + rosc_clksrc_ph = 0, // + clksrc_clk_ref_aux = 1, // + xosc_clksrc = 2 // + } type CLK_REF_CTRL_t { SRC = uint2(0); // Selects the clock source glitchlessly, can be changed on-the-fly _res1 = uint3(0); // Reserved, 3 bits AUXSRC = uint2(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint25(0); // Reserved, 25 bits } // Clock control, can be changed on-the-fly (except for auxsrc) register CLK_REF_CTRL_t CLK_REF_CTRL at 0x40008030; + register uint32 CLK_REF_CTRL_raw at 0x40008030; type CLK_REF_DIV_t { _res1 = uint8(0); // Reserved, 8 bits INT = uint2(0); // Integer component of the divisor, 0 -> divide by 2^16 + _res2 = uint22(0); // Reserved, 22 bits } // Clock divisor, can be changed on-the-fly register CLK_REF_DIV_t CLK_REF_DIV at 0x40008034; + register uint32 CLK_REF_DIV_raw at 0x40008034; type CLK_REF_SELECTED_t { CLK_REF_SELECTED = uint32(0); // The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. @@ -367,15 +471,32 @@ // Indicates which SRC is currently selected by the glitchless mux (one-hot). register CLK_REF_SELECTED_t CLK_REF_SELECTED at 0x40008038; + register uint32 CLK_REF_SELECTED_raw at 0x40008038; + + enum CLK_SYS_CTRL_AUXSRC { + clksrc_pll_sys = 0, // + clksrc_pll_usb = 1, // + rosc_clksrc = 2, // + xosc_clksrc = 3, // + clksrc_gpin0 = 4, // + clksrc_gpin1 = 5 // + } + + enum CLK_SYS_CTRL_SRC { + clk_ref = 0, // + clksrc_clk_sys_aux = 1 // + } type CLK_SYS_CTRL_t { SRC = false; // Selects the clock source glitchlessly, can be changed on-the-fly _res1 = uint4(0); // Reserved, 4 bits AUXSRC = uint3(0); // Selects the auxiliary clock source, will glitch when switching + _res2 = uint24(0); // Reserved, 24 bits } // Clock control, can be changed on-the-fly (except for auxsrc) register CLK_SYS_CTRL_t CLK_SYS_CTRL at 0x4000803c; + register uint32 CLK_SYS_CTRL_raw at 0x4000803c; type CLK_SYS_DIV_t { FRAC = uint8(0); // Fractional component of the divisor @@ -384,6 +505,7 @@ // Clock divisor, can be changed on-the-fly register CLK_SYS_DIV_t CLK_SYS_DIV at 0x40008040; + register uint32 CLK_SYS_DIV_raw at 0x40008040; type CLK_SYS_SELECTED_t { CLK_SYS_SELECTED = uint32(0); // The glitchless multiplexer does not switch instantaneously (to avoid glitches), so software should poll this register to wait for the switch to complete. This register contains one decoded bit for each of the clock sources enumerated in the CTRL SRC field. At most one of these bits will be set at any time, indicating that clock is currently present at the output of the glitchless mux. Whilst switching is in progress, this register may briefly show all-0s. @@ -391,6 +513,17 @@ // Indicates which SRC is currently selected by the glitchless mux (one-hot). register CLK_SYS_SELECTED_t CLK_SYS_SELECTED at 0x40008044; + register uint32 CLK_SYS_SELECTED_raw at 0x40008044; + + enum CLK_PERI_CTRL_AUXSRC { + clk_sys = 0, // + clksrc_pll_sys = 1, // + clksrc_pll_usb = 2, // + rosc_clksrc_ph = 3, // + xosc_clksrc = 4, // + clksrc_gpin0 = 5, // + clksrc_gpin1 = 6 // + } type CLK_PERI_CTRL_t { _res1 = uint5(0); // Reserved, 5 bits @@ -398,10 +531,12 @@ _res2 = uint2(0); // Reserved, 2 bits KILL = false; // Asynchronously kills the clock generator ENABLE = false; // Starts and stops the clock generator cleanly + _res3 = uint20(0); // Reserved, 20 bits } // Clock control, can be changed on-the-fly (except for auxsrc) register CLK_PERI_CTRL_t CLK_PERI_CTRL at 0x40008048; + register uint32 CLK_PERI_CTRL_raw at 0x40008048; type CLK_PERI_DIV_t { FRAC = uint8(0); // Fractional component of the divisor @@ -410,6 +545,7 @@ // Clock divisor, can be changed on-the-fly register CLK_PERI_DIV_t CLK_PERI_DIV at 0x4000804c; + register uint32 CLK_PERI_DIV_raw at 0x4000804c; type CLK_PERI_SELECTED_t { CLK_PERI_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. @@ -417,6 +553,16 @@ // Indicates which SRC is currently selected by the glitchless mux (one-hot). register CLK_PERI_SELECTED_t CLK_PERI_SELECTED at 0x40008050; + register uint32 CLK_PERI_SELECTED_raw at 0x40008050; + + enum CLK_USB_CTRL_AUXSRC { + clksrc_pll_usb = 0, // + clksrc_pll_sys = 1, // + rosc_clksrc_ph = 2, // + xosc_clksrc = 3, // + clksrc_gpin0 = 4, // + clksrc_gpin1 = 5 // + } type CLK_USB_CTRL_t { _res1 = uint5(0); // Reserved, 5 bits @@ -428,18 +574,22 @@ PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect _res4 = uint2(0); // Reserved, 2 bits NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits } // Clock control, can be changed on-the-fly (except for auxsrc) register CLK_USB_CTRL_t CLK_USB_CTRL at 0x40008054; + register uint32 CLK_USB_CTRL_raw at 0x40008054; type CLK_USB_DIV_t { _res1 = uint8(0); // Reserved, 8 bits INT = uint2(0); // Integer component of the divisor, 0 -> divide by 2^16 + _res2 = uint22(0); // Reserved, 22 bits } // Clock divisor, can be changed on-the-fly register CLK_USB_DIV_t CLK_USB_DIV at 0x40008058; + register uint32 CLK_USB_DIV_raw at 0x40008058; type CLK_USB_SELECTED_t { CLK_USB_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. @@ -447,6 +597,16 @@ // Indicates which SRC is currently selected by the glitchless mux (one-hot). register CLK_USB_SELECTED_t CLK_USB_SELECTED at 0x4000805c; + register uint32 CLK_USB_SELECTED_raw at 0x4000805c; + + enum CLK_ADC_CTRL_AUXSRC { + clksrc_pll_usb = 0, // + clksrc_pll_sys = 1, // + rosc_clksrc_ph = 2, // + xosc_clksrc = 3, // + clksrc_gpin0 = 4, // + clksrc_gpin1 = 5 // + } type CLK_ADC_CTRL_t { _res1 = uint5(0); // Reserved, 5 bits @@ -458,18 +618,22 @@ PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect _res4 = uint2(0); // Reserved, 2 bits NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits } // Clock control, can be changed on-the-fly (except for auxsrc) register CLK_ADC_CTRL_t CLK_ADC_CTRL at 0x40008060; + register uint32 CLK_ADC_CTRL_raw at 0x40008060; type CLK_ADC_DIV_t { _res1 = uint8(0); // Reserved, 8 bits INT = uint2(0); // Integer component of the divisor, 0 -> divide by 2^16 + _res2 = uint22(0); // Reserved, 22 bits } // Clock divisor, can be changed on-the-fly register CLK_ADC_DIV_t CLK_ADC_DIV at 0x40008064; + register uint32 CLK_ADC_DIV_raw at 0x40008064; type CLK_ADC_SELECTED_t { CLK_ADC_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. @@ -477,6 +641,16 @@ // Indicates which SRC is currently selected by the glitchless mux (one-hot). register CLK_ADC_SELECTED_t CLK_ADC_SELECTED at 0x40008068; + register uint32 CLK_ADC_SELECTED_raw at 0x40008068; + + enum CLK_RTC_CTRL_AUXSRC { + clksrc_pll_usb = 0, // + clksrc_pll_sys = 1, // + rosc_clksrc_ph = 2, // + xosc_clksrc = 3, // + clksrc_gpin0 = 4, // + clksrc_gpin1 = 5 // + } type CLK_RTC_CTRL_t { _res1 = uint5(0); // Reserved, 5 bits @@ -488,10 +662,12 @@ PHASE = uint2(0); // This delays the enable signal by up to 3 cycles of the input clock This must be set before the clock is enabled to have any effect _res4 = uint2(0); // Reserved, 2 bits NUDGE = false; // An edge on this signal shifts the phase of the output by 1 cycle of the input clock This can be done at any time + _res5 = uint11(0); // Reserved, 11 bits } // Clock control, can be changed on-the-fly (except for auxsrc) register CLK_RTC_CTRL_t CLK_RTC_CTRL at 0x4000806c; + register uint32 CLK_RTC_CTRL_raw at 0x4000806c; type CLK_RTC_DIV_t { FRAC = uint8(0); // Fractional component of the divisor @@ -500,6 +676,7 @@ // Clock divisor, can be changed on-the-fly register CLK_RTC_DIV_t CLK_RTC_DIV at 0x40008070; + register uint32 CLK_RTC_DIV_raw at 0x40008070; type CLK_RTC_SELECTED_t { CLK_RTC_SELECTED = uint32(0); // This slice does not have a glitchless mux (only the AUX_SRC field is present, not SRC) so this register is hardwired to 0x1. @@ -507,6 +684,7 @@ // Indicates which SRC is currently selected by the glitchless mux (one-hot). register CLK_RTC_SELECTED_t CLK_RTC_SELECTED at 0x40008074; + register uint32 CLK_RTC_SELECTED_raw at 0x40008074; type CLK_SYS_RESUS_CTRL_t { TIMEOUT = uint8(0); // This is expressed as a number of clk_ref cycles and must be >= 2x clk_ref_freq/min_clk_tst_freq @@ -515,59 +693,92 @@ FRCE = false; // Force a resus, for test purposes only _res2 = uint3(0); // Reserved, 3 bits CLEAR = false; // For clearing the resus after the fault that triggered it has been corrected + _res3 = uint15(0); // Reserved, 15 bits } // register CLK_SYS_RESUS_CTRL_t CLK_SYS_RESUS_CTRL at 0x40008078; + register uint32 CLK_SYS_RESUS_CTRL_raw at 0x40008078; type CLK_SYS_RESUS_STATUS_t { RESUSSED = false; // Clock has been resuscitated, correct the error then send ctrl_clear=1 + _res1 = uint31(0); // Reserved, 31 bits } // register CLK_SYS_RESUS_STATUS_t CLK_SYS_RESUS_STATUS at 0x4000807c; + register uint32 CLK_SYS_RESUS_STATUS_raw at 0x4000807c; type FC0_REF_KHZ_t { FC0_REF_KHZ = uint20(0); // + _res1 = uint12(0); // Reserved, 12 bits } // Reference clock frequency in kHz register FC0_REF_KHZ_t FC0_REF_KHZ at 0x40008080; + register uint32 FC0_REF_KHZ_raw at 0x40008080; type FC0_MIN_KHZ_t { FC0_MIN_KHZ = uint25(0); // + _res1 = uint7(0); // Reserved, 7 bits } // Minimum pass frequency in kHz. This is optional. Set to 0 if you are not using the pass/fail flags register FC0_MIN_KHZ_t FC0_MIN_KHZ at 0x40008084; + register uint32 FC0_MIN_KHZ_raw at 0x40008084; type FC0_MAX_KHZ_t { FC0_MAX_KHZ = uint25(0); // + _res1 = uint7(0); // Reserved, 7 bits } // Maximum pass frequency in kHz. This is optional. Set to 0x1ffffff if you are not using the pass/fail flags register FC0_MAX_KHZ_t FC0_MAX_KHZ at 0x40008088; + register uint32 FC0_MAX_KHZ_raw at 0x40008088; type FC0_DELAY_t { FC0_DELAY = uint3(0); // + _res1 = uint29(0); // Reserved, 29 bits } // Delays the start of frequency counting to allow the mux to settle Delay is measured in multiples of the reference clock period register FC0_DELAY_t FC0_DELAY at 0x4000808c; + register uint32 FC0_DELAY_raw at 0x4000808c; type FC0_INTERVAL_t { FC0_INTERVAL = uint4(0); // + _res1 = uint28(0); // Reserved, 28 bits } // The test interval is 0.98us * 2**interval, but let's call it 1us * 2**interval The default gives a test interval of 250us register FC0_INTERVAL_t FC0_INTERVAL at 0x40008090; + register uint32 FC0_INTERVAL_raw at 0x40008090; + + enum FC0_SRC_FC0_SRC { + NULL = 0, // + pll_sys_clksrc_primary = 1, // + pll_usb_clksrc_primary = 2, // + rosc_clksrc = 3, // + rosc_clksrc_ph = 4, // + xosc_clksrc = 5, // + clksrc_gpin0 = 6, // + clksrc_gpin1 = 7, // + clk_ref = 8, // + clk_sys = 9, // + clk_peri = 10, // + clk_usb = 11, // + clk_adc = 12, // + clk_rtc = 13 // + } type FC0_SRC_t { FC0_SRC = uint8(0); // + _res1 = uint24(0); // Reserved, 24 bits } // Clock sent to frequency counter, set to 0 when not required Writing to this register initiates the frequency count register FC0_SRC_t FC0_SRC at 0x40008094; + register uint32 FC0_SRC_raw at 0x40008094; type FC0_STATUS_t { PASS = false; // Test passed @@ -585,18 +796,22 @@ FAST = false; // Test clock faster than expected, only valid when status_done=1 _res7 = uint3(0); // Reserved, 3 bits DIED = false; // Test clock stopped during test + _res8 = uint3(0); // Reserved, 3 bits } // Frequency counter status register FC0_STATUS_t FC0_STATUS at 0x40008098; + register uint32 FC0_STATUS_raw at 0x40008098; type FC0_RESULT_t { - FRAC = uint5(0); // - KHZ = uint25(0); // + FRAC = uint5(0); // + KHZ = uint25(0); // + _res1 = uint2(0); // Reserved, 2 bits } // Result of frequency measurement, only valid when status_done=1 register FC0_RESULT_t FC0_RESULT at 0x4000809c; + register uint32 FC0_RESULT_raw at 0x4000809c; type WAKE_EN0_t { CLK_SYS_CLOCKS = false; // @@ -635,6 +850,7 @@ // enable clock in wake mode register WAKE_EN0_t WAKE_EN0 at 0x400080a0; + register uint32 WAKE_EN0_raw at 0x400080a0; type WAKE_EN1_t { CLK_SYS_SRAM4 = false; // @@ -652,10 +868,12 @@ CLK_SYS_WATCHDOG = false; // CLK_SYS_XIP = false; // CLK_SYS_XOSC = false; // + _res1 = uint17(0); // Reserved, 17 bits } // enable clock in wake mode register WAKE_EN1_t WAKE_EN1 at 0x400080a4; + register uint32 WAKE_EN1_raw at 0x400080a4; type SLEEP_EN0_t { CLK_SYS_CLOCKS = false; // @@ -694,6 +912,7 @@ // enable clock in sleep mode register SLEEP_EN0_t SLEEP_EN0 at 0x400080a8; + register uint32 SLEEP_EN0_raw at 0x400080a8; type SLEEP_EN1_t { CLK_SYS_SRAM4 = false; // @@ -711,10 +930,12 @@ CLK_SYS_WATCHDOG = false; // CLK_SYS_XIP = false; // CLK_SYS_XOSC = false; // + _res1 = uint17(0); // Reserved, 17 bits } // enable clock in sleep mode register SLEEP_EN1_t SLEEP_EN1 at 0x400080ac; + register uint32 SLEEP_EN1_raw at 0x400080ac; type ENABLED0_t { CLK_SYS_CLOCKS = false; // @@ -753,6 +974,7 @@ // indicates the state of the clock enable register ENABLED0_t ENABLED0 at 0x400080b0; + register uint32 ENABLED0_raw at 0x400080b0; type ENABLED1_t { CLK_SYS_SRAM4 = false; // @@ -770,48 +992,72 @@ CLK_SYS_WATCHDOG = false; // CLK_SYS_XIP = false; // CLK_SYS_XOSC = false; // + _res1 = uint17(0); // Reserved, 17 bits } // indicates the state of the clock enable register ENABLED1_t ENABLED1 at 0x400080b4; + register uint32 ENABLED1_raw at 0x400080b4; type CLOCKS_INTR_t { CLK_SYS_RESUS = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Raw Interrupts register CLOCKS_INTR_t CLOCKS_INTR at 0x400080b8; + register uint32 CLOCKS_INTR_raw at 0x400080b8; type CLOCKS_INTE_t { CLK_SYS_RESUS = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Interrupt Enable register CLOCKS_INTE_t CLOCKS_INTE at 0x400080bc; + register uint32 CLOCKS_INTE_raw at 0x400080bc; type CLOCKS_INTF_t { CLK_SYS_RESUS = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Interrupt Force register CLOCKS_INTF_t CLOCKS_INTF at 0x400080c0; + register uint32 CLOCKS_INTF_raw at 0x400080c0; type CLOCKS_INTS_t { CLK_SYS_RESUS = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Interrupt status after masking & forcing register CLOCKS_INTS_t CLOCKS_INTS at 0x400080c4; + register uint32 CLOCKS_INTS_raw at 0x400080c4; /* Types and registers for PADS_BANK0 */ + enum PADS_BANK0_VOLTAGE_SELECT_VOLTAGE_SELECT { + _3v3 = 0, // Set voltage to 3.3V (DVDD >= 2V5) + _1v8 = 1 // Set voltage to 1.8V (DVDD <= 1V8) + } + type PADS_BANK0_VOLTAGE_SELECT_t { VOLTAGE_SELECT = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Voltage select. Per bank control register PADS_BANK0_VOLTAGE_SELECT_t PADS_BANK0_VOLTAGE_SELECT at 0x4001c000; + register uint32 PADS_BANK0_VOLTAGE_SELECT_raw at 0x4001c000; + + enum GPIO0_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO0_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -821,10 +1067,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO0_t GPIO0 at 0x4001c004; + register uint32 GPIO0_raw at 0x4001c004; + + enum GPIO1_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO1_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -834,10 +1089,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO1_t GPIO1 at 0x4001c008; + register uint32 GPIO1_raw at 0x4001c008; + + enum GPIO2_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO2_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -847,10 +1111,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO2_t GPIO2 at 0x4001c00c; + register uint32 GPIO2_raw at 0x4001c00c; + + enum GPIO3_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO3_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -860,10 +1133,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO3_t GPIO3 at 0x4001c010; + register uint32 GPIO3_raw at 0x4001c010; + + enum GPIO4_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO4_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -873,10 +1155,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO4_t GPIO4 at 0x4001c014; + register uint32 GPIO4_raw at 0x4001c014; + + enum GPIO5_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO5_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -886,10 +1177,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO5_t GPIO5 at 0x4001c018; + register uint32 GPIO5_raw at 0x4001c018; + + enum GPIO6_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO6_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -899,10 +1199,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO6_t GPIO6 at 0x4001c01c; + register uint32 GPIO6_raw at 0x4001c01c; + + enum GPIO7_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO7_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -912,10 +1221,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO7_t GPIO7 at 0x4001c020; + register uint32 GPIO7_raw at 0x4001c020; + + enum GPIO8_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO8_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -925,10 +1243,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO8_t GPIO8 at 0x4001c024; + register uint32 GPIO8_raw at 0x4001c024; + + enum GPIO9_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO9_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -938,10 +1265,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO9_t GPIO9 at 0x4001c028; + register uint32 GPIO9_raw at 0x4001c028; + + enum GPIO10_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO10_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -951,10 +1287,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO10_t GPIO10 at 0x4001c02c; + register uint32 GPIO10_raw at 0x4001c02c; + + enum GPIO11_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO11_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -964,10 +1309,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO11_t GPIO11 at 0x4001c030; + register uint32 GPIO11_raw at 0x4001c030; + + enum GPIO12_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO12_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -977,10 +1331,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO12_t GPIO12 at 0x4001c034; + register uint32 GPIO12_raw at 0x4001c034; + + enum GPIO13_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO13_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -990,10 +1353,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO13_t GPIO13 at 0x4001c038; + register uint32 GPIO13_raw at 0x4001c038; + + enum GPIO14_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO14_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1003,10 +1375,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO14_t GPIO14 at 0x4001c03c; + register uint32 GPIO14_raw at 0x4001c03c; + + enum GPIO15_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO15_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1016,10 +1397,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO15_t GPIO15 at 0x4001c040; + register uint32 GPIO15_raw at 0x4001c040; + + enum GPIO16_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO16_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1029,10 +1419,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO16_t GPIO16 at 0x4001c044; + register uint32 GPIO16_raw at 0x4001c044; + + enum GPIO17_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO17_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1042,10 +1441,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO17_t GPIO17 at 0x4001c048; + register uint32 GPIO17_raw at 0x4001c048; + + enum GPIO18_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO18_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1055,10 +1463,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO18_t GPIO18 at 0x4001c04c; + register uint32 GPIO18_raw at 0x4001c04c; + + enum GPIO19_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO19_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1068,10 +1485,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO19_t GPIO19 at 0x4001c050; + register uint32 GPIO19_raw at 0x4001c050; + + enum GPIO20_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO20_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1081,10 +1507,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO20_t GPIO20 at 0x4001c054; + register uint32 GPIO20_raw at 0x4001c054; + + enum GPIO21_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO21_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1094,10 +1529,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO21_t GPIO21 at 0x4001c058; + register uint32 GPIO21_raw at 0x4001c058; + + enum GPIO22_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO22_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1107,10 +1551,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO22_t GPIO22 at 0x4001c05c; + register uint32 GPIO22_raw at 0x4001c05c; + + enum GPIO23_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO23_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1120,10 +1573,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO23_t GPIO23 at 0x4001c060; + register uint32 GPIO23_raw at 0x4001c060; + + enum GPIO24_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO24_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1133,10 +1595,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO24_t GPIO24 at 0x4001c064; + register uint32 GPIO24_raw at 0x4001c064; + + enum GPIO25_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO25_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1146,10 +1617,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO25_t GPIO25 at 0x4001c068; + register uint32 GPIO25_raw at 0x4001c068; + + enum GPIO26_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO26_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1159,10 +1639,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO26_t GPIO26 at 0x4001c06c; + register uint32 GPIO26_raw at 0x4001c06c; + + enum GPIO27_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO27_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1172,10 +1661,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO27_t GPIO27 at 0x4001c070; + register uint32 GPIO27_raw at 0x4001c070; + + enum GPIO28_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO28_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1185,10 +1683,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO28_t GPIO28 at 0x4001c074; + register uint32 GPIO28_raw at 0x4001c074; + + enum GPIO29_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO29_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1198,10 +1705,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO29_t GPIO29 at 0x4001c078; + register uint32 GPIO29_raw at 0x4001c078; + + enum SWCLK_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type SWCLK_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1211,10 +1727,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register SWCLK_t SWCLK at 0x4001c07c; + register uint32 SWCLK_raw at 0x4001c07c; + + enum SWD_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type SWD_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1224,20 +1749,36 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register SWD_t SWD at 0x4001c080; + register uint32 SWD_raw at 0x4001c080; /* Types and registers for PADS_QSPI */ + enum PADS_QSPI_VOLTAGE_SELECT_VOLTAGE_SELECT { + _3v3 = 0, // Set voltage to 3.3V (DVDD >= 2V5) + _1v8 = 1 // Set voltage to 1.8V (DVDD <= 1V8) + } + type PADS_QSPI_VOLTAGE_SELECT_t { VOLTAGE_SELECT = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Voltage select. Per bank control register PADS_QSPI_VOLTAGE_SELECT_t PADS_QSPI_VOLTAGE_SELECT at 0x40020000; + register uint32 PADS_QSPI_VOLTAGE_SELECT_raw at 0x40020000; + + enum GPIO_QSPI_SCLK_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO_QSPI_SCLK_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1247,10 +1788,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO_QSPI_SCLK_t GPIO_QSPI_SCLK at 0x40020004; + register uint32 GPIO_QSPI_SCLK_raw at 0x40020004; + + enum GPIO_QSPI_SD0_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO_QSPI_SD0_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1260,10 +1810,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO_QSPI_SD0_t GPIO_QSPI_SD0 at 0x40020008; + register uint32 GPIO_QSPI_SD0_raw at 0x40020008; + + enum GPIO_QSPI_SD1_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO_QSPI_SD1_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1273,10 +1832,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO_QSPI_SD1_t GPIO_QSPI_SD1 at 0x4002000c; + register uint32 GPIO_QSPI_SD1_raw at 0x4002000c; + + enum GPIO_QSPI_SD2_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO_QSPI_SD2_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1286,10 +1854,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO_QSPI_SD2_t GPIO_QSPI_SD2 at 0x40020010; + register uint32 GPIO_QSPI_SD2_raw at 0x40020010; + + enum GPIO_QSPI_SD3_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO_QSPI_SD3_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1299,10 +1876,19 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO_QSPI_SD3_t GPIO_QSPI_SD3 at 0x40020014; + register uint32 GPIO_QSPI_SD3_raw at 0x40020014; + + enum GPIO_QSPI_SS_DRIVE { + _2mA = 0, // + _4mA = 1, // + _8mA = 2, // + _12mA = 3 // + } type GPIO_QSPI_SS_t { SLEWFAST = false; // Slew rate control. 1 = Fast, 0 = Slow @@ -1312,10 +1898,12 @@ DRIVE = uint2(0); // Drive strength. IE = false; // Input enable OD = false; // Output disable. Has priority over output enable from peripherals + _res1 = uint24(0); // Reserved, 24 bits } // Pad control register register GPIO_QSPI_SS_t GPIO_QSPI_SS at 0x40020018; + register uint32 GPIO_QSPI_SS_raw at 0x40020018; /* Types and registers for IO_QSPI */ @@ -1335,10 +1923,46 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO_QSPI_SCLK_STATUS_t GPIO_QSPI_SCLK_STATUS at 0x40018000; + register uint32 GPIO_QSPI_SCLK_STATUS_raw at 0x40018000; + + enum GPIO_QSPI_SCLK_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SCLK_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SCLK_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SCLK_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SCLK_CTRL_FUNCSEL { + xip_sclk = 0, // + sio_30 = 5, // + null = 31 // + } type GPIO_QSPI_SCLK_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -1348,13 +1972,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO_QSPI_SCLK_CTRL_t GPIO_QSPI_SCLK_CTRL at 0x40018004; + register uint32 GPIO_QSPI_SCLK_CTRL_raw at 0x40018004; type GPIO_QSPI_SS_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -1371,10 +1996,46 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO_QSPI_SS_STATUS_t GPIO_QSPI_SS_STATUS at 0x40018008; + register uint32 GPIO_QSPI_SS_STATUS_raw at 0x40018008; + + enum GPIO_QSPI_SS_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SS_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SS_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SS_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SS_CTRL_FUNCSEL { + xip_ss_n = 0, // + sio_31 = 5, // + null = 31 // + } type GPIO_QSPI_SS_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -1384,13 +2045,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO_QSPI_SS_CTRL_t GPIO_QSPI_SS_CTRL at 0x4001800c; + register uint32 GPIO_QSPI_SS_CTRL_raw at 0x4001800c; type GPIO_QSPI_SD0_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -1407,10 +2069,46 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO_QSPI_SD0_STATUS_t GPIO_QSPI_SD0_STATUS at 0x40018010; + register uint32 GPIO_QSPI_SD0_STATUS_raw at 0x40018010; + + enum GPIO_QSPI_SD0_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SD0_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SD0_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SD0_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SD0_CTRL_FUNCSEL { + xip_sd0 = 0, // + sio_32 = 5, // + null = 31 // + } type GPIO_QSPI_SD0_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -1420,13 +2118,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO_QSPI_SD0_CTRL_t GPIO_QSPI_SD0_CTRL at 0x40018014; + register uint32 GPIO_QSPI_SD0_CTRL_raw at 0x40018014; type GPIO_QSPI_SD1_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -1443,10 +2142,46 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO_QSPI_SD1_STATUS_t GPIO_QSPI_SD1_STATUS at 0x40018018; + register uint32 GPIO_QSPI_SD1_STATUS_raw at 0x40018018; + + enum GPIO_QSPI_SD1_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SD1_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SD1_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SD1_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SD1_CTRL_FUNCSEL { + xip_sd1 = 0, // + sio_33 = 5, // + null = 31 // + } type GPIO_QSPI_SD1_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -1456,13 +2191,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO_QSPI_SD1_CTRL_t GPIO_QSPI_SD1_CTRL at 0x4001801c; + register uint32 GPIO_QSPI_SD1_CTRL_raw at 0x4001801c; type GPIO_QSPI_SD2_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -1479,10 +2215,46 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO_QSPI_SD2_STATUS_t GPIO_QSPI_SD2_STATUS at 0x40018020; + register uint32 GPIO_QSPI_SD2_STATUS_raw at 0x40018020; + + enum GPIO_QSPI_SD2_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SD2_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SD2_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SD2_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SD2_CTRL_FUNCSEL { + xip_sd2 = 0, // + sio_34 = 5, // + null = 31 // + } type GPIO_QSPI_SD2_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -1492,13 +2264,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO_QSPI_SD2_CTRL_t GPIO_QSPI_SD2_CTRL at 0x40018024; + register uint32 GPIO_QSPI_SD2_CTRL_raw at 0x40018024; type GPIO_QSPI_SD3_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -1515,10 +2288,46 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO_QSPI_SD3_STATUS_t GPIO_QSPI_SD3_STATUS at 0x40018028; + register uint32 GPIO_QSPI_SD3_STATUS_raw at 0x40018028; + + enum GPIO_QSPI_SD3_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO_QSPI_SD3_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO_QSPI_SD3_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO_QSPI_SD3_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO_QSPI_SD3_CTRL_FUNCSEL { + xip_sd3 = 0, // + sio_35 = 5, // + null = 31 // + } type GPIO_QSPI_SD3_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -1528,13 +2337,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO_QSPI_SD3_CTRL_t GPIO_QSPI_SD3_CTRL at 0x4001802c; + register uint32 GPIO_QSPI_SD3_CTRL_raw at 0x4001802c; type IO_QSPI_INTR_t { GPIO_QSPI_SCLK_LEVEL_LOW = false; // @@ -1561,10 +2371,12 @@ GPIO_QSPI_SD3_LEVEL_HIGH = false; // GPIO_QSPI_SD3_EDGE_LOW = false; // GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Raw Interrupts register IO_QSPI_INTR_t IO_QSPI_INTR at 0x40018030; + register uint32 IO_QSPI_INTR_raw at 0x40018030; type PROC0_INTE_t { GPIO_QSPI_SCLK_LEVEL_LOW = false; // @@ -1591,10 +2403,12 @@ GPIO_QSPI_SD3_LEVEL_HIGH = false; // GPIO_QSPI_SD3_EDGE_LOW = false; // GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Enable for proc0 register PROC0_INTE_t PROC0_INTE at 0x40018034; + register uint32 PROC0_INTE_raw at 0x40018034; type PROC0_INTF_t { GPIO_QSPI_SCLK_LEVEL_LOW = false; // @@ -1621,10 +2435,12 @@ GPIO_QSPI_SD3_LEVEL_HIGH = false; // GPIO_QSPI_SD3_EDGE_LOW = false; // GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Force for proc0 register PROC0_INTF_t PROC0_INTF at 0x40018038; + register uint32 PROC0_INTF_raw at 0x40018038; type PROC0_INTS_t { GPIO_QSPI_SCLK_LEVEL_LOW = false; // @@ -1651,10 +2467,12 @@ GPIO_QSPI_SD3_LEVEL_HIGH = false; // GPIO_QSPI_SD3_EDGE_LOW = false; // GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt status after masking & forcing for proc0 register PROC0_INTS_t PROC0_INTS at 0x4001803c; + register uint32 PROC0_INTS_raw at 0x4001803c; type PROC1_INTE_t { GPIO_QSPI_SCLK_LEVEL_LOW = false; // @@ -1681,10 +2499,12 @@ GPIO_QSPI_SD3_LEVEL_HIGH = false; // GPIO_QSPI_SD3_EDGE_LOW = false; // GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Enable for proc1 register PROC1_INTE_t PROC1_INTE at 0x40018040; + register uint32 PROC1_INTE_raw at 0x40018040; type PROC1_INTF_t { GPIO_QSPI_SCLK_LEVEL_LOW = false; // @@ -1711,10 +2531,12 @@ GPIO_QSPI_SD3_LEVEL_HIGH = false; // GPIO_QSPI_SD3_EDGE_LOW = false; // GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Force for proc1 register PROC1_INTF_t PROC1_INTF at 0x40018044; + register uint32 PROC1_INTF_raw at 0x40018044; type PROC1_INTS_t { GPIO_QSPI_SCLK_LEVEL_LOW = false; // @@ -1741,10 +2563,12 @@ GPIO_QSPI_SD3_LEVEL_HIGH = false; // GPIO_QSPI_SD3_EDGE_LOW = false; // GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt status after masking & forcing for proc1 register PROC1_INTS_t PROC1_INTS at 0x40018048; + register uint32 PROC1_INTS_raw at 0x40018048; type DORMANT_WAKE_INTE_t { GPIO_QSPI_SCLK_LEVEL_LOW = false; // @@ -1771,10 +2595,12 @@ GPIO_QSPI_SD3_LEVEL_HIGH = false; // GPIO_QSPI_SD3_EDGE_LOW = false; // GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Enable for dormant_wake register DORMANT_WAKE_INTE_t DORMANT_WAKE_INTE at 0x4001804c; + register uint32 DORMANT_WAKE_INTE_raw at 0x4001804c; type DORMANT_WAKE_INTF_t { GPIO_QSPI_SCLK_LEVEL_LOW = false; // @@ -1801,10 +2627,12 @@ GPIO_QSPI_SD3_LEVEL_HIGH = false; // GPIO_QSPI_SD3_EDGE_LOW = false; // GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Force for dormant_wake register DORMANT_WAKE_INTF_t DORMANT_WAKE_INTF at 0x40018050; + register uint32 DORMANT_WAKE_INTF_raw at 0x40018050; type DORMANT_WAKE_INTS_t { GPIO_QSPI_SCLK_LEVEL_LOW = false; // @@ -1831,10 +2659,12 @@ GPIO_QSPI_SD3_LEVEL_HIGH = false; // GPIO_QSPI_SD3_EDGE_LOW = false; // GPIO_QSPI_SD3_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt status after masking & forcing for dormant_wake register DORMANT_WAKE_INTS_t DORMANT_WAKE_INTS at 0x40018054; + register uint32 DORMANT_WAKE_INTS_raw at 0x40018054; /* Types and registers for IO_BANK0 */ @@ -1854,10 +2684,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO0_STATUS_t GPIO0_STATUS at 0x40014000; + register uint32 GPIO0_STATUS_raw at 0x40014000; + + enum GPIO0_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO0_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO0_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO0_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO0_CTRL_FUNCSEL { + jtag_tck = 0, // + spi0_rx = 1, // + uart0_tx = 2, // + i2c0_sda = 3, // + pwm_a_0 = 4, // + sio_0 = 5, // + pio0_0 = 6, // + pio1_0 = 7, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } type GPIO0_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -1867,13 +2740,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO0_CTRL_t GPIO0_CTRL at 0x40014004; + register uint32 GPIO0_CTRL_raw at 0x40014004; type GPIO1_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -1890,10 +2764,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO1_STATUS_t GPIO1_STATUS at 0x40014008; + register uint32 GPIO1_STATUS_raw at 0x40014008; + + enum GPIO1_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO1_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO1_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO1_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO1_CTRL_FUNCSEL { + jtag_tms = 0, // + spi0_ss_n = 1, // + uart0_rx = 2, // + i2c0_scl = 3, // + pwm_b_0 = 4, // + sio_1 = 5, // + pio0_1 = 6, // + pio1_1 = 7, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } type GPIO1_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -1903,13 +2820,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO1_CTRL_t GPIO1_CTRL at 0x4001400c; + register uint32 GPIO1_CTRL_raw at 0x4001400c; type GPIO2_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -1926,10 +2844,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO2_STATUS_t GPIO2_STATUS at 0x40014010; + register uint32 GPIO2_STATUS_raw at 0x40014010; + + enum GPIO2_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO2_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO2_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO2_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO2_CTRL_FUNCSEL { + jtag_tdi = 0, // + spi0_sclk = 1, // + uart0_cts = 2, // + i2c1_sda = 3, // + pwm_a_1 = 4, // + sio_2 = 5, // + pio0_2 = 6, // + pio1_2 = 7, // + usb_muxing_vbus_en = 9, // + null = 31 // + } type GPIO2_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -1939,13 +2900,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO2_CTRL_t GPIO2_CTRL at 0x40014014; + register uint32 GPIO2_CTRL_raw at 0x40014014; type GPIO3_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -1962,10 +2924,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO3_STATUS_t GPIO3_STATUS at 0x40014018; + register uint32 GPIO3_STATUS_raw at 0x40014018; + + enum GPIO3_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO3_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO3_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO3_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO3_CTRL_FUNCSEL { + jtag_tdo = 0, // + spi0_tx = 1, // + uart0_rts = 2, // + i2c1_scl = 3, // + pwm_b_1 = 4, // + sio_3 = 5, // + pio0_3 = 6, // + pio1_3 = 7, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } type GPIO3_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -1975,13 +2980,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO3_CTRL_t GPIO3_CTRL at 0x4001401c; + register uint32 GPIO3_CTRL_raw at 0x4001401c; type GPIO4_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -1998,10 +3004,52 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO4_STATUS_t GPIO4_STATUS at 0x40014020; + register uint32 GPIO4_STATUS_raw at 0x40014020; + + enum GPIO4_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO4_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO4_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO4_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO4_CTRL_FUNCSEL { + spi0_rx = 1, // + uart1_tx = 2, // + i2c0_sda = 3, // + pwm_a_2 = 4, // + sio_4 = 5, // + pio0_4 = 6, // + pio1_4 = 7, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } type GPIO4_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2011,13 +3059,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO4_CTRL_t GPIO4_CTRL at 0x40014024; + register uint32 GPIO4_CTRL_raw at 0x40014024; type GPIO5_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2034,10 +3083,52 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO5_STATUS_t GPIO5_STATUS at 0x40014028; + register uint32 GPIO5_STATUS_raw at 0x40014028; + + enum GPIO5_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO5_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO5_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO5_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO5_CTRL_FUNCSEL { + spi0_ss_n = 1, // + uart1_rx = 2, // + i2c0_scl = 3, // + pwm_b_2 = 4, // + sio_5 = 5, // + pio0_5 = 6, // + pio1_5 = 7, // + usb_muxing_vbus_en = 9, // + null = 31 // + } type GPIO5_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2047,13 +3138,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO5_CTRL_t GPIO5_CTRL at 0x4001402c; + register uint32 GPIO5_CTRL_raw at 0x4001402c; type GPIO6_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2070,10 +3162,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO6_STATUS_t GPIO6_STATUS at 0x40014030; + register uint32 GPIO6_STATUS_raw at 0x40014030; + + enum GPIO6_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO6_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO6_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO6_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO6_CTRL_FUNCSEL { + spi0_sclk = 1, // + uart1_cts = 2, // + i2c1_sda = 3, // + pwm_a_3 = 4, // + sio_6 = 5, // + pio0_6 = 6, // + pio1_6 = 7, // + usb_muxing_extphy_softcon = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } type GPIO6_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2083,13 +3218,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO6_CTRL_t GPIO6_CTRL at 0x40014034; + register uint32 GPIO6_CTRL_raw at 0x40014034; type GPIO7_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2106,10 +3242,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO7_STATUS_t GPIO7_STATUS at 0x40014038; + register uint32 GPIO7_STATUS_raw at 0x40014038; + + enum GPIO7_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO7_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO7_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO7_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO7_CTRL_FUNCSEL { + spi0_tx = 1, // + uart1_rts = 2, // + i2c1_scl = 3, // + pwm_b_3 = 4, // + sio_7 = 5, // + pio0_7 = 6, // + pio1_7 = 7, // + usb_muxing_extphy_oe_n = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } type GPIO7_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2119,13 +3298,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO7_CTRL_t GPIO7_CTRL at 0x4001403c; + register uint32 GPIO7_CTRL_raw at 0x4001403c; type GPIO8_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2142,10 +3322,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO8_STATUS_t GPIO8_STATUS at 0x40014040; + register uint32 GPIO8_STATUS_raw at 0x40014040; + + enum GPIO8_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO8_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO8_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO8_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO8_CTRL_FUNCSEL { + spi1_rx = 1, // + uart1_tx = 2, // + i2c0_sda = 3, // + pwm_a_4 = 4, // + sio_8 = 5, // + pio0_8 = 6, // + pio1_8 = 7, // + usb_muxing_extphy_rcv = 8, // + usb_muxing_vbus_en = 9, // + null = 31 // + } type GPIO8_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2155,13 +3378,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO8_CTRL_t GPIO8_CTRL at 0x40014044; + register uint32 GPIO8_CTRL_raw at 0x40014044; type GPIO9_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2178,10 +3402,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO9_STATUS_t GPIO9_STATUS at 0x40014048; + register uint32 GPIO9_STATUS_raw at 0x40014048; + + enum GPIO9_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO9_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO9_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO9_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO9_CTRL_FUNCSEL { + spi1_ss_n = 1, // + uart1_rx = 2, // + i2c0_scl = 3, // + pwm_b_4 = 4, // + sio_9 = 5, // + pio0_9 = 6, // + pio1_9 = 7, // + usb_muxing_extphy_vp = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } type GPIO9_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2191,13 +3458,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO9_CTRL_t GPIO9_CTRL at 0x4001404c; + register uint32 GPIO9_CTRL_raw at 0x4001404c; type GPIO10_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2214,10 +3482,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO10_STATUS_t GPIO10_STATUS at 0x40014050; + register uint32 GPIO10_STATUS_raw at 0x40014050; + + enum GPIO10_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO10_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO10_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO10_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO10_CTRL_FUNCSEL { + spi1_sclk = 1, // + uart1_cts = 2, // + i2c1_sda = 3, // + pwm_a_5 = 4, // + sio_10 = 5, // + pio0_10 = 6, // + pio1_10 = 7, // + usb_muxing_extphy_vm = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } type GPIO10_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2227,13 +3538,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO10_CTRL_t GPIO10_CTRL at 0x40014054; + register uint32 GPIO10_CTRL_raw at 0x40014054; type GPIO11_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2250,10 +3562,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO11_STATUS_t GPIO11_STATUS at 0x40014058; + register uint32 GPIO11_STATUS_raw at 0x40014058; + + enum GPIO11_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO11_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO11_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO11_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO11_CTRL_FUNCSEL { + spi1_tx = 1, // + uart1_rts = 2, // + i2c1_scl = 3, // + pwm_b_5 = 4, // + sio_11 = 5, // + pio0_11 = 6, // + pio1_11 = 7, // + usb_muxing_extphy_suspnd = 8, // + usb_muxing_vbus_en = 9, // + null = 31 // + } type GPIO11_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2263,13 +3618,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO11_CTRL_t GPIO11_CTRL at 0x4001405c; + register uint32 GPIO11_CTRL_raw at 0x4001405c; type GPIO12_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2286,10 +3642,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO12_STATUS_t GPIO12_STATUS at 0x40014060; + register uint32 GPIO12_STATUS_raw at 0x40014060; + + enum GPIO12_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO12_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO12_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO12_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO12_CTRL_FUNCSEL { + spi1_rx = 1, // + uart0_tx = 2, // + i2c0_sda = 3, // + pwm_a_6 = 4, // + sio_12 = 5, // + pio0_12 = 6, // + pio1_12 = 7, // + usb_muxing_extphy_speed = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } type GPIO12_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2299,13 +3698,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO12_CTRL_t GPIO12_CTRL at 0x40014064; + register uint32 GPIO12_CTRL_raw at 0x40014064; type GPIO13_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2322,10 +3722,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO13_STATUS_t GPIO13_STATUS at 0x40014068; + register uint32 GPIO13_STATUS_raw at 0x40014068; + + enum GPIO13_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO13_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO13_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO13_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO13_CTRL_FUNCSEL { + spi1_ss_n = 1, // + uart0_rx = 2, // + i2c0_scl = 3, // + pwm_b_6 = 4, // + sio_13 = 5, // + pio0_13 = 6, // + pio1_13 = 7, // + usb_muxing_extphy_vpo = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } type GPIO13_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2335,13 +3778,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO13_CTRL_t GPIO13_CTRL at 0x4001406c; + register uint32 GPIO13_CTRL_raw at 0x4001406c; type GPIO14_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2358,10 +3802,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO14_STATUS_t GPIO14_STATUS at 0x40014070; + register uint32 GPIO14_STATUS_raw at 0x40014070; + + enum GPIO14_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO14_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO14_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO14_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO14_CTRL_FUNCSEL { + spi1_sclk = 1, // + uart0_cts = 2, // + i2c1_sda = 3, // + pwm_a_7 = 4, // + sio_14 = 5, // + pio0_14 = 6, // + pio1_14 = 7, // + usb_muxing_extphy_vmo = 8, // + usb_muxing_vbus_en = 9, // + null = 31 // + } type GPIO14_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2371,13 +3858,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO14_CTRL_t GPIO14_CTRL at 0x40014074; + register uint32 GPIO14_CTRL_raw at 0x40014074; type GPIO15_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2394,10 +3882,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO15_STATUS_t GPIO15_STATUS at 0x40014078; + register uint32 GPIO15_STATUS_raw at 0x40014078; + + enum GPIO15_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO15_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO15_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO15_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO15_CTRL_FUNCSEL { + spi1_tx = 1, // + uart0_rts = 2, // + i2c1_scl = 3, // + pwm_b_7 = 4, // + sio_15 = 5, // + pio0_15 = 6, // + pio1_15 = 7, // + usb_muxing_digital_dp = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } type GPIO15_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2407,13 +3938,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO15_CTRL_t GPIO15_CTRL at 0x4001407c; + register uint32 GPIO15_CTRL_raw at 0x4001407c; type GPIO16_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2430,10 +3962,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO16_STATUS_t GPIO16_STATUS at 0x40014080; + register uint32 GPIO16_STATUS_raw at 0x40014080; + + enum GPIO16_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO16_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO16_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO16_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO16_CTRL_FUNCSEL { + spi0_rx = 1, // + uart0_tx = 2, // + i2c0_sda = 3, // + pwm_a_0 = 4, // + sio_16 = 5, // + pio0_16 = 6, // + pio1_16 = 7, // + usb_muxing_digital_dm = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } type GPIO16_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2443,13 +4018,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO16_CTRL_t GPIO16_CTRL at 0x40014084; + register uint32 GPIO16_CTRL_raw at 0x40014084; type GPIO17_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2466,10 +4042,52 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO17_STATUS_t GPIO17_STATUS at 0x40014088; + register uint32 GPIO17_STATUS_raw at 0x40014088; + + enum GPIO17_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO17_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO17_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO17_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO17_CTRL_FUNCSEL { + spi0_ss_n = 1, // + uart0_rx = 2, // + i2c0_scl = 3, // + pwm_b_0 = 4, // + sio_17 = 5, // + pio0_17 = 6, // + pio1_17 = 7, // + usb_muxing_vbus_en = 9, // + null = 31 // + } type GPIO17_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2479,13 +4097,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO17_CTRL_t GPIO17_CTRL at 0x4001408c; + register uint32 GPIO17_CTRL_raw at 0x4001408c; type GPIO18_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2502,10 +4121,52 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO18_STATUS_t GPIO18_STATUS at 0x40014090; + register uint32 GPIO18_STATUS_raw at 0x40014090; + + enum GPIO18_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO18_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO18_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO18_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO18_CTRL_FUNCSEL { + spi0_sclk = 1, // + uart0_cts = 2, // + i2c1_sda = 3, // + pwm_a_1 = 4, // + sio_18 = 5, // + pio0_18 = 6, // + pio1_18 = 7, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } type GPIO18_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2515,13 +4176,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO18_CTRL_t GPIO18_CTRL at 0x40014094; + register uint32 GPIO18_CTRL_raw at 0x40014094; type GPIO19_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2538,10 +4200,52 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO19_STATUS_t GPIO19_STATUS at 0x40014098; + register uint32 GPIO19_STATUS_raw at 0x40014098; + + enum GPIO19_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO19_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO19_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO19_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO19_CTRL_FUNCSEL { + spi0_tx = 1, // + uart0_rts = 2, // + i2c1_scl = 3, // + pwm_b_1 = 4, // + sio_19 = 5, // + pio0_19 = 6, // + pio1_19 = 7, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } type GPIO19_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2551,13 +4255,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO19_CTRL_t GPIO19_CTRL at 0x4001409c; + register uint32 GPIO19_CTRL_raw at 0x4001409c; type GPIO20_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2574,10 +4279,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO20_STATUS_t GPIO20_STATUS at 0x400140a0; + register uint32 GPIO20_STATUS_raw at 0x400140a0; + + enum GPIO20_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO20_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO20_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO20_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO20_CTRL_FUNCSEL { + spi0_rx = 1, // + uart1_tx = 2, // + i2c0_sda = 3, // + pwm_a_2 = 4, // + sio_20 = 5, // + pio0_20 = 6, // + pio1_20 = 7, // + clocks_gpin_0 = 8, // + usb_muxing_vbus_en = 9, // + null = 31 // + } type GPIO20_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2587,13 +4335,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO20_CTRL_t GPIO20_CTRL at 0x400140a4; + register uint32 GPIO20_CTRL_raw at 0x400140a4; type GPIO21_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2610,10 +4359,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO21_STATUS_t GPIO21_STATUS at 0x400140a8; + register uint32 GPIO21_STATUS_raw at 0x400140a8; + + enum GPIO21_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO21_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO21_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO21_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO21_CTRL_FUNCSEL { + spi0_ss_n = 1, // + uart1_rx = 2, // + i2c0_scl = 3, // + pwm_b_2 = 4, // + sio_21 = 5, // + pio0_21 = 6, // + pio1_21 = 7, // + clocks_gpout_0 = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } type GPIO21_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2623,13 +4415,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO21_CTRL_t GPIO21_CTRL at 0x400140ac; + register uint32 GPIO21_CTRL_raw at 0x400140ac; type GPIO22_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2646,10 +4439,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO22_STATUS_t GPIO22_STATUS at 0x400140b0; + register uint32 GPIO22_STATUS_raw at 0x400140b0; + + enum GPIO22_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO22_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO22_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO22_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO22_CTRL_FUNCSEL { + spi0_sclk = 1, // + uart1_cts = 2, // + i2c1_sda = 3, // + pwm_a_3 = 4, // + sio_22 = 5, // + pio0_22 = 6, // + pio1_22 = 7, // + clocks_gpin_1 = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } type GPIO22_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2659,13 +4495,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO22_CTRL_t GPIO22_CTRL at 0x400140b4; + register uint32 GPIO22_CTRL_raw at 0x400140b4; type GPIO23_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2682,10 +4519,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO23_STATUS_t GPIO23_STATUS at 0x400140b8; + register uint32 GPIO23_STATUS_raw at 0x400140b8; + + enum GPIO23_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO23_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO23_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO23_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO23_CTRL_FUNCSEL { + spi0_tx = 1, // + uart1_rts = 2, // + i2c1_scl = 3, // + pwm_b_3 = 4, // + sio_23 = 5, // + pio0_23 = 6, // + pio1_23 = 7, // + clocks_gpout_1 = 8, // + usb_muxing_vbus_en = 9, // + null = 31 // + } type GPIO23_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2695,13 +4575,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO23_CTRL_t GPIO23_CTRL at 0x400140bc; + register uint32 GPIO23_CTRL_raw at 0x400140bc; type GPIO24_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2718,10 +4599,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO24_STATUS_t GPIO24_STATUS at 0x400140c0; + register uint32 GPIO24_STATUS_raw at 0x400140c0; + + enum GPIO24_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO24_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO24_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO24_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO24_CTRL_FUNCSEL { + spi1_rx = 1, // + uart1_tx = 2, // + i2c0_sda = 3, // + pwm_a_4 = 4, // + sio_24 = 5, // + pio0_24 = 6, // + pio1_24 = 7, // + clocks_gpout_2 = 8, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } type GPIO24_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2731,13 +4655,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO24_CTRL_t GPIO24_CTRL at 0x400140c4; + register uint32 GPIO24_CTRL_raw at 0x400140c4; type GPIO25_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2754,10 +4679,53 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO25_STATUS_t GPIO25_STATUS at 0x400140c8; + register uint32 GPIO25_STATUS_raw at 0x400140c8; + + enum GPIO25_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO25_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO25_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO25_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO25_CTRL_FUNCSEL { + spi1_ss_n = 1, // + uart1_rx = 2, // + i2c0_scl = 3, // + pwm_b_4 = 4, // + sio_25 = 5, // + pio0_25 = 6, // + pio1_25 = 7, // + clocks_gpout_3 = 8, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } type GPIO25_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2767,13 +4735,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO25_CTRL_t GPIO25_CTRL at 0x400140cc; + register uint32 GPIO25_CTRL_raw at 0x400140cc; type GPIO26_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2790,10 +4759,52 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO26_STATUS_t GPIO26_STATUS at 0x400140d0; + register uint32 GPIO26_STATUS_raw at 0x400140d0; + + enum GPIO26_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO26_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO26_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO26_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO26_CTRL_FUNCSEL { + spi1_sclk = 1, // + uart1_cts = 2, // + i2c1_sda = 3, // + pwm_a_5 = 4, // + sio_26 = 5, // + pio0_26 = 6, // + pio1_26 = 7, // + usb_muxing_vbus_en = 9, // + null = 31 // + } type GPIO26_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2803,13 +4814,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO26_CTRL_t GPIO26_CTRL at 0x400140d4; + register uint32 GPIO26_CTRL_raw at 0x400140d4; type GPIO27_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2826,10 +4838,52 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO27_STATUS_t GPIO27_STATUS at 0x400140d8; + register uint32 GPIO27_STATUS_raw at 0x400140d8; + + enum GPIO27_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO27_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO27_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO27_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO27_CTRL_FUNCSEL { + spi1_tx = 1, // + uart1_rts = 2, // + i2c1_scl = 3, // + pwm_b_5 = 4, // + sio_27 = 5, // + pio0_27 = 6, // + pio1_27 = 7, // + usb_muxing_overcurr_detect = 9, // + null = 31 // + } type GPIO27_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2839,13 +4893,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO27_CTRL_t GPIO27_CTRL at 0x400140dc; + register uint32 GPIO27_CTRL_raw at 0x400140dc; type GPIO28_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2862,10 +4917,52 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO28_STATUS_t GPIO28_STATUS at 0x400140e0; + register uint32 GPIO28_STATUS_raw at 0x400140e0; + + enum GPIO28_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO28_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO28_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO28_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO28_CTRL_FUNCSEL { + spi1_rx = 1, // + uart0_tx = 2, // + i2c0_sda = 3, // + pwm_a_6 = 4, // + sio_28 = 5, // + pio0_28 = 6, // + pio1_28 = 7, // + usb_muxing_vbus_detect = 9, // + null = 31 // + } type GPIO28_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2875,13 +4972,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO28_CTRL_t GPIO28_CTRL at 0x400140e4; + register uint32 GPIO28_CTRL_raw at 0x400140e4; type GPIO29_STATUS_t { _res1 = uint8(0); // Reserved, 8 bits @@ -2898,10 +4996,52 @@ IRQFROMPAD = false; // interrupt from pad before override is applied _res6 = false; // Reserved, 1 bits IRQTOPROC = false; // interrupt to processors, after override is applied + _res7 = uint5(0); // Reserved, 5 bits } // GPIO status register GPIO29_STATUS_t GPIO29_STATUS at 0x400140e8; + register uint32 GPIO29_STATUS_raw at 0x400140e8; + + enum GPIO29_CTRL_IRQOVER { + NORMAL = 0, // don't invert the interrupt + INVERT = 1, // invert the interrupt + LOW = 2, // drive interrupt low + HIGH = 3 // drive interrupt high + } + + enum GPIO29_CTRL_INOVER { + NORMAL = 0, // don't invert the peri input + INVERT = 1, // invert the peri input + LOW = 2, // drive peri input low + HIGH = 3 // drive peri input high + } + + enum GPIO29_CTRL_OEOVER { + NORMAL = 0, // drive output enable from peripheral signal selected by funcsel + INVERT = 1, // drive output enable from inverse of peripheral signal selected by funcsel + DISABLE = 2, // disable output + ENABLE = 3 // enable output + } + + enum GPIO29_CTRL_OUTOVER { + NORMAL = 0, // drive output from peripheral signal selected by funcsel + INVERT = 1, // drive output from inverse of peripheral signal selected by funcsel + LOW = 2, // drive output low + HIGH = 3 // drive output high + } + + enum GPIO29_CTRL_FUNCSEL { + spi1_ss_n = 1, // + uart0_rx = 2, // + i2c0_scl = 3, // + pwm_b_6 = 4, // + sio_29 = 5, // + pio0_29 = 6, // + pio1_29 = 7, // + usb_muxing_vbus_en = 9, // + null = 31 // + } type GPIO29_CTRL_t { FUNCSEL = uint5(0); // 0-31 -> selects pin function according to the gpio table 31 == NULL @@ -2911,13 +5051,14 @@ OEOVER = uint2(0); // _res3 = uint2(0); // Reserved, 2 bits INOVER = uint2(0); // - _res4 = uint8(0); // Reserved, 10 bits - _res5 = uint2(0); // + _res4 = uint10(0); // Reserved, 10 bits IRQOVER = uint2(0); // + _res5 = uint2(0); // Reserved, 2 bits } // GPIO control including function select and overrides. register GPIO29_CTRL_t GPIO29_CTRL at 0x400140ec; + register uint32 GPIO29_CTRL_raw at 0x400140ec; type INTR0_t { GPIO0_LEVEL_LOW = false; // @@ -2956,6 +5097,7 @@ // Raw Interrupts register INTR0_t INTR0 at 0x400140f0; + register uint32 INTR0_raw at 0x400140f0; type IO_BANK0_INTR1_t { GPIO8_LEVEL_LOW = false; // @@ -2994,6 +5136,7 @@ // Raw Interrupts register IO_BANK0_INTR1_t IO_BANK0_INTR1 at 0x400140f4; + register uint32 IO_BANK0_INTR1_raw at 0x400140f4; type INTR2_t { GPIO16_LEVEL_LOW = false; // @@ -3032,6 +5175,7 @@ // Raw Interrupts register INTR2_t INTR2 at 0x400140f8; + register uint32 INTR2_raw at 0x400140f8; type INTR3_t { GPIO24_LEVEL_LOW = false; // @@ -3058,10 +5202,12 @@ GPIO29_LEVEL_HIGH = false; // GPIO29_EDGE_LOW = false; // GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Raw Interrupts register INTR3_t INTR3 at 0x400140fc; + register uint32 INTR3_raw at 0x400140fc; type PROC0_INTE0_t { GPIO0_LEVEL_LOW = false; // @@ -3100,6 +5246,7 @@ // Interrupt Enable for proc0 register PROC0_INTE0_t PROC0_INTE0 at 0x40014100; + register uint32 PROC0_INTE0_raw at 0x40014100; type PROC0_INTE1_t { GPIO8_LEVEL_LOW = false; // @@ -3138,6 +5285,7 @@ // Interrupt Enable for proc0 register PROC0_INTE1_t PROC0_INTE1 at 0x40014104; + register uint32 PROC0_INTE1_raw at 0x40014104; type PROC0_INTE2_t { GPIO16_LEVEL_LOW = false; // @@ -3176,6 +5324,7 @@ // Interrupt Enable for proc0 register PROC0_INTE2_t PROC0_INTE2 at 0x40014108; + register uint32 PROC0_INTE2_raw at 0x40014108; type PROC0_INTE3_t { GPIO24_LEVEL_LOW = false; // @@ -3202,10 +5351,12 @@ GPIO29_LEVEL_HIGH = false; // GPIO29_EDGE_LOW = false; // GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Enable for proc0 register PROC0_INTE3_t PROC0_INTE3 at 0x4001410c; + register uint32 PROC0_INTE3_raw at 0x4001410c; type PROC0_INTF0_t { GPIO0_LEVEL_LOW = false; // @@ -3244,6 +5395,7 @@ // Interrupt Force for proc0 register PROC0_INTF0_t PROC0_INTF0 at 0x40014110; + register uint32 PROC0_INTF0_raw at 0x40014110; type PROC0_INTF1_t { GPIO8_LEVEL_LOW = false; // @@ -3282,6 +5434,7 @@ // Interrupt Force for proc0 register PROC0_INTF1_t PROC0_INTF1 at 0x40014114; + register uint32 PROC0_INTF1_raw at 0x40014114; type PROC0_INTF2_t { GPIO16_LEVEL_LOW = false; // @@ -3320,6 +5473,7 @@ // Interrupt Force for proc0 register PROC0_INTF2_t PROC0_INTF2 at 0x40014118; + register uint32 PROC0_INTF2_raw at 0x40014118; type PROC0_INTF3_t { GPIO24_LEVEL_LOW = false; // @@ -3346,10 +5500,12 @@ GPIO29_LEVEL_HIGH = false; // GPIO29_EDGE_LOW = false; // GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Force for proc0 register PROC0_INTF3_t PROC0_INTF3 at 0x4001411c; + register uint32 PROC0_INTF3_raw at 0x4001411c; type PROC0_INTS0_t { GPIO0_LEVEL_LOW = false; // @@ -3388,6 +5544,7 @@ // Interrupt status after masking & forcing for proc0 register PROC0_INTS0_t PROC0_INTS0 at 0x40014120; + register uint32 PROC0_INTS0_raw at 0x40014120; type PROC0_INTS1_t { GPIO8_LEVEL_LOW = false; // @@ -3426,6 +5583,7 @@ // Interrupt status after masking & forcing for proc0 register PROC0_INTS1_t PROC0_INTS1 at 0x40014124; + register uint32 PROC0_INTS1_raw at 0x40014124; type PROC0_INTS2_t { GPIO16_LEVEL_LOW = false; // @@ -3464,6 +5622,7 @@ // Interrupt status after masking & forcing for proc0 register PROC0_INTS2_t PROC0_INTS2 at 0x40014128; + register uint32 PROC0_INTS2_raw at 0x40014128; type PROC0_INTS3_t { GPIO24_LEVEL_LOW = false; // @@ -3490,10 +5649,12 @@ GPIO29_LEVEL_HIGH = false; // GPIO29_EDGE_LOW = false; // GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt status after masking & forcing for proc0 register PROC0_INTS3_t PROC0_INTS3 at 0x4001412c; + register uint32 PROC0_INTS3_raw at 0x4001412c; type PROC1_INTE0_t { GPIO0_LEVEL_LOW = false; // @@ -3532,6 +5693,7 @@ // Interrupt Enable for proc1 register PROC1_INTE0_t PROC1_INTE0 at 0x40014130; + register uint32 PROC1_INTE0_raw at 0x40014130; type PROC1_INTE1_t { GPIO8_LEVEL_LOW = false; // @@ -3570,6 +5732,7 @@ // Interrupt Enable for proc1 register PROC1_INTE1_t PROC1_INTE1 at 0x40014134; + register uint32 PROC1_INTE1_raw at 0x40014134; type PROC1_INTE2_t { GPIO16_LEVEL_LOW = false; // @@ -3608,6 +5771,7 @@ // Interrupt Enable for proc1 register PROC1_INTE2_t PROC1_INTE2 at 0x40014138; + register uint32 PROC1_INTE2_raw at 0x40014138; type PROC1_INTE3_t { GPIO24_LEVEL_LOW = false; // @@ -3634,10 +5798,12 @@ GPIO29_LEVEL_HIGH = false; // GPIO29_EDGE_LOW = false; // GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Enable for proc1 register PROC1_INTE3_t PROC1_INTE3 at 0x4001413c; + register uint32 PROC1_INTE3_raw at 0x4001413c; type PROC1_INTF0_t { GPIO0_LEVEL_LOW = false; // @@ -3676,6 +5842,7 @@ // Interrupt Force for proc1 register PROC1_INTF0_t PROC1_INTF0 at 0x40014140; + register uint32 PROC1_INTF0_raw at 0x40014140; type PROC1_INTF1_t { GPIO8_LEVEL_LOW = false; // @@ -3714,6 +5881,7 @@ // Interrupt Force for proc1 register PROC1_INTF1_t PROC1_INTF1 at 0x40014144; + register uint32 PROC1_INTF1_raw at 0x40014144; type PROC1_INTF2_t { GPIO16_LEVEL_LOW = false; // @@ -3752,6 +5920,7 @@ // Interrupt Force for proc1 register PROC1_INTF2_t PROC1_INTF2 at 0x40014148; + register uint32 PROC1_INTF2_raw at 0x40014148; type PROC1_INTF3_t { GPIO24_LEVEL_LOW = false; // @@ -3778,10 +5947,12 @@ GPIO29_LEVEL_HIGH = false; // GPIO29_EDGE_LOW = false; // GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Force for proc1 register PROC1_INTF3_t PROC1_INTF3 at 0x4001414c; + register uint32 PROC1_INTF3_raw at 0x4001414c; type PROC1_INTS0_t { GPIO0_LEVEL_LOW = false; // @@ -3820,6 +5991,7 @@ // Interrupt status after masking & forcing for proc1 register PROC1_INTS0_t PROC1_INTS0 at 0x40014150; + register uint32 PROC1_INTS0_raw at 0x40014150; type PROC1_INTS1_t { GPIO8_LEVEL_LOW = false; // @@ -3858,6 +6030,7 @@ // Interrupt status after masking & forcing for proc1 register PROC1_INTS1_t PROC1_INTS1 at 0x40014154; + register uint32 PROC1_INTS1_raw at 0x40014154; type PROC1_INTS2_t { GPIO16_LEVEL_LOW = false; // @@ -3896,6 +6069,7 @@ // Interrupt status after masking & forcing for proc1 register PROC1_INTS2_t PROC1_INTS2 at 0x40014158; + register uint32 PROC1_INTS2_raw at 0x40014158; type PROC1_INTS3_t { GPIO24_LEVEL_LOW = false; // @@ -3922,10 +6096,12 @@ GPIO29_LEVEL_HIGH = false; // GPIO29_EDGE_LOW = false; // GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt status after masking & forcing for proc1 register PROC1_INTS3_t PROC1_INTS3 at 0x4001415c; + register uint32 PROC1_INTS3_raw at 0x4001415c; type DORMANT_WAKE_INTE0_t { GPIO0_LEVEL_LOW = false; // @@ -3964,6 +6140,7 @@ // Interrupt Enable for dormant_wake register DORMANT_WAKE_INTE0_t DORMANT_WAKE_INTE0 at 0x40014160; + register uint32 DORMANT_WAKE_INTE0_raw at 0x40014160; type DORMANT_WAKE_INTE1_t { GPIO8_LEVEL_LOW = false; // @@ -4002,6 +6179,7 @@ // Interrupt Enable for dormant_wake register DORMANT_WAKE_INTE1_t DORMANT_WAKE_INTE1 at 0x40014164; + register uint32 DORMANT_WAKE_INTE1_raw at 0x40014164; type DORMANT_WAKE_INTE2_t { GPIO16_LEVEL_LOW = false; // @@ -4040,6 +6218,7 @@ // Interrupt Enable for dormant_wake register DORMANT_WAKE_INTE2_t DORMANT_WAKE_INTE2 at 0x40014168; + register uint32 DORMANT_WAKE_INTE2_raw at 0x40014168; type DORMANT_WAKE_INTE3_t { GPIO24_LEVEL_LOW = false; // @@ -4066,10 +6245,12 @@ GPIO29_LEVEL_HIGH = false; // GPIO29_EDGE_LOW = false; // GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Enable for dormant_wake register DORMANT_WAKE_INTE3_t DORMANT_WAKE_INTE3 at 0x4001416c; + register uint32 DORMANT_WAKE_INTE3_raw at 0x4001416c; type DORMANT_WAKE_INTF0_t { GPIO0_LEVEL_LOW = false; // @@ -4108,6 +6289,7 @@ // Interrupt Force for dormant_wake register DORMANT_WAKE_INTF0_t DORMANT_WAKE_INTF0 at 0x40014170; + register uint32 DORMANT_WAKE_INTF0_raw at 0x40014170; type DORMANT_WAKE_INTF1_t { GPIO8_LEVEL_LOW = false; // @@ -4146,6 +6328,7 @@ // Interrupt Force for dormant_wake register DORMANT_WAKE_INTF1_t DORMANT_WAKE_INTF1 at 0x40014174; + register uint32 DORMANT_WAKE_INTF1_raw at 0x40014174; type DORMANT_WAKE_INTF2_t { GPIO16_LEVEL_LOW = false; // @@ -4184,6 +6367,7 @@ // Interrupt Force for dormant_wake register DORMANT_WAKE_INTF2_t DORMANT_WAKE_INTF2 at 0x40014178; + register uint32 DORMANT_WAKE_INTF2_raw at 0x40014178; type DORMANT_WAKE_INTF3_t { GPIO24_LEVEL_LOW = false; // @@ -4210,10 +6394,12 @@ GPIO29_LEVEL_HIGH = false; // GPIO29_EDGE_LOW = false; // GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt Force for dormant_wake register DORMANT_WAKE_INTF3_t DORMANT_WAKE_INTF3 at 0x4001417c; + register uint32 DORMANT_WAKE_INTF3_raw at 0x4001417c; type DORMANT_WAKE_INTS0_t { GPIO0_LEVEL_LOW = false; // @@ -4252,6 +6438,7 @@ // Interrupt status after masking & forcing for dormant_wake register DORMANT_WAKE_INTS0_t DORMANT_WAKE_INTS0 at 0x40014180; + register uint32 DORMANT_WAKE_INTS0_raw at 0x40014180; type DORMANT_WAKE_INTS1_t { GPIO8_LEVEL_LOW = false; // @@ -4290,6 +6477,7 @@ // Interrupt status after masking & forcing for dormant_wake register DORMANT_WAKE_INTS1_t DORMANT_WAKE_INTS1 at 0x40014184; + register uint32 DORMANT_WAKE_INTS1_raw at 0x40014184; type DORMANT_WAKE_INTS2_t { GPIO16_LEVEL_LOW = false; // @@ -4328,6 +6516,7 @@ // Interrupt status after masking & forcing for dormant_wake register DORMANT_WAKE_INTS2_t DORMANT_WAKE_INTS2 at 0x40014188; + register uint32 DORMANT_WAKE_INTS2_raw at 0x40014188; type DORMANT_WAKE_INTS3_t { GPIO24_LEVEL_LOW = false; // @@ -4354,10 +6543,12 @@ GPIO29_LEVEL_HIGH = false; // GPIO29_EDGE_LOW = false; // GPIO29_EDGE_HIGH = false; // + _res1 = uint8(0); // Reserved, 8 bits } // Interrupt status after masking & forcing for dormant_wake register DORMANT_WAKE_INTS3_t DORMANT_WAKE_INTS3 at 0x4001418c; + register uint32 DORMANT_WAKE_INTS3_raw at 0x4001418c; /* Types and registers for SYSINFO */ @@ -4370,14 +6561,17 @@ // JEDEC JEP-106 compliant chip identifier. register CHIP_ID_t CHIP_ID at 0x40000000; + register uint32 CHIP_ID_raw at 0x40000000; type SYSINFO_PLATFORM_t { - FPGA = false; // - ASIC = false; // + FPGA = false; // + ASIC = false; // + _res1 = uint30(0); // Reserved, 30 bits } // Platform register. Allows software to know what environment it is running in. register SYSINFO_PLATFORM_t SYSINFO_PLATFORM at 0x40000004; + register uint32 SYSINFO_PLATFORM_raw at 0x40000004; type GITREF_RP2040_t { GITREF_RP2040 = uint32(0); // @@ -4385,6 +6579,7 @@ // Git hash of the chip source. Used to identify chip version. register GITREF_RP2040_t GITREF_RP2040 at 0x40000010; + register uint32 GITREF_RP2040_raw at 0x40000010; /* Types and registers for PPB */ @@ -4393,27 +6588,32 @@ ENABLE = false; // Enable SysTick counter: 0 = Counter disabled. 1 = Counter enabled. TICKINT = false; // Enables SysTick exception request: 0 = Counting down to zero does not assert the SysTick exception request. 1 = Counting down to zero to asserts the SysTick exception request. CLKSOURCE = false; // SysTick clock source. Always reads as one if SYST_CALIB reports NOREF. Selects the SysTick timer clock source: 0 = External reference clock. 1 = Processor clock. - _res1 = uint8(0); // Reserved, 13 bits - _res2 = uint5(0); // + _res1 = uint13(0); // Reserved, 13 bits COUNTFLAG = false; // Returns 1 if timer counted to 0 since last time this was read. Clears on read by application or debugger. + _res2 = uint15(0); // Reserved, 15 bits } // Use the SysTick Control and Status Register to enable the SysTick features. register SYST_CSR_t SYST_CSR at 0xe000e010; + register uint32 SYST_CSR_raw at 0xe000e010; type SYST_RVR_t { RELOAD = uint24(0); // Value to load into the SysTick Current Value Register when the counter reaches 0. + _res1 = uint8(0); // Reserved, 8 bits } // Use the SysTick Reload Value Register to specify the start value to load into the current value register when the counter reaches 0. It can be any value between 0 and 0x00FFFFFF. A start value of 0 is possible, but has no effect because the SysTick interrupt and COUNTFLAG are activated when counting from 1 to 0. The reset value of this register is UNKNOWN. To generate a multi-shot timer with a period of N processor clock cycles, use a RELOAD value of N-1. For example, if the SysTick interrupt is required every 100 clock pulses, set RELOAD to 99. register SYST_RVR_t SYST_RVR at 0xe000e014; + register uint32 SYST_RVR_raw at 0xe000e014; type SYST_CVR_t { CURRENT = uint24(0); // Reads return the current value of the SysTick counter. This register is write-clear. Writing to it with any value clears the register to 0. Clearing this register also clears the COUNTFLAG bit of the SysTick Control and Status Register. + _res1 = uint8(0); // Reserved, 8 bits } // Use the SysTick Current Value Register to find the current value in the register. The reset value of this register is UNKNOWN. register SYST_CVR_t SYST_CVR at 0xe000e018; + register uint32 SYST_CVR_raw at 0xe000e018; type SYST_CALIB_t { TENMS = uint24(0); // An optional Reload value to be used for 10ms (100Hz) timing, subject to system clock skew errors. If the value reads as 0, the calibration value is not known. @@ -4424,6 +6624,7 @@ // Use the SysTick Calibration Value Register to enable software to scale to any required speed using divide and multiply. register SYST_CALIB_t SYST_CALIB at 0xe000e01c; + register uint32 SYST_CALIB_raw at 0xe000e01c; type NVIC_ISER_t { SETENA = uint32(0); // Interrupt set-enable bits. Write: 0 = No effect. 1 = Enable interrupt. Read: 0 = Interrupt disabled. 1 = Interrupt enabled. @@ -4431,6 +6632,7 @@ // Use the Interrupt Set-Enable Register to enable interrupts and determine which interrupts are currently enabled. If a pending interrupt is enabled, the NVIC activates the interrupt based on its priority. If an interrupt is not enabled, asserting its interrupt signal changes the interrupt state to pending, but the NVIC never activates the interrupt, regardless of its priority. register NVIC_ISER_t NVIC_ISER at 0xe000e100; + register uint32 NVIC_ISER_raw at 0xe000e100; type NVIC_ICER_t { CLRENA = uint32(0); // Interrupt clear-enable bits. Write: 0 = No effect. 1 = Disable interrupt. Read: 0 = Interrupt disabled. 1 = Interrupt enabled. @@ -4438,6 +6640,7 @@ // Use the Interrupt Clear-Enable Registers to disable interrupts and determine which interrupts are currently enabled. register NVIC_ICER_t NVIC_ICER at 0xe000e180; + register uint32 NVIC_ICER_raw at 0xe000e180; type NVIC_ISPR_t { SETPEND = uint32(0); // Interrupt set-pending bits. Write: 0 = No effect. 1 = Changes interrupt state to pending. Read: 0 = Interrupt is not pending. 1 = Interrupt is pending. Note: Writing 1 to the NVIC_ISPR bit corresponding to: An interrupt that is pending has no effect. A disabled interrupt sets the state of that interrupt to pending. @@ -4445,6 +6648,7 @@ // The NVIC_ISPR forces interrupts into the pending state, and shows which interrupts are pending. register NVIC_ISPR_t NVIC_ISPR at 0xe000e200; + register uint32 NVIC_ISPR_raw at 0xe000e200; type NVIC_ICPR_t { CLRPEND = uint32(0); // Interrupt clear-pending bits. Write: 0 = No effect. 1 = Removes pending state and interrupt. Read: 0 = Interrupt is not pending. 1 = Interrupt is pending. @@ -4452,6 +6656,7 @@ // Use the Interrupt Clear-Pending Register to clear pending interrupts and determine which interrupts are currently pending. register NVIC_ICPR_t NVIC_ICPR at 0xe000e280; + register uint32 NVIC_ICPR_raw at 0xe000e280; type NVIC_IPR0_t { _res1 = uint6(0); // Reserved, 6 bits @@ -4466,6 +6671,7 @@ // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. Note: Writing 1 to an NVIC_ICPR bit does not affect the active state of the corresponding interrupt. These registers are only word-accessible register NVIC_IPR0_t NVIC_IPR0 at 0xe000e400; + register uint32 NVIC_IPR0_raw at 0xe000e400; type NVIC_IPR1_t { _res1 = uint6(0); // Reserved, 6 bits @@ -4480,6 +6686,7 @@ // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. register NVIC_IPR1_t NVIC_IPR1 at 0xe000e404; + register uint32 NVIC_IPR1_raw at 0xe000e404; type NVIC_IPR2_t { _res1 = uint6(0); // Reserved, 6 bits @@ -4494,6 +6701,7 @@ // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. register NVIC_IPR2_t NVIC_IPR2 at 0xe000e408; + register uint32 NVIC_IPR2_raw at 0xe000e408; type NVIC_IPR3_t { _res1 = uint6(0); // Reserved, 6 bits @@ -4508,6 +6716,7 @@ // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. register NVIC_IPR3_t NVIC_IPR3 at 0xe000e40c; + register uint32 NVIC_IPR3_raw at 0xe000e40c; type NVIC_IPR4_t { _res1 = uint6(0); // Reserved, 6 bits @@ -4522,6 +6731,7 @@ // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. register NVIC_IPR4_t NVIC_IPR4 at 0xe000e410; + register uint32 NVIC_IPR4_raw at 0xe000e410; type NVIC_IPR5_t { _res1 = uint6(0); // Reserved, 6 bits @@ -4536,6 +6746,7 @@ // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. register NVIC_IPR5_t NVIC_IPR5 at 0xe000e414; + register uint32 NVIC_IPR5_raw at 0xe000e414; type NVIC_IPR6_t { _res1 = uint6(0); // Reserved, 6 bits @@ -4550,6 +6761,7 @@ // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. register NVIC_IPR6_t NVIC_IPR6 at 0xe000e418; + register uint32 NVIC_IPR6_raw at 0xe000e418; type NVIC_IPR7_t { _res1 = uint6(0); // Reserved, 6 bits @@ -4564,6 +6776,7 @@ // Use the Interrupt Priority Registers to assign a priority from 0 to 3 to each of the available interrupts. 0 is the highest priority, and 3 is the lowest. register NVIC_IPR7_t NVIC_IPR7 at 0xe000e41c; + register uint32 NVIC_IPR7_raw at 0xe000e41c; type PPB_CPUID_t { REVISION = uint4(0); // Minor revision number m in the rnpm revision status: 0x1 = Patch 1. @@ -4575,6 +6788,7 @@ // Read the CPU ID Base Register to determine: the ID number of the processor core, the version number of the processor core, the implementation details of the processor core. register PPB_CPUID_t PPB_CPUID at 0xe000ed00; + register uint32 PPB_CPUID_raw at 0xe000ed00; type ICSR_t { VECTACTIVE = uint9(0); // Active exception number field. Reset clears the VECTACTIVE field. @@ -4594,6 +6808,7 @@ // Use the Interrupt Control State Register to set a pending Non-Maskable Interrupt (NMI), set or clear a pending PendSV, set or clear a pending SysTick, check for pending exceptions, check the vector number of the highest priority pended exception, check the vector number of the active exception. register ICSR_t ICSR at 0xe000ed04; + register uint32 ICSR_raw at 0xe000ed04; type VTOR_t { _res1 = uint8(0); // Reserved, 8 bits @@ -4602,19 +6817,20 @@ // The VTOR holds the vector table offset address. register VTOR_t VTOR at 0xe000ed08; + register uint32 VTOR_raw at 0xe000ed08; type AIRCR_t { _res1 = false; // Reserved, 1 bits VECTCLRACTIVE = false; // Clears all active state information for fixed and configurable exceptions. This bit: is self-clearing, can only be set by the DAP when the core is halted. When set: clears all active exception status of the processor, forces a return to Thread mode, forces an IPSR of 0. A debugger must re-initialize the stack. SYSRESETREQ = false; // Writing 1 to this bit causes the SYSRESETREQ signal to the outer system to be asserted to request a reset. The intention is to force a large system reset of all major components except for debug. The C_HALT bit in the DHCSR is cleared as a result of the system reset requested. The debugger does not lose contact with the device. - _res2 = uint8(0); // Reserved, 12 bits - _res3 = uint4(0); // + _res2 = uint12(0); // Reserved, 12 bits ENDIANESS = false; // Data endianness implemented: 0 = Little-endian. VECTKEY = uint16(0); // Register key: Reads as Unknown On writes, write 0x05FA to VECTKEY, otherwise the write is ignored. } // Use the Application Interrupt and Reset Control Register to: determine data endianness, clear all active state information from debug halt mode, request a system reset. register AIRCR_t AIRCR at 0xe000ed0c; + register uint32 AIRCR_raw at 0xe000ed0c; type SCR_t { _res1 = false; // Reserved, 1 bits @@ -4622,76 +6838,86 @@ SLEEPDEEP = false; // Controls whether the processor uses sleep or deep sleep as its low power mode: 0 = Sleep. 1 = Deep sleep. _res2 = false; // Reserved, 1 bits SEVONPEND = false; // Send Event on Pending bit: 0 = Only enabled interrupts or events can wakeup the processor, disabled interrupts are excluded. 1 = Enabled events and all interrupts, including disabled interrupts, can wakeup the processor. When an event or interrupt becomes pending, the event signal wakes up the processor from WFE. If the processor is not waiting for an event, the event is registered and affects the next WFE. The processor also wakes up on execution of an SEV instruction or an external event. + _res3 = uint27(0); // Reserved, 27 bits } // System Control Register. Use the System Control Register for power-management functions: signal to the system when the processor can enter a low power state, control how the processor enters and exits low power states. register SCR_t SCR at 0xe000ed10; + register uint32 SCR_raw at 0xe000ed10; type CCR_t { _res1 = uint3(0); // Reserved, 3 bits UNALIGN_TRP = false; // Always reads as one, indicates that all unaligned accesses generate a HardFault. _res2 = uint5(0); // Reserved, 5 bits STKALIGN = false; // Always reads as one, indicates 8-byte stack alignment on exception entry. On exception entry, the processor uses bit[9] of the stacked PSR to indicate the stack alignment. On return from the exception it uses this stacked bit to restore the correct stack alignment. + _res3 = uint22(0); // Reserved, 22 bits } // The Configuration and Control Register permanently enables stack alignment and causes unaligned accesses to result in a Hard Fault. register CCR_t CCR at 0xe000ed14; + register uint32 CCR_raw at 0xe000ed14; type SHPR2_t { - _res1 = uint16(0); // Reserved, 30 bits - _res2 = uint8(0); // - _res3 = uint6(0); // + _res1 = uint30(0); // Reserved, 30 bits PRI_11 = uint2(0); // Priority of system handler 11, SVCall } // System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 2 to set the priority of SVCall. register SHPR2_t SHPR2 at 0xe000ed1c; + register uint32 SHPR2_raw at 0xe000ed1c; type SHPR3_t { - _res1 = uint16(0); // Reserved, 22 bits - _res2 = uint6(0); // + _res1 = uint22(0); // Reserved, 22 bits PRI_14 = uint2(0); // Priority of system handler 14, PendSV - _res3 = uint6(0); // Reserved, 6 bits + _res2 = uint6(0); // Reserved, 6 bits PRI_15 = uint2(0); // Priority of system handler 15, SysTick } // System handlers are a special class of exception handler that can have their priority set to any of the priority levels. Use the System Handler Priority Register 3 to set the priority of PendSV and SysTick. register SHPR3_t SHPR3 at 0xe000ed20; + register uint32 SHPR3_raw at 0xe000ed20; type SHCSR_t { - _res1 = uint8(0); // Reserved, 15 bits - _res2 = uint7(0); // + _res1 = uint15(0); // Reserved, 15 bits SVCALLPENDED = false; // Reads as 1 if SVCall is Pending. Write 1 to set pending SVCall, write 0 to clear pending SVCall. + _res2 = uint16(0); // Reserved, 16 bits } // Use the System Handler Control and State Register to determine or clear the pending status of SVCall. register SHCSR_t SHCSR at 0xe000ed24; + register uint32 SHCSR_raw at 0xe000ed24; type MPU_TYPE_t { SEPARATE = false; // Indicates support for separate instruction and data address maps. Reads as 0 as ARMv6-M only supports a unified MPU. _res1 = uint7(0); // Reserved, 7 bits DREGION = uint8(0); // Number of regions supported by the MPU. IREGION = uint8(0); // Instruction region. Reads as zero as ARMv6-M only supports a unified MPU. + _res2 = uint8(0); // Reserved, 8 bits } // Read the MPU Type Register to determine if the processor implements an MPU, and how many regions the MPU supports. register MPU_TYPE_t MPU_TYPE at 0xe000ed90; + register uint32 MPU_TYPE_raw at 0xe000ed90; type MPU_CTRL_t { ENABLE = false; // Enables the MPU. If the MPU is disabled, privileged and unprivileged accesses use the default memory map. 0 = MPU disabled. 1 = MPU enabled. HFNMIENA = false; // Controls the use of the MPU for HardFaults and NMIs. Setting this bit when ENABLE is clear results in UNPREDICTABLE behaviour. When the MPU is enabled: 0 = MPU is disabled during HardFault and NMI handlers, regardless of the value of the ENABLE bit. 1 = the MPU is enabled during HardFault and NMI handlers. PRIVDEFENA = false; // Controls whether the default memory map is enabled as a background region for privileged accesses. This bit is ignored when ENABLE is clear. 0 = If the MPU is enabled, disables use of the default memory map. Any memory access to a location not covered by any enabled region causes a fault. 1 = If the MPU is enabled, enables use of the default memory map as a background region for privileged software accesses. When enabled, the background region acts as if it is region number -1. Any region that is defined and enabled has priority over this default map. + _res1 = uint29(0); // Reserved, 29 bits } // Use the MPU Control Register to enable and disable the MPU, and to control whether the default memory map is enabled as a background region for privileged accesses, and whether the MPU is enabled for HardFaults and NMIs. register MPU_CTRL_t MPU_CTRL at 0xe000ed94; + register uint32 MPU_CTRL_raw at 0xe000ed94; type MPU_RNR_t { REGION = uint4(0); // Indicates the MPU region referenced by the MPU_RBAR and MPU_RASR registers. The MPU supports 8 memory regions, so the permitted values of this field are 0-7. + _res1 = uint28(0); // Reserved, 28 bits } // Use the MPU Region Number Register to select the region currently accessed by MPU_RBAR and MPU_RASR. register MPU_RNR_t MPU_RNR at 0xe000ed98; + register uint32 MPU_RNR_raw at 0xe000ed98; type MPU_RBAR_t { REGION = uint4(0); // On writes, specifies the number of the region whose base address to update provided VALID is set written as 1. On reads, returns bits [3:0] of MPU_RNR. @@ -4702,6 +6928,7 @@ // Read the MPU Region Base Address Register to determine the base address of the region identified by MPU_RNR. Write to update the base address of said region or that of a specified region, with whose number MPU_RNR will also be updated. register MPU_RBAR_t MPU_RBAR at 0xe000ed9c; + register uint32 MPU_RBAR_raw at 0xe000ed9c; type MPU_RASR_t { ENABLE = false; // Enables the region. @@ -4713,12 +6940,26 @@ // Use the MPU Region Attribute and Size Register to define the size, access behaviour and memory type of the region identified by MPU_RNR, and enable that region. register MPU_RASR_t MPU_RASR at 0xe000eda0; + register uint32 MPU_RASR_raw at 0xe000eda0; /* Types and registers for SSI DW_apb_ssi has the following features: * APB interface – Allows for easy integration into a DesignWare Synthesizable Components for AMBA 2 implementation. * APB3 and APB4 protocol support. * Scalable APB data bus width – Supports APB data bus widths of 8, 16, and 32 bits. * Serial-master or serial-slave operation – Enables serial communication with serial-master or serial-slave peripheral devices. * Programmable Dual/Quad/Octal SPI support in Master Mode. * Dual Data Rate (DDR) and Read Data Strobe (RDS) Support - Enables the DW_apb_ssi master to perform operations with the device in DDR and RDS modes when working in Dual/Quad/Octal mode of operation. * Data Mask Support - Enables the DW_apb_ssi to selectively update the bytes in the device. This feature is applicable only in enhanced SPI modes. * eXecute-In-Place (XIP) support - Enables the DW_apb_ssi master to behave as a memory mapped I/O and fetches the data from the device based on the APB read request. This feature is applicable only in enhanced SPI modes. * DMA Controller Interface – Enables the DW_apb_ssi to interface to a DMA controller over the bus using a handshaking interface for transfer requests. * Independent masking of interrupts – Master collision, transmit FIFO overflow, transmit FIFO empty, receive FIFO full, receive FIFO underflow, and receive FIFO overflow interrupts can all be masked independently. * Multi-master contention detection – Informs the processor of multiple serial-master accesses on the serial bus. * Bypass of meta-stability flip-flops for synchronous clocks – When the APB clock (pclk) and the DW_apb_ssi serial clock (ssi_clk) are synchronous, meta-stable flip-flops are not used when transferring control signals across these clock domains. * Programmable delay on the sample time of the received serial data bit (rxd); enables programmable control of routing delays resulting in higher serial data-bit rates. * Programmable features: - Serial interface operation – Choice of Motorola SPI, Texas Instruments Synchronous Serial Protocol or National Semiconductor Microwire. - Clock bit-rate – Dynamic control of the serial bit rate of the data transfer; used in only serial-master mode of operation. - Data Item size (4 to 32 bits) – Item size of each data transfer under the control of the programmer. * Configured features: - FIFO depth – 16 words deep. The FIFO width is fixed at 32 bits. - 1 slave select output. - Hardware slave-select – Dedicated hardware slave-select line. - Combined interrupt line - one combined interrupt line from the DW_apb_ssi to the interrupt controller. - Interrupt polarity – active high interrupt lines. - Serial clock polarity – low serial-clock polarity directly after reset. - Serial clock phase – capture on first edge of serial-clock directly after reset. */ + enum CTRLR0_SPI_FRF { + STD = 0, // Standard 1-bit SPI frame format; 1 bit per SCK, full-duplex + DUAL = 1, // Dual-SPI frame format; two bits per SCK, half-duplex + QUAD = 2 // Quad-SPI frame format; four bits per SCK, half-duplex + } + + enum CTRLR0_TMOD { + TX_AND_RX = 0, // Both transmit and receive + TX_ONLY = 1, // Transmit only (not for FRF == 0, standard SPI mode) + RX_ONLY = 2, // Receive only (not for FRF == 0, standard SPI mode) + EEPROM_READ = 3 // EEPROM read mode (TX then RX; RX starts after control data TX'd) + } + type CTRLR0_t { DFS = uint4(0); // Data frame size FRF = uint2(0); // Frame format @@ -4732,88 +6973,110 @@ SPI_FRF = uint2(0); // SPI frame format _res1 = false; // Reserved, 1 bits SSTE = false; // Slave select toggle enable + _res2 = uint7(0); // Reserved, 7 bits } // Control register 0 register CTRLR0_t CTRLR0 at 0x18000000; + register uint32 CTRLR0_raw at 0x18000000; type CTRLR1_t { - NDF = uint16(0); // Number of data frames + NDF = uint16(0); // Number of data frames + _res1 = uint16(0); // Reserved, 16 bits } // Master Control register 1 register CTRLR1_t CTRLR1 at 0x18000004; + register uint32 CTRLR1_raw at 0x18000004; type SSIENR_t { SSI_EN = false; // SSI enable + _res1 = uint31(0); // Reserved, 31 bits } // SSI Enable register SSIENR_t SSIENR at 0x18000008; + register uint32 SSIENR_raw at 0x18000008; type MWCR_t { MWMOD = false; // Microwire transfer mode MDD = false; // Microwire control MHS = false; // Microwire handshaking + _res1 = uint29(0); // Reserved, 29 bits } // Microwire Control register MWCR_t MWCR at 0x1800000c; + register uint32 MWCR_raw at 0x1800000c; type SER_t { - SER = false; // For each bit: 0 -> slave not selected 1 -> slave selected + SER = false; // For each bit: 0 -> slave not selected 1 -> slave selected + _res1 = uint31(0); // Reserved, 31 bits } // Slave enable register SER_t SER at 0x18000010; + register uint32 SER_raw at 0x18000010; type BAUDR_t { SCKDV = uint16(0); // SSI clock divider + _res1 = uint16(0); // Reserved, 16 bits } // Baud rate register BAUDR_t BAUDR at 0x18000014; + register uint32 BAUDR_raw at 0x18000014; type TXFTLR_t { - TFT = uint8(0); // Transmit FIFO threshold + TFT = uint8(0); // Transmit FIFO threshold + _res1 = uint24(0); // Reserved, 24 bits } // TX FIFO threshold level register TXFTLR_t TXFTLR at 0x18000018; + register uint32 TXFTLR_raw at 0x18000018; type RXFTLR_t { - RFT = uint8(0); // Receive FIFO threshold + RFT = uint8(0); // Receive FIFO threshold + _res1 = uint24(0); // Reserved, 24 bits } // RX FIFO threshold level register RXFTLR_t RXFTLR at 0x1800001c; + register uint32 RXFTLR_raw at 0x1800001c; type TXFLR_t { TFTFL = uint8(0); // Transmit FIFO level + _res1 = uint24(0); // Reserved, 24 bits } // TX FIFO level register TXFLR_t TXFLR at 0x18000020; + register uint32 TXFLR_raw at 0x18000020; type RXFLR_t { RXTFL = uint8(0); // Receive FIFO level + _res1 = uint24(0); // Reserved, 24 bits } // RX FIFO level register RXFLR_t RXFLR at 0x18000024; + register uint32 RXFLR_raw at 0x18000024; type SR_t { - BUSY = false; // SSI busy flag - TFNF = false; // Transmit FIFO not full - TFE = false; // Transmit FIFO empty - RFNE = false; // Receive FIFO not empty - RFF = false; // Receive FIFO full - TXE = false; // Transmission error - DCOL = false; // Data collision error + BUSY = false; // SSI busy flag + TFNF = false; // Transmit FIFO not full + TFE = false; // Transmit FIFO empty + RFNE = false; // Receive FIFO not empty + RFF = false; // Receive FIFO full + TXE = false; // Transmission error + DCOL = false; // Data collision error + _res1 = uint25(0); // Reserved, 25 bits } // Status register register SR_t SR at 0x18000028; + register uint32 SR_raw at 0x18000028; type IMR_t { TXEIM = false; // Transmit FIFO empty interrupt mask @@ -4822,10 +7085,12 @@ RXOIM = false; // Receive FIFO overflow interrupt mask RXFIM = false; // Receive FIFO full interrupt mask MSTIM = false; // Multi-master contention interrupt mask + _res1 = uint26(0); // Reserved, 26 bits } // Interrupt mask register IMR_t IMR at 0x1800002c; + register uint32 IMR_raw at 0x1800002c; type ISR_t { TXEIS = false; // Transmit FIFO empty interrupt status @@ -4834,10 +7099,12 @@ RXOIS = false; // Receive FIFO overflow interrupt status RXFIS = false; // Receive FIFO full interrupt status MSTIS = false; // Multi-master contention interrupt status + _res1 = uint26(0); // Reserved, 26 bits } // Interrupt status register ISR_t ISR at 0x18000030; + register uint32 ISR_raw at 0x18000030; type RISR_t { TXEIR = false; // Transmit FIFO empty raw interrupt status @@ -4846,67 +7113,85 @@ RXOIR = false; // Receive FIFO overflow raw interrupt status RXFIR = false; // Receive FIFO full raw interrupt status MSTIR = false; // Multi-master contention raw interrupt status + _res1 = uint26(0); // Reserved, 26 bits } // Raw interrupt status register RISR_t RISR at 0x18000034; + register uint32 RISR_raw at 0x18000034; type TXOICR_t { TXOICR = false; // Clear-on-read transmit FIFO overflow interrupt + _res1 = uint31(0); // Reserved, 31 bits } // TX FIFO overflow interrupt clear register TXOICR_t TXOICR at 0x18000038; + register uint32 TXOICR_raw at 0x18000038; type RXOICR_t { RXOICR = false; // Clear-on-read receive FIFO overflow interrupt + _res1 = uint31(0); // Reserved, 31 bits } // RX FIFO overflow interrupt clear register RXOICR_t RXOICR at 0x1800003c; + register uint32 RXOICR_raw at 0x1800003c; type RXUICR_t { RXUICR = false; // Clear-on-read receive FIFO underflow interrupt + _res1 = uint31(0); // Reserved, 31 bits } // RX FIFO underflow interrupt clear register RXUICR_t RXUICR at 0x18000040; + register uint32 RXUICR_raw at 0x18000040; type MSTICR_t { MSTICR = false; // Clear-on-read multi-master contention interrupt + _res1 = uint31(0); // Reserved, 31 bits } // Multi-master interrupt clear register MSTICR_t MSTICR at 0x18000044; + register uint32 MSTICR_raw at 0x18000044; type ICR_t { - ICR = false; // Clear-on-read all active interrupts + ICR = false; // Clear-on-read all active interrupts + _res1 = uint31(0); // Reserved, 31 bits } // Interrupt clear register ICR_t ICR at 0x18000048; + register uint32 ICR_raw at 0x18000048; type DMACR_t { RDMAE = false; // Receive DMA enable TDMAE = false; // Transmit DMA enable + _res1 = uint30(0); // Reserved, 30 bits } // DMA control register DMACR_t DMACR at 0x1800004c; + register uint32 DMACR_raw at 0x1800004c; type DMATDLR_t { DMATDL = uint8(0); // Transmit data watermark level + _res1 = uint24(0); // Reserved, 24 bits } // DMA TX data level register DMATDLR_t DMATDLR at 0x18000050; + register uint32 DMATDLR_raw at 0x18000050; type DMARDLR_t { DMARDL = uint8(0); // Receive data watermark level (DMARDLR+1) + _res1 = uint24(0); // Reserved, 24 bits } // DMA RX data level register DMARDLR_t DMARDLR at 0x18000054; + register uint32 DMARDLR_raw at 0x18000054; type IDR_t { IDCODE = uint32(0); // Peripheral dentification code @@ -4914,6 +7199,7 @@ // Identification register register IDR_t IDR at 0x18000058; + register uint32 IDR_raw at 0x18000058; type SSI_VERSION_ID_t { SSI_COMP_VERSION = uint32(0); // SNPS component version (format X.YY) @@ -4921,6 +7207,7 @@ // Version ID register SSI_VERSION_ID_t SSI_VERSION_ID at 0x1800005c; + register uint32 SSI_VERSION_ID_raw at 0x1800005c; type DR0_t { DR = uint32(0); // First data register of 36 @@ -4928,13 +7215,29 @@ // Data Register 0 (of 36) register DR0_t DR0 at 0x18000060; + register uint32 DR0_raw at 0x18000060; type RX_SAMPLE_DLY_t { - RSD = uint8(0); // RXD sample delay (in SCLK cycles) + RSD = uint8(0); // RXD sample delay (in SCLK cycles) + _res1 = uint24(0); // Reserved, 24 bits } // RX sample delay register RX_SAMPLE_DLY_t RX_SAMPLE_DLY at 0x180000f0; + register uint32 RX_SAMPLE_DLY_raw at 0x180000f0; + + enum SPI_CTRLR0_INST_L { + NONE = 0, // No instruction + _4B = 1, // 4-bit instruction + _8B = 2, // 8-bit instruction + _16B = 3 // 16-bit instruction + } + + enum SPI_CTRLR0_TRANS_TYPE { + _1C1A = 0, // Command and address both in standard SPI frame format + _1C2A = 1, // Command in standard SPI format, address in format specified by FRF + _2C2A = 2 // Command and address both in format specified by FRF (e.g. Dual-SPI) + } type SPI_CTRLR0_t { TRANS_TYPE = uint2(0); // Address and instruction transfer format @@ -4952,13 +7255,16 @@ // SPI control register SPI_CTRLR0_t SPI_CTRLR0 at 0x180000f4; + register uint32 SPI_CTRLR0_raw at 0x180000f4; type TXD_DRIVE_EDGE_t { - TDE = uint8(0); // TXD drive edge + TDE = uint8(0); // TXD drive edge + _res1 = uint24(0); // Reserved, 24 bits } // TX drive edge register TXD_DRIVE_EDGE_t TXD_DRIVE_EDGE at 0x180000f8; + register uint32 TXD_DRIVE_EDGE_raw at 0x180000f8; /* Types and registers for XIP_CTRL @@ -4970,26 +7276,32 @@ ERR_BADWRITE = false; // When 1, writes to any alias other than 0x0 (caching, allocating) will produce a bus fault. When 0, these writes are silently ignored. In either case, writes to the 0x0 alias will deallocate on tag match, as usual. _res1 = false; // Reserved, 1 bits POWER_DOWN = false; // When 1, the cache memories are powered down. They retain state, but can not be accessed. This reduces static power dissipation. Writing 1 to this bit forces CTRL_EN to 0, i.e. the cache cannot be enabled when powered down. Cache-as-SRAM accesses will produce a bus error response when the cache is powered down. + _res2 = uint28(0); // Reserved, 28 bits } // Cache control register XIP_CTRL_CTRL_t XIP_CTRL_CTRL at 0x14000000; + register uint32 XIP_CTRL_CTRL_raw at 0x14000000; type FLUSH_t { FLUSH = false; // Write 1 to flush the cache. This clears the tag memory, but the data memory retains its contents. (This means cache-as-SRAM contents is not affected by flush or reset.) Reading will hold the bus (stall the processor) until the flush completes. Alternatively STAT can be polled until completion. + _res1 = uint31(0); // Reserved, 31 bits } // Cache Flush control register FLUSH_t FLUSH at 0x14000004; + register uint32 FLUSH_raw at 0x14000004; type STAT_t { FLUSH_READY = false; // Reads as 0 while a cache flush is in progress, and 1 otherwise. The cache is flushed whenever the XIP block is reset, and also when requested via the FLUSH register. FIFO_EMPTY = false; // When 1, indicates the XIP streaming FIFO is completely empty. FIFO_FULL = false; // When 1, indicates the XIP streaming FIFO is completely full. The streaming FIFO is 2 entries deep, so the full and empty flag allow its level to be ascertained. + _res1 = uint29(0); // Reserved, 29 bits } // Cache Status register STAT_t STAT at 0x14000008; + register uint32 STAT_raw at 0x14000008; type CTR_HIT_t { CTR_HIT = uint32(0); // A 32 bit saturating counter that increments upon each cache hit, i.e. when an XIP access is serviced directly from cached data. Write any value to clear. @@ -4997,6 +7309,7 @@ // Cache Hit counter register CTR_HIT_t CTR_HIT at 0x1400000c; + register uint32 CTR_HIT_raw at 0x1400000c; type CTR_ACC_t { CTR_ACC = uint32(0); // A 32 bit saturating counter that increments upon each XIP access, whether the cache is hit or not. This includes noncacheable accesses. Write any value to clear. @@ -5004,6 +7317,7 @@ // Cache Access counter register CTR_ACC_t CTR_ACC at 0x14000010; + register uint32 CTR_ACC_raw at 0x14000010; type STREAM_ADDR_t { _res1 = uint2(0); // Reserved, 2 bits @@ -5012,13 +7326,16 @@ // FIFO stream address register STREAM_ADDR_t STREAM_ADDR at 0x14000014; + register uint32 STREAM_ADDR_raw at 0x14000014; type STREAM_CTR_t { STREAM_CTR = uint22(0); // Write a nonzero value to start a streaming read. This will then progress in the background, using flash idle cycles to transfer a linear data block from flash to the streaming FIFO. Decrements automatically (1 at a time) as the stream progresses, and halts on reaching 0. Write 0 to halt an in-progress stream, and discard any in-flight read, so that a new stream can immediately be started (after draining the FIFO and reinitialising STREAM_ADDR) + _res1 = uint10(0); // Reserved, 10 bits } // FIFO stream control register STREAM_CTR_t STREAM_CTR at 0x14000018; + register uint32 STREAM_CTR_raw at 0x14000018; type STREAM_FIFO_t { STREAM_FIFO = uint32(0); // Streamed data is buffered here, for retrieval by the system DMA. This FIFO can also be accessed via the XIP_AUX slave, to avoid exposing the DMA to bus stalls caused by other XIP traffic. @@ -5026,6 +7343,7 @@ // FIFO stream data register STREAM_FIFO_t STREAM_FIFO at 0x1400001c; + register uint32 STREAM_FIFO_raw at 0x1400001c; /* Types and registers for SYSCFG @@ -5038,6 +7356,7 @@ // Processor core 0 NMI source mask register PROC0_NMI_MASK_t PROC0_NMI_MASK at 0x40004000; + register uint32 PROC0_NMI_MASK_raw at 0x40004000; type PROC1_NMI_MASK_t { PROC1_NMI_MASK = uint32(0); // Set a bit high to enable NMI from that IRQ @@ -5045,32 +7364,37 @@ // Processor core 1 NMI source mask register PROC1_NMI_MASK_t PROC1_NMI_MASK at 0x40004004; + register uint32 PROC1_NMI_MASK_raw at 0x40004004; type PROC_CONFIG_t { PROC0_HALTED = false; // Indication that proc0 has halted PROC1_HALTED = false; // Indication that proc1 has halted - _res1 = uint16(0); // Reserved, 22 bits - _res2 = uint6(0); // + _res1 = uint22(0); // Reserved, 22 bits PROC0_DAP_INSTID = uint4(0); // Configure proc0 DAP instance ID. Recommend that this is NOT changed until you require debug access in multi-chip environment WARNING: do not set to 15 as this is reserved for RescueDP PROC1_DAP_INSTID = uint4(0); // Configure proc1 DAP instance ID. Recommend that this is NOT changed until you require debug access in multi-chip environment WARNING: do not set to 15 as this is reserved for RescueDP } // Configuration for processors register PROC_CONFIG_t PROC_CONFIG at 0x40004008; + register uint32 PROC_CONFIG_raw at 0x40004008; type PROC_IN_SYNC_BYPASS_t { PROC_IN_SYNC_BYPASS = uint30(0); // + _res1 = uint2(0); // Reserved, 2 bits } // For each bit, if 1, bypass the input synchronizer between that GPIO and the GPIO input register in the SIO. The input synchronizers should generally be unbypassed, to avoid injecting metastabilities into processors. If you're feeling brave, you can bypass to save two cycles of input latency. This register applies to GPIO 0...29. register PROC_IN_SYNC_BYPASS_t PROC_IN_SYNC_BYPASS at 0x4000400c; + register uint32 PROC_IN_SYNC_BYPASS_raw at 0x4000400c; type PROC_IN_SYNC_BYPASS_HI_t { PROC_IN_SYNC_BYPASS_HI = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // For each bit, if 1, bypass the input synchronizer between that GPIO and the GPIO input register in the SIO. The input synchronizers should generally be unbypassed, to avoid injecting metastabilities into processors. If you're feeling brave, you can bypass to save two cycles of input latency. This register applies to GPIO 30...35 (the QSPI IOs). register PROC_IN_SYNC_BYPASS_HI_t PROC_IN_SYNC_BYPASS_HI at 0x40004010; + register uint32 PROC_IN_SYNC_BYPASS_HI_raw at 0x40004010; type DBGFORCE_t { PROC0_SWDO = false; // Observe the value of processor 0 SWDIO output. @@ -5081,10 +7405,12 @@ PROC1_SWDI = false; // Directly drive processor 1 SWDIO input, if PROC1_ATTACH is set PROC1_SWCLK = false; // Directly drive processor 1 SWCLK, if PROC1_ATTACH is set PROC1_ATTACH = false; // Attach processor 1 debug port to syscfg controls, and disconnect it from external SWD pads. + _res1 = uint24(0); // Reserved, 24 bits } // Directly control the SWD debug port of either processor register DBGFORCE_t DBGFORCE at 0x40004014; + register uint32 DBGFORCE_raw at 0x40004014; type MEMPOWERDOWN_t { SRAM0 = false; // @@ -5095,38 +7421,65 @@ SRAM5 = false; // USB = false; // ROM = false; // + _res1 = uint24(0); // Reserved, 24 bits } // Control power downs to memories. Set high to power down memories. Use with extreme caution register MEMPOWERDOWN_t MEMPOWERDOWN at 0x40004018; + register uint32 MEMPOWERDOWN_raw at 0x40004018; /* Types and registers for XOSC Controls the crystal oscillator */ + enum XOSC_CTRL_ENABLE { + DISABLE = 3358, // + ENABLE = 4011 // + } + + enum XOSC_CTRL_FREQ_RANGE { + _1_15MHZ = 2720, // + RESERVED_1 = 2721, // + RESERVED_2 = 2722, // + RESERVED_3 = 2723 // + } + type XOSC_CTRL_t { FREQ_RANGE = uint12(0); // Frequency range. An invalid setting will retain the previous value. The actual value being used can be read from STATUS_FREQ_RANGE. This resets to 0xAA0 and cannot be changed. ENABLE = uint12(0); // On power-up this field is initialised to DISABLE and the chip runs from the ROSC. If the chip has subsequently been programmed to run from the XOSC then DISABLE may lock-up the chip. If this is a concern then run the clk_ref from the ROSC and enable the clk_sys RESUS feature. The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + _res1 = uint8(0); // Reserved, 8 bits } // Crystal Oscillator Control register XOSC_CTRL_t XOSC_CTRL at 0x40024000; + register uint32 XOSC_CTRL_raw at 0x40024000; + + enum XOSC_STATUS_FREQ_RANGE { + _1_15MHZ = 0, // + RESERVED_1 = 1, // + RESERVED_2 = 2, // + RESERVED_3 = 3 // + } type XOSC_STATUS_t { FREQ_RANGE = uint2(0); // The current frequency range setting, always reads 0 - _res1 = uint8(0); // Reserved, 10 bits - _res2 = uint2(0); // + _res1 = uint10(0); // Reserved, 10 bits ENABLED = false; // Oscillator is enabled but not necessarily running and stable, resets to 0 - _res3 = uint8(0); // Reserved, 11 bits - _res4 = uint3(0); // + _res2 = uint11(0); // Reserved, 11 bits BADWRITE = false; // An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or DORMANT - _res5 = uint6(0); // Reserved, 6 bits + _res3 = uint6(0); // Reserved, 6 bits STABLE = false; // Oscillator is running and stable } // Crystal Oscillator Status register XOSC_STATUS_t XOSC_STATUS at 0x40024004; + register uint32 XOSC_STATUS_raw at 0x40024004; + + enum XOSC_DORMANT_DORMANT { + dormant = 1668246881, // + WAKE = 2002873189 // + } type XOSC_DORMANT_t { DORMANT = uint32(0); // This is used to save power by pausing the XOSC On power-up this field is initialised to WAKE An invalid write will also select WAKE Warning: stop the PLLs before selecting dormant mode Warning: setup the irq before selecting dormant mode @@ -5134,22 +7487,27 @@ // Crystal Oscillator pause control register XOSC_DORMANT_t XOSC_DORMANT at 0x40024008; + register uint32 XOSC_DORMANT_raw at 0x40024008; type STARTUP_t { DELAY = uint14(0); // in multiples of 256*xtal_period. The reset value of 0xc4 corresponds to approx 50 000 cycles. _res1 = uint6(0); // Reserved, 6 bits X4 = false; // Multiplies the startup_delay by 4. This is of little value to the user given that the delay can be programmed directly. + _res2 = uint11(0); // Reserved, 11 bits } // Controls the startup delay register STARTUP_t STARTUP at 0x4002400c; + register uint32 STARTUP_raw at 0x4002400c; type XOSC_COUNT_t { COUNT = uint8(0); // + _res1 = uint24(0); // Reserved, 24 bits } // A down counter running at the xosc frequency which counts to zero and stops. To start the counter write a non-zero value. Can be used for short software pauses when setting up time sensitive hardware. register XOSC_COUNT_t XOSC_COUNT at 0x4002401c; + register uint32 XOSC_COUNT_raw at 0x4002401c; /* Types and registers for PLL_SYS */ @@ -5158,13 +7516,13 @@ REFDIV = uint6(0); // Divides the PLL input reference clock. Behaviour is undefined for div=0. PLL output will be unpredictable during refdiv changes, wait for lock=1 before using it. _res1 = uint2(0); // Reserved, 2 bits BYPASS = false; // Passes the reference clock to the output instead of the divided VCO. The VCO continues to run so the user can switch between the reference clock and the divided VCO but the output will glitch when doing so. - _res2 = uint16(0); // Reserved, 22 bits - _res3 = uint6(0); // + _res2 = uint22(0); // Reserved, 22 bits LOCK = false; // PLL is locked } // PLL_SYS Control and Status GENERAL CONSTRAINTS: Reference clock frequency min=5MHz, max=800MHz Feedback divider min=16, max=320 VCO frequency min=750MHz, max=1600MHz register PLL_SYS_CS_t PLL_SYS_PLL_SYS_CS at 0x40028000; + register uint32 PLL_SYS_PLL_SYS_CS_raw at 0x40028000; type PWR_t { PD = false; // PLL powerdown To save power set high when PLL output not required. @@ -5173,116 +7531,139 @@ POSTDIVPD = false; // PLL post divider powerdown To save power set high when PLL output not required or bypass=1. _res2 = false; // Reserved, 1 bits VCOPD = false; // PLL VCO powerdown To save power set high when PLL output not required or bypass=1. + _res3 = uint26(0); // Reserved, 26 bits } // PLL_SYS Controls the PLL power modes. register PWR_t PLL_SYS_PWR at 0x40028004; + register uint32 PLL_SYS_PWR_raw at 0x40028004; type FBDIV_INT_t { FBDIV_INT = uint12(0); // see ctrl reg description for constraints + _res1 = uint20(0); // Reserved, 20 bits } // PLL_SYS Feedback divisor (note: this PLL does not support fractional division) register FBDIV_INT_t PLL_SYS_FBDIV_INT at 0x40028008; + register uint32 PLL_SYS_FBDIV_INT_raw at 0x40028008; type PRIM_t { - _res1 = uint8(0); // Reserved, 12 bits - _res2 = uint4(0); // + _res1 = uint12(0); // Reserved, 12 bits POSTDIV2 = uint3(0); // divide by 1-7 - _res3 = false; // Reserved, 1 bits + _res2 = false; // Reserved, 1 bits POSTDIV1 = uint3(0); // divide by 1-7 + _res3 = uint13(0); // Reserved, 13 bits } // PLL_SYS Controls the PLL post dividers for the primary output (note: this PLL does not have a secondary output) the primary output is driven from VCO divided by postdiv1*postdiv2 register PRIM_t PLL_SYS_PRIM at 0x4002800c; + register uint32 PLL_SYS_PRIM_raw at 0x4002800c; /* Types and registers for PLL_USB */ // PLL_USB Control and Status GENERAL CONSTRAINTS: Reference clock frequency min=5MHz, max=800MHz Feedback divider min=16, max=320 VCO frequency min=750MHz, max=1600MHz register PLL_SYS_CS_t PLL_USB_CS at 0x4002c000; + register uint32 PLL_USB_CS_raw at 0x4002c000; // PLL_USB Controls the PLL power modes. register PWR_t PLL_USB_PWR at 0x4002c004; + register uint32 PLL_USB_PWR_raw at 0x4002c004; // PLL_USB Feedback divisor (note: this PLL does not support fractional division) register FBDIV_INT_t PLL_USB_FBDIV_INT at 0x4002c008; + register uint32 PLL_USB_FBDIV_INT_raw at 0x4002c008; // PLL_USB Controls the PLL post dividers for the primary output (note: this PLL does not have a secondary output) the primary output is driven from VCO divided by postdiv1*postdiv2 register PRIM_t PLL_USB_PRIM at 0x4002c00c; + register uint32 PLL_USB_PRIM_raw at 0x4002c00c; /* Types and registers for UART0 */ type UARTDR_t { - DATA = uint8(0); // Receive (read) data character. Transmit (write) data character. - FE = false; // Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is associated with the character at the top of the FIFO. - PE = false; // Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. In FIFO mode, this error is associated with the character at the top of the FIFO. - BE = false; // Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity and stop bits). In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state), and the next valid start bit is received. - OE = false; // Overrun error. This bit is set to 1 if data is received and the receive FIFO is already full. This is cleared to 0 once there is an empty space in the FIFO and a new character can be written to it. + DATA = uint8(0); // Receive (read) data character. Transmit (write) data character. + FE = false; // Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is associated with the character at the top of the FIFO. + PE = false; // Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. In FIFO mode, this error is associated with the character at the top of the FIFO. + BE = false; // Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity and stop bits). In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state), and the next valid start bit is received. + OE = false; // Overrun error. This bit is set to 1 if data is received and the receive FIFO is already full. This is cleared to 0 once there is an empty space in the FIFO and a new character can be written to it. + _res1 = uint20(0); // Reserved, 20 bits } // UART0 Data Register, UARTDR register UARTDR_t UART0_UARTDR at 0x40034000; + register uint32 UART0_UARTDR_raw at 0x40034000; type UARTRSR_t { - FE = false; // Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. - PE = false; // Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. - BE = false; // Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity, and stop bits). This bit is cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state) and the next valid start bit is received. - OE = false; // Overrun error. This bit is set to 1 if data is received and the FIFO is already full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain valid because no more data is written when the FIFO is full, only the contents of the shift register are overwritten. The CPU must now read the data, to empty the FIFO. + FE = false; // Framing error. When set to 1, it indicates that the received character did not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + PE = false; // Parity error. When set to 1, it indicates that the parity of the received data character does not match the parity that the EPS and SPS bits in the Line Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. + BE = false; // Break error. This bit is set to 1 if a break condition was detected, indicating that the received data input was held LOW for longer than a full-word transmission time (defined as start, data, parity, and stop bits). This bit is cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated with the character at the top of the FIFO. When a break occurs, only one 0 character is loaded into the FIFO. The next character is only enabled after the receive data input goes to a 1 (marking state) and the next valid start bit is received. + OE = false; // Overrun error. This bit is set to 1 if data is received and the FIFO is already full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain valid because no more data is written when the FIFO is full, only the contents of the shift register are overwritten. The CPU must now read the data, to empty the FIFO. + _res1 = uint28(0); // Reserved, 28 bits } // UART0 Receive Status Register/Error Clear Register, UARTRSR/UARTECR register UARTRSR_t UART0_UARTRSR at 0x40034004; + register uint32 UART0_UARTRSR_raw at 0x40034004; type UARTFR_t { - CTS = false; // Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW. - DSR = false; // Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW. - DCD = false; // Data carrier detect. This bit is the complement of the UART data carrier detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. - BUSY = false; // UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit remains set until the complete byte, including all the stop bits, has been sent from the shift register. This bit is set as soon as the transmit FIFO becomes non-empty, regardless of whether the UART is enabled or not. - RXFE = false; // Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set when the receive FIFO is empty. - TXFF = false; // Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set when the transmit FIFO is full. - RXFF = false; // Receive FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is full. If the FIFO is enabled, the RXFF bit is set when the receive FIFO is full. - TXFE = false; // Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is set when the transmit holding register is empty. If the FIFO is enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if there is data in the transmit shift register. - RI = false; // Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW. + CTS = false; // Clear to send. This bit is the complement of the UART clear to send, nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW. + DSR = false; // Data set ready. This bit is the complement of the UART data set ready, nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW. + DCD = false; // Data carrier detect. This bit is the complement of the UART data carrier detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD is LOW. + BUSY = false; // UART busy. If this bit is set to 1, the UART is busy transmitting data. This bit remains set until the complete byte, including all the stop bits, has been sent from the shift register. This bit is set as soon as the transmit FIFO becomes non-empty, regardless of whether the UART is enabled or not. + RXFE = false; // Receive FIFO empty. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set when the receive FIFO is empty. + TXFF = false; // Transmit FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set when the transmit FIFO is full. + RXFF = false; // Receive FIFO full. The meaning of this bit depends on the state of the FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when the receive holding register is full. If the FIFO is enabled, the RXFF bit is set when the receive FIFO is full. + TXFE = false; // Transmit FIFO empty. The meaning of this bit depends on the state of the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled, this bit is set when the transmit holding register is empty. If the FIFO is enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not indicate if there is data in the transmit shift register. + RI = false; // Ring indicator. This bit is the complement of the UART ring indicator, nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW. + _res1 = uint23(0); // Reserved, 23 bits } // UART0 Flag Register, UARTFR register UARTFR_t UART0_UARTFR at 0x40034018; + register uint32 UART0_UARTFR_raw at 0x40034018; type UARTILPR_t { ILPDVSR = uint8(0); // 8-bit low-power divisor value. These bits are cleared to 0 at reset. + _res1 = uint24(0); // Reserved, 24 bits } // UART0 IrDA Low-Power Counter Register, UARTILPR register UARTILPR_t UART0_UARTILPR at 0x40034020; + register uint32 UART0_UARTILPR_raw at 0x40034020; type UARTIBRD_t { BAUD_DIVINT = uint16(0); // The integer baud rate divisor. These bits are cleared to 0 on reset. + _res1 = uint16(0); // Reserved, 16 bits } // UART0 Integer Baud Rate Register, UARTIBRD register UARTIBRD_t UART0_UARTIBRD at 0x40034024; + register uint32 UART0_UARTIBRD_raw at 0x40034024; type UARTFBRD_t { BAUD_DIVFRAC = uint6(0); // The fractional baud rate divisor. These bits are cleared to 0 on reset. + _res1 = uint26(0); // Reserved, 26 bits } // UART0 Fractional Baud Rate Register, UARTFBRD register UARTFBRD_t UART0_UARTFBRD at 0x40034028; + register uint32 UART0_UARTFBRD_raw at 0x40034028; type UARTLCR_H_t { - BRK = false; // Send break. If this bit is set to 1, a low-level is continually output on the UARTTXD output, after completing transmission of the current character. For the proper execution of the break command, the software must set this bit for at least two complete frames. For normal use, this bit must be cleared to 0. - PEN = false; // Parity enable: 0 = parity is disabled and no parity bit added to the data frame 1 = parity checking and generation is enabled. - EPS = false; // Even parity select. Controls the type of parity the UART uses during transmission and reception: 0 = odd parity. The UART generates or checks for an odd number of 1s in the data and parity bits. 1 = even parity. The UART generates or checks for an even number of 1s in the data and parity bits. This bit has no effect when the PEN bit disables parity checking and generation. - STP2 = false; // Two stop bits select. If this bit is set to 1, two stop bits are transmitted at the end of the frame. The receive logic does not check for two stop bits being received. - FEN = false; // Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled (FIFO mode). - WLEN = uint2(0); // Word length. These bits indicate the number of data bits transmitted or received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. - SPS = false; // Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then the parity bit is transmitted and checked as a 0. This bit has no effect when the PEN bit disables parity checking and generation. + BRK = false; // Send break. If this bit is set to 1, a low-level is continually output on the UARTTXD output, after completing transmission of the current character. For the proper execution of the break command, the software must set this bit for at least two complete frames. For normal use, this bit must be cleared to 0. + PEN = false; // Parity enable: 0 = parity is disabled and no parity bit added to the data frame 1 = parity checking and generation is enabled. + EPS = false; // Even parity select. Controls the type of parity the UART uses during transmission and reception: 0 = odd parity. The UART generates or checks for an odd number of 1s in the data and parity bits. 1 = even parity. The UART generates or checks for an even number of 1s in the data and parity bits. This bit has no effect when the PEN bit disables parity checking and generation. + STP2 = false; // Two stop bits select. If this bit is set to 1, two stop bits are transmitted at the end of the frame. The receive logic does not check for two stop bits being received. + FEN = false; // Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers are enabled (FIFO mode). + WLEN = uint2(0); // Word length. These bits indicate the number of data bits transmitted or received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5 bits. + SPS = false; // Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is 0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then the parity bit is transmitted and checked as a 0. This bit has no effect when the PEN bit disables parity checking and generation. + _res1 = uint24(0); // Reserved, 24 bits } // UART0 Line Control Register, UARTLCR_H register UARTLCR_H_t UART0_UARTLCR_H at 0x4003402c; + register uint32 UART0_UARTLCR_H_raw at 0x4003402c; type UARTCR_t { UARTEN = false; // UART enable: 0 = UART is disabled. If the UART is disabled in the middle of transmission or reception, it completes the current character before stopping. 1 = the UART is enabled. Data transmission and reception occurs for either UART signals or SIR signals depending on the setting of the SIREN bit. @@ -5298,18 +7679,22 @@ OUT2 = false; // This bit is the complement of the UART Out2 (nUARTOut2) modem status output. That is, when the bit is programmed to a 1, the output is 0. For DTE this can be used as Ring Indicator (RI). RTSEN = false; // RTS hardware flow control enable. If this bit is set to 1, RTS hardware flow control is enabled. Data is only requested when there is space in the receive FIFO for it to be received. CTSEN = false; // CTS hardware flow control enable. If this bit is set to 1, CTS hardware flow control is enabled. Data is only transmitted when the nUARTCTS signal is asserted. + _res2 = uint16(0); // Reserved, 16 bits } // UART0 Control Register, UARTCR register UARTCR_t UART0_UARTCR at 0x40034030; + register uint32 UART0_UARTCR_raw at 0x40034030; type UARTIFLS_t { TXIFLSEL = uint3(0); // Transmit interrupt FIFO level select. The trigger points for the transmit interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full b001 = Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <= 1 / 2 full b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO becomes <= 7 / 8 full b101-b111 = reserved. RXIFLSEL = uint3(0); // Receive interrupt FIFO level select. The trigger points for the receive interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 = Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7 / 8 full b101-b111 = reserved. + _res1 = uint26(0); // Reserved, 26 bits } // UART0 Interrupt FIFO Level Select Register, UARTIFLS register UARTIFLS_t UART0_UARTIFLS at 0x40034034; + register uint32 UART0_UARTIFLS_raw at 0x40034034; type UARTIMSC_t { RIMIM = false; // nUARTRI modem interrupt mask. A read returns the current mask for the UARTRIINTR interrupt. On a write of 1, the mask of the UARTRIINTR interrupt is set. A write of 0 clears the mask. @@ -5323,10 +7708,12 @@ PEIM = false; // Parity error interrupt mask. A read returns the current mask for the UARTPEINTR interrupt. On a write of 1, the mask of the UARTPEINTR interrupt is set. A write of 0 clears the mask. BEIM = false; // Break error interrupt mask. A read returns the current mask for the UARTBEINTR interrupt. On a write of 1, the mask of the UARTBEINTR interrupt is set. A write of 0 clears the mask. OEIM = false; // Overrun error interrupt mask. A read returns the current mask for the UARTOEINTR interrupt. On a write of 1, the mask of the UARTOEINTR interrupt is set. A write of 0 clears the mask. + _res1 = uint21(0); // Reserved, 21 bits } // UART0 Interrupt Mask Set/Clear Register, UARTIMSC register UARTIMSC_t UART0_UARTIMSC at 0x40034038; + register uint32 UART0_UARTIMSC_raw at 0x40034038; type UARTRIS_t { RIRMIS = false; // nUARTRI modem interrupt status. Returns the raw interrupt state of the UARTRIINTR interrupt. @@ -5340,10 +7727,12 @@ PERIS = false; // Parity error interrupt status. Returns the raw interrupt state of the UARTPEINTR interrupt. BERIS = false; // Break error interrupt status. Returns the raw interrupt state of the UARTBEINTR interrupt. OERIS = false; // Overrun error interrupt status. Returns the raw interrupt state of the UARTOEINTR interrupt. + _res1 = uint21(0); // Reserved, 21 bits } // UART0 Raw Interrupt Status Register, UARTRIS register UARTRIS_t UART0_UARTRIS at 0x4003403c; + register uint32 UART0_UARTRIS_raw at 0x4003403c; type UARTMIS_t { RIMMIS = false; // nUARTRI modem masked interrupt status. Returns the masked interrupt state of the UARTRIINTR interrupt. @@ -5357,10 +7746,12 @@ PEMIS = false; // Parity error masked interrupt status. Returns the masked interrupt state of the UARTPEINTR interrupt. BEMIS = false; // Break error masked interrupt status. Returns the masked interrupt state of the UARTBEINTR interrupt. OEMIS = false; // Overrun error masked interrupt status. Returns the masked interrupt state of the UARTOEINTR interrupt. + _res1 = uint21(0); // Reserved, 21 bits } // UART0 Masked Interrupt Status Register, UARTMIS register UARTMIS_t UART0_UARTMIS at 0x40034040; + register uint32 UART0_UARTMIS_raw at 0x40034040; type UARTICR_t { RIMIC = false; // nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. @@ -5374,157 +7765,217 @@ PEIC = false; // Parity error interrupt clear. Clears the UARTPEINTR interrupt. BEIC = false; // Break error interrupt clear. Clears the UARTBEINTR interrupt. OEIC = false; // Overrun error interrupt clear. Clears the UARTOEINTR interrupt. + _res1 = uint21(0); // Reserved, 21 bits } // UART0 Interrupt Clear Register, UARTICR register UARTICR_t UART0_UARTICR at 0x40034044; + register uint32 UART0_UARTICR_raw at 0x40034044; type UARTDMACR_t { RXDMAE = false; // Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO is enabled. TXDMAE = false; // Transmit DMA enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. DMAONERR = false; // DMA on error. If this bit is set to 1, the DMA receive request outputs, UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the UART error interrupt is asserted. + _res1 = uint29(0); // Reserved, 29 bits } // UART0 DMA Control Register, UARTDMACR register UARTDMACR_t UART0_UARTDMACR at 0x40034048; + register uint32 UART0_UARTDMACR_raw at 0x40034048; type UARTPERIPHID0_t { PARTNUMBER0 = uint8(0); // These bits read back as 0x11 + _res1 = uint24(0); // Reserved, 24 bits } // UART0 UARTPeriphID0 Register register UARTPERIPHID0_t UART0_UARTPERIPHID0 at 0x40034fe0; + register uint32 UART0_UARTPERIPHID0_raw at 0x40034fe0; type UARTPERIPHID1_t { PARTNUMBER1 = uint4(0); // These bits read back as 0x0 DESIGNER0 = uint4(0); // These bits read back as 0x1 + _res1 = uint24(0); // Reserved, 24 bits } // UART0 UARTPeriphID1 Register register UARTPERIPHID1_t UART0_UARTPERIPHID1 at 0x40034fe4; + register uint32 UART0_UARTPERIPHID1_raw at 0x40034fe4; type UARTPERIPHID2_t { DESIGNER1 = uint4(0); // These bits read back as 0x4 REVISION = uint4(0); // This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1 r1p3 0x2 r1p4 0x2 r1p5 0x3 + _res1 = uint24(0); // Reserved, 24 bits } // UART0 UARTPeriphID2 Register register UARTPERIPHID2_t UART0_UARTPERIPHID2 at 0x40034fe8; + register uint32 UART0_UARTPERIPHID2_raw at 0x40034fe8; type UARTPERIPHID3_t { CONFIGURATION = uint8(0); // These bits read back as 0x00 + _res1 = uint24(0); // Reserved, 24 bits } // UART0 UARTPeriphID3 Register register UARTPERIPHID3_t UART0_UARTPERIPHID3 at 0x40034fec; + register uint32 UART0_UARTPERIPHID3_raw at 0x40034fec; type UARTPCELLID0_t { UARTPCELLID0 = uint8(0); // These bits read back as 0x0D + _res1 = uint24(0); // Reserved, 24 bits } // UART0 UARTPCellID0 Register register UARTPCELLID0_t UART0_UARTPCELLID0 at 0x40034ff0; + register uint32 UART0_UARTPCELLID0_raw at 0x40034ff0; type UARTPCELLID1_t { UARTPCELLID1 = uint8(0); // These bits read back as 0xF0 + _res1 = uint24(0); // Reserved, 24 bits } // UART0 UARTPCellID1 Register register UARTPCELLID1_t UART0_UARTPCELLID1 at 0x40034ff4; + register uint32 UART0_UARTPCELLID1_raw at 0x40034ff4; type UARTPCELLID2_t { UARTPCELLID2 = uint8(0); // These bits read back as 0x05 + _res1 = uint24(0); // Reserved, 24 bits } // UART0 UARTPCellID2 Register register UARTPCELLID2_t UART0_UARTPCELLID2 at 0x40034ff8; + register uint32 UART0_UARTPCELLID2_raw at 0x40034ff8; type UARTPCELLID3_t { UARTPCELLID3 = uint8(0); // These bits read back as 0xB1 + _res1 = uint24(0); // Reserved, 24 bits } // UART0 UARTPCellID3 Register register UARTPCELLID3_t UART0_UARTPCELLID3 at 0x40034ffc; + register uint32 UART0_UARTPCELLID3_raw at 0x40034ffc; /* Types and registers for UART1 */ // UART1 Data Register, UARTDR register UARTDR_t UART1_UARTDR at 0x40038000; + register uint32 UART1_UARTDR_raw at 0x40038000; // UART1 Receive Status Register/Error Clear Register, UARTRSR/UARTECR register UARTRSR_t UART1_UARTRSR at 0x40038004; + register uint32 UART1_UARTRSR_raw at 0x40038004; // UART1 Flag Register, UARTFR register UARTFR_t UART1_UARTFR at 0x40038018; + register uint32 UART1_UARTFR_raw at 0x40038018; // UART1 IrDA Low-Power Counter Register, UARTILPR register UARTILPR_t UART1_UARTILPR at 0x40038020; + register uint32 UART1_UARTILPR_raw at 0x40038020; // UART1 Integer Baud Rate Register, UARTIBRD register UARTIBRD_t UART1_UARTIBRD at 0x40038024; + register uint32 UART1_UARTIBRD_raw at 0x40038024; // UART1 Fractional Baud Rate Register, UARTFBRD register UARTFBRD_t UART1_UARTFBRD at 0x40038028; + register uint32 UART1_UARTFBRD_raw at 0x40038028; // UART1 Line Control Register, UARTLCR_H register UARTLCR_H_t UART1_UARTLCR_H at 0x4003802c; + register uint32 UART1_UARTLCR_H_raw at 0x4003802c; // UART1 Control Register, UARTCR register UARTCR_t UART1_UARTCR at 0x40038030; + register uint32 UART1_UARTCR_raw at 0x40038030; // UART1 Interrupt FIFO Level Select Register, UARTIFLS register UARTIFLS_t UART1_UARTIFLS at 0x40038034; + register uint32 UART1_UARTIFLS_raw at 0x40038034; // UART1 Interrupt Mask Set/Clear Register, UARTIMSC register UARTIMSC_t UART1_UARTIMSC at 0x40038038; + register uint32 UART1_UARTIMSC_raw at 0x40038038; // UART1 Raw Interrupt Status Register, UARTRIS register UARTRIS_t UART1_UARTRIS at 0x4003803c; + register uint32 UART1_UARTRIS_raw at 0x4003803c; // UART1 Masked Interrupt Status Register, UARTMIS register UARTMIS_t UART1_UARTMIS at 0x40038040; + register uint32 UART1_UARTMIS_raw at 0x40038040; // UART1 Interrupt Clear Register, UARTICR register UARTICR_t UART1_UARTICR at 0x40038044; + register uint32 UART1_UARTICR_raw at 0x40038044; // UART1 DMA Control Register, UARTDMACR register UARTDMACR_t UART1_UARTDMACR at 0x40038048; + register uint32 UART1_UARTDMACR_raw at 0x40038048; // UART1 UARTPeriphID0 Register register UARTPERIPHID0_t UART1_UARTPERIPHID0 at 0x40038fe0; + register uint32 UART1_UARTPERIPHID0_raw at 0x40038fe0; // UART1 UARTPeriphID1 Register register UARTPERIPHID1_t UART1_UARTPERIPHID1 at 0x40038fe4; + register uint32 UART1_UARTPERIPHID1_raw at 0x40038fe4; // UART1 UARTPeriphID2 Register register UARTPERIPHID2_t UART1_UARTPERIPHID2 at 0x40038fe8; + register uint32 UART1_UARTPERIPHID2_raw at 0x40038fe8; // UART1 UARTPeriphID3 Register register UARTPERIPHID3_t UART1_UARTPERIPHID3 at 0x40038fec; + register uint32 UART1_UARTPERIPHID3_raw at 0x40038fec; // UART1 UARTPCellID0 Register register UARTPCELLID0_t UART1_UARTPCELLID0 at 0x40038ff0; + register uint32 UART1_UARTPCELLID0_raw at 0x40038ff0; // UART1 UARTPCellID1 Register register UARTPCELLID1_t UART1_UARTPCELLID1 at 0x40038ff4; + register uint32 UART1_UARTPCELLID1_raw at 0x40038ff4; // UART1 UARTPCellID2 Register register UARTPCELLID2_t UART1_UARTPCELLID2 at 0x40038ff8; + register uint32 UART1_UARTPCELLID2_raw at 0x40038ff8; // UART1 UARTPCellID3 Register register UARTPCELLID3_t UART1_UARTPCELLID3 at 0x40038ffc; + register uint32 UART1_UARTPCELLID3_raw at 0x40038ffc; /* Types and registers for ROSC */ + enum ROSC_CTRL_ENABLE { + DISABLE = 3358, // + ENABLE = 4011 // + } + + enum ROSC_CTRL_FREQ_RANGE { + LOW = 4004, // + MEDIUM = 4005, // + HIGH = 4007, // + TOOHIGH = 4006 // + } + type ROSC_CTRL_t { FREQ_RANGE = uint12(0); // Controls the number of delay stages in the ROSC ring LOW uses stages 0 to 7 MEDIUM uses stages 2 to 7 HIGH uses stages 4 to 7 TOOHIGH uses stages 6 to 7 and should not be used because its frequency exceeds design specifications The clock output will not glitch when changing the range up one step at a time The clock output will glitch when changing the range down Note: the values here are gray coded which is why HIGH comes before TOOHIGH ENABLE = uint12(0); // On power-up this field is initialised to ENABLE The system clock must be switched to another source before setting this field to DISABLE otherwise the chip will lock up The 12-bit code is intended to give some protection against accidental writes. An invalid setting will enable the oscillator. + _res1 = uint8(0); // Reserved, 8 bits } // Ring Oscillator control register ROSC_CTRL_t ROSC_CTRL at 0x40060000; + register uint32 ROSC_CTRL_raw at 0x40060000; + + enum FREQA_PASSWD { + PASS = 38550 // + } type FREQA_t { DS0 = uint3(0); // Stage 0 drive strength @@ -5540,6 +7991,11 @@ // The FREQA & FREQB registers control the frequency by controlling the drive strength of each stage The drive strength has 4 levels determined by the number of bits set Increasing the number of bits set increases the drive strength and increases the oscillation frequency 0 bits set is the default drive strength 1 bit set doubles the drive strength 2 bits set triples drive strength 3 bits set quadruples drive strength register FREQA_t FREQA at 0x40060004; + register uint32 FREQA_raw at 0x40060004; + + enum FREQB_PASSWD { + PASS = 38550 // + } type FREQB_t { DS4 = uint3(0); // Stage 4 drive strength @@ -5555,6 +8011,12 @@ // For a detailed description see freqa register register FREQB_t FREQB at 0x40060008; + register uint32 FREQB_raw at 0x40060008; + + enum ROSC_DORMANT_DORMANT { + dormant = 1668246881, // + WAKE = 2002873189 // + } type ROSC_DORMANT_t { DORMANT = uint32(0); // This is used to save power by pausing the ROSC On power-up this field is initialised to WAKE An invalid write will also select WAKE Warning: setup the irq before selecting dormant mode @@ -5562,52 +8024,65 @@ // Ring Oscillator pause control register ROSC_DORMANT_t ROSC_DORMANT at 0x4006000c; + register uint32 ROSC_DORMANT_raw at 0x4006000c; + + enum ROSC_DIV_DIV { + PASS = 2720 // + } type ROSC_DIV_t { - DIV = uint12(0); // set to 0xaa0 + div where div = 0 divides by 32 div = 1-31 divides by div any other value sets div=31 this register resets to div=16 + DIV = uint12(0); // set to 0xaa0 + div where div = 0 divides by 32 div = 1-31 divides by div any other value sets div=31 this register resets to div=16 + _res1 = uint20(0); // Reserved, 20 bits } // Controls the output divider register ROSC_DIV_t ROSC_DIV at 0x40060010; + register uint32 ROSC_DIV_raw at 0x40060010; type PHASE_t { SHIFT = uint2(0); // phase shift the phase-shifted output by SHIFT input clocks this can be changed on-the-fly must be set to 0 before setting div=1 FLIP = false; // invert the phase-shifted output this is ignored when div=1 ENABLE = false; // enable the phase-shifted output this can be changed on-the-fly PASSWD = uint8(0); // set to 0xaa any other value enables the output with shift=0 + _res1 = uint20(0); // Reserved, 20 bits } // Controls the phase shifted output register PHASE_t PHASE at 0x40060014; + register uint32 PHASE_raw at 0x40060014; type ROSC_STATUS_t { - _res1 = uint8(0); // Reserved, 12 bits - _res2 = uint4(0); // + _res1 = uint12(0); // Reserved, 12 bits ENABLED = false; // Oscillator is enabled but not necessarily running and stable this resets to 0 but transitions to 1 during chip startup - _res3 = uint3(0); // Reserved, 3 bits + _res2 = uint3(0); // Reserved, 3 bits DIV_RUNNING = false; // post-divider is running this resets to 0 but transitions to 1 during chip startup - _res4 = uint7(0); // Reserved, 7 bits + _res3 = uint7(0); // Reserved, 7 bits BADWRITE = false; // An invalid value has been written to CTRL_ENABLE or CTRL_FREQ_RANGE or FREQA or FREQB or DIV or PHASE or DORMANT - _res5 = uint6(0); // Reserved, 6 bits + _res4 = uint6(0); // Reserved, 6 bits STABLE = false; // Oscillator is running and stable } // Ring Oscillator Status register ROSC_STATUS_t ROSC_STATUS at 0x40060018; + register uint32 ROSC_STATUS_raw at 0x40060018; type RANDOMBIT_t { RANDOMBIT = false; // + _res1 = uint31(0); // Reserved, 31 bits } // This just reads the state of the oscillator output so randomness is compromised if the ring oscillator is stopped or run at a harmonic of the bus frequency register RANDOMBIT_t RANDOMBIT at 0x4006001c; + register uint32 RANDOMBIT_raw at 0x4006001c; type ROSC_COUNT_t { COUNT = uint8(0); // + _res1 = uint24(0); // Reserved, 24 bits } // A down counter running at the ROSC frequency which counts to zero and stops. To start the counter write a non-zero value. Can be used for short software pauses when setting up time sensitive hardware. register ROSC_COUNT_t ROSC_COUNT at 0x40060020; + register uint32 ROSC_COUNT_raw at 0x40060020; /* Types and registers for WATCHDOG */ @@ -5624,21 +8099,26 @@ // Watchdog control The rst_wdsel register determines which subsystems are reset when the watchdog is triggered. The watchdog can be triggered in software. register WATCHDOG_CTRL_t WATCHDOG_CTRL at 0x40058000; + register uint32 WATCHDOG_CTRL_raw at 0x40058000; type LOAD_t { - LOAD = uint24(0); // + LOAD = uint24(0); // + _res1 = uint8(0); // Reserved, 8 bits } // Load the watchdog timer. The maximum setting is 0xffffff which corresponds to 0xffffff / 2 ticks before triggering a watchdog reset (see errata RP2040-E1). register LOAD_t LOAD at 0x40058004; + register uint32 LOAD_raw at 0x40058004; type REASON_t { TIMER = false; // FORCE = false; // + _res1 = uint30(0); // Reserved, 30 bits } // Logs the reason for the last reset. Both bits are zero for the case of a hardware reset. register REASON_t REASON at 0x40058008; + register uint32 REASON_raw at 0x40058008; type SCRATCH0_t { SCRATCH0 = uint32(0); // @@ -5646,6 +8126,7 @@ // Scratch register. Information persists through soft reset of the chip. register SCRATCH0_t SCRATCH0 at 0x4005800c; + register uint32 SCRATCH0_raw at 0x4005800c; type SCRATCH1_t { SCRATCH1 = uint32(0); // @@ -5653,6 +8134,7 @@ // Scratch register. Information persists through soft reset of the chip. register SCRATCH1_t SCRATCH1 at 0x40058010; + register uint32 SCRATCH1_raw at 0x40058010; type SCRATCH2_t { SCRATCH2 = uint32(0); // @@ -5660,6 +8142,7 @@ // Scratch register. Information persists through soft reset of the chip. register SCRATCH2_t SCRATCH2 at 0x40058014; + register uint32 SCRATCH2_raw at 0x40058014; type SCRATCH3_t { SCRATCH3 = uint32(0); // @@ -5667,6 +8150,7 @@ // Scratch register. Information persists through soft reset of the chip. register SCRATCH3_t SCRATCH3 at 0x40058018; + register uint32 SCRATCH3_raw at 0x40058018; type SCRATCH4_t { SCRATCH4 = uint32(0); // @@ -5674,6 +8158,7 @@ // Scratch register. Information persists through soft reset of the chip. register SCRATCH4_t SCRATCH4 at 0x4005801c; + register uint32 SCRATCH4_raw at 0x4005801c; type SCRATCH5_t { SCRATCH5 = uint32(0); // @@ -5681,6 +8166,7 @@ // Scratch register. Information persists through soft reset of the chip. register SCRATCH5_t SCRATCH5 at 0x40058020; + register uint32 SCRATCH5_raw at 0x40058020; type SCRATCH6_t { SCRATCH6 = uint32(0); // @@ -5688,6 +8174,7 @@ // Scratch register. Information persists through soft reset of the chip. register SCRATCH6_t SCRATCH6 at 0x40058024; + register uint32 SCRATCH6_raw at 0x40058024; type SCRATCH7_t { SCRATCH7 = uint32(0); // @@ -5695,16 +8182,19 @@ // Scratch register. Information persists through soft reset of the chip. register SCRATCH7_t SCRATCH7 at 0x40058028; + register uint32 SCRATCH7_raw at 0x40058028; type TICK_t { CYCLES = uint9(0); // Total number of clk_tick cycles before the next tick. ENABLE = false; // start / stop tick generation RUNNING = false; // Is the tick generator running? COUNT = uint9(0); // Count down timer: the remaining number clk_tick cycles before the next tick is generated. + _res1 = uint12(0); // Reserved, 12 bits } // Controls the tick generator register TICK_t TICK at 0x4005802c; + register uint32 TICK_raw at 0x4005802c; /* Types and registers for DMA @@ -5717,6 +8207,7 @@ // DMA Channel 0 Read Address pointer register CH0_READ_ADDR_t CH0_READ_ADDR at 0x50000000; + register uint32 CH0_READ_ADDR_raw at 0x50000000; type CH0_WRITE_ADDR_t { CH0_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -5724,6 +8215,7 @@ // DMA Channel 0 Write Address pointer register CH0_WRITE_ADDR_t CH0_WRITE_ADDR at 0x50000004; + register uint32 CH0_WRITE_ADDR_raw at 0x50000004; type CH0_TRANS_COUNT_t { CH0_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -5731,6 +8223,65 @@ // DMA Channel 0 Transfer Count register CH0_TRANS_COUNT_t CH0_TRANS_COUNT at 0x50000008; + register uint32 CH0_TRANS_COUNT_raw at 0x50000008; + + enum CH0_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH0_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH0_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH0_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -5754,6 +8305,7 @@ // DMA Channel 0 Control and Status register CH0_CTRL_TRIG_t CH0_CTRL_TRIG at 0x5000000c; + register uint32 CH0_CTRL_TRIG_raw at 0x5000000c; type CH0_AL1_CTRL_t { CH0_AL1_CTRL = uint32(0); // @@ -5761,6 +8313,7 @@ // Alias for channel 0 CTRL register register CH0_AL1_CTRL_t CH0_AL1_CTRL at 0x50000010; + register uint32 CH0_AL1_CTRL_raw at 0x50000010; type CH0_AL1_READ_ADDR_t { CH0_AL1_READ_ADDR = uint32(0); // @@ -5768,6 +8321,7 @@ // Alias for channel 0 READ_ADDR register register CH0_AL1_READ_ADDR_t CH0_AL1_READ_ADDR at 0x50000014; + register uint32 CH0_AL1_READ_ADDR_raw at 0x50000014; type CH0_AL1_WRITE_ADDR_t { CH0_AL1_WRITE_ADDR = uint32(0); // @@ -5775,6 +8329,7 @@ // Alias for channel 0 WRITE_ADDR register register CH0_AL1_WRITE_ADDR_t CH0_AL1_WRITE_ADDR at 0x50000018; + register uint32 CH0_AL1_WRITE_ADDR_raw at 0x50000018; type CH0_AL1_TRANS_COUNT_TRIG_t { CH0_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -5782,6 +8337,7 @@ // Alias for channel 0 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH0_AL1_TRANS_COUNT_TRIG_t CH0_AL1_TRANS_COUNT_TRIG at 0x5000001c; + register uint32 CH0_AL1_TRANS_COUNT_TRIG_raw at 0x5000001c; type CH0_AL2_CTRL_t { CH0_AL2_CTRL = uint32(0); // @@ -5789,6 +8345,7 @@ // Alias for channel 0 CTRL register register CH0_AL2_CTRL_t CH0_AL2_CTRL at 0x50000020; + register uint32 CH0_AL2_CTRL_raw at 0x50000020; type CH0_AL2_TRANS_COUNT_t { CH0_AL2_TRANS_COUNT = uint32(0); // @@ -5796,6 +8353,7 @@ // Alias for channel 0 TRANS_COUNT register register CH0_AL2_TRANS_COUNT_t CH0_AL2_TRANS_COUNT at 0x50000024; + register uint32 CH0_AL2_TRANS_COUNT_raw at 0x50000024; type CH0_AL2_READ_ADDR_t { CH0_AL2_READ_ADDR = uint32(0); // @@ -5803,6 +8361,7 @@ // Alias for channel 0 READ_ADDR register register CH0_AL2_READ_ADDR_t CH0_AL2_READ_ADDR at 0x50000028; + register uint32 CH0_AL2_READ_ADDR_raw at 0x50000028; type CH0_AL2_WRITE_ADDR_TRIG_t { CH0_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -5810,6 +8369,7 @@ // Alias for channel 0 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH0_AL2_WRITE_ADDR_TRIG_t CH0_AL2_WRITE_ADDR_TRIG at 0x5000002c; + register uint32 CH0_AL2_WRITE_ADDR_TRIG_raw at 0x5000002c; type CH0_AL3_CTRL_t { CH0_AL3_CTRL = uint32(0); // @@ -5817,6 +8377,7 @@ // Alias for channel 0 CTRL register register CH0_AL3_CTRL_t CH0_AL3_CTRL at 0x50000030; + register uint32 CH0_AL3_CTRL_raw at 0x50000030; type CH0_AL3_WRITE_ADDR_t { CH0_AL3_WRITE_ADDR = uint32(0); // @@ -5824,6 +8385,7 @@ // Alias for channel 0 WRITE_ADDR register register CH0_AL3_WRITE_ADDR_t CH0_AL3_WRITE_ADDR at 0x50000034; + register uint32 CH0_AL3_WRITE_ADDR_raw at 0x50000034; type CH0_AL3_TRANS_COUNT_t { CH0_AL3_TRANS_COUNT = uint32(0); // @@ -5831,6 +8393,7 @@ // Alias for channel 0 TRANS_COUNT register register CH0_AL3_TRANS_COUNT_t CH0_AL3_TRANS_COUNT at 0x50000038; + register uint32 CH0_AL3_TRANS_COUNT_raw at 0x50000038; type CH0_AL3_READ_ADDR_TRIG_t { CH0_AL3_READ_ADDR_TRIG = uint32(0); // @@ -5838,6 +8401,7 @@ // Alias for channel 0 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH0_AL3_READ_ADDR_TRIG_t CH0_AL3_READ_ADDR_TRIG at 0x5000003c; + register uint32 CH0_AL3_READ_ADDR_TRIG_raw at 0x5000003c; type CH1_READ_ADDR_t { CH1_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -5845,6 +8409,7 @@ // DMA Channel 1 Read Address pointer register CH1_READ_ADDR_t CH1_READ_ADDR at 0x50000040; + register uint32 CH1_READ_ADDR_raw at 0x50000040; type CH1_WRITE_ADDR_t { CH1_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -5852,6 +8417,7 @@ // DMA Channel 1 Write Address pointer register CH1_WRITE_ADDR_t CH1_WRITE_ADDR at 0x50000044; + register uint32 CH1_WRITE_ADDR_raw at 0x50000044; type CH1_TRANS_COUNT_t { CH1_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -5859,6 +8425,65 @@ // DMA Channel 1 Transfer Count register CH1_TRANS_COUNT_t CH1_TRANS_COUNT at 0x50000048; + register uint32 CH1_TRANS_COUNT_raw at 0x50000048; + + enum CH1_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH1_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH1_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH1_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -5882,6 +8507,7 @@ // DMA Channel 1 Control and Status register CH1_CTRL_TRIG_t CH1_CTRL_TRIG at 0x5000004c; + register uint32 CH1_CTRL_TRIG_raw at 0x5000004c; type CH1_AL1_CTRL_t { CH1_AL1_CTRL = uint32(0); // @@ -5889,6 +8515,7 @@ // Alias for channel 1 CTRL register register CH1_AL1_CTRL_t CH1_AL1_CTRL at 0x50000050; + register uint32 CH1_AL1_CTRL_raw at 0x50000050; type CH1_AL1_READ_ADDR_t { CH1_AL1_READ_ADDR = uint32(0); // @@ -5896,6 +8523,7 @@ // Alias for channel 1 READ_ADDR register register CH1_AL1_READ_ADDR_t CH1_AL1_READ_ADDR at 0x50000054; + register uint32 CH1_AL1_READ_ADDR_raw at 0x50000054; type CH1_AL1_WRITE_ADDR_t { CH1_AL1_WRITE_ADDR = uint32(0); // @@ -5903,6 +8531,7 @@ // Alias for channel 1 WRITE_ADDR register register CH1_AL1_WRITE_ADDR_t CH1_AL1_WRITE_ADDR at 0x50000058; + register uint32 CH1_AL1_WRITE_ADDR_raw at 0x50000058; type CH1_AL1_TRANS_COUNT_TRIG_t { CH1_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -5910,6 +8539,7 @@ // Alias for channel 1 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH1_AL1_TRANS_COUNT_TRIG_t CH1_AL1_TRANS_COUNT_TRIG at 0x5000005c; + register uint32 CH1_AL1_TRANS_COUNT_TRIG_raw at 0x5000005c; type CH1_AL2_CTRL_t { CH1_AL2_CTRL = uint32(0); // @@ -5917,6 +8547,7 @@ // Alias for channel 1 CTRL register register CH1_AL2_CTRL_t CH1_AL2_CTRL at 0x50000060; + register uint32 CH1_AL2_CTRL_raw at 0x50000060; type CH1_AL2_TRANS_COUNT_t { CH1_AL2_TRANS_COUNT = uint32(0); // @@ -5924,6 +8555,7 @@ // Alias for channel 1 TRANS_COUNT register register CH1_AL2_TRANS_COUNT_t CH1_AL2_TRANS_COUNT at 0x50000064; + register uint32 CH1_AL2_TRANS_COUNT_raw at 0x50000064; type CH1_AL2_READ_ADDR_t { CH1_AL2_READ_ADDR = uint32(0); // @@ -5931,6 +8563,7 @@ // Alias for channel 1 READ_ADDR register register CH1_AL2_READ_ADDR_t CH1_AL2_READ_ADDR at 0x50000068; + register uint32 CH1_AL2_READ_ADDR_raw at 0x50000068; type CH1_AL2_WRITE_ADDR_TRIG_t { CH1_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -5938,6 +8571,7 @@ // Alias for channel 1 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH1_AL2_WRITE_ADDR_TRIG_t CH1_AL2_WRITE_ADDR_TRIG at 0x5000006c; + register uint32 CH1_AL2_WRITE_ADDR_TRIG_raw at 0x5000006c; type CH1_AL3_CTRL_t { CH1_AL3_CTRL = uint32(0); // @@ -5945,6 +8579,7 @@ // Alias for channel 1 CTRL register register CH1_AL3_CTRL_t CH1_AL3_CTRL at 0x50000070; + register uint32 CH1_AL3_CTRL_raw at 0x50000070; type CH1_AL3_WRITE_ADDR_t { CH1_AL3_WRITE_ADDR = uint32(0); // @@ -5952,6 +8587,7 @@ // Alias for channel 1 WRITE_ADDR register register CH1_AL3_WRITE_ADDR_t CH1_AL3_WRITE_ADDR at 0x50000074; + register uint32 CH1_AL3_WRITE_ADDR_raw at 0x50000074; type CH1_AL3_TRANS_COUNT_t { CH1_AL3_TRANS_COUNT = uint32(0); // @@ -5959,6 +8595,7 @@ // Alias for channel 1 TRANS_COUNT register register CH1_AL3_TRANS_COUNT_t CH1_AL3_TRANS_COUNT at 0x50000078; + register uint32 CH1_AL3_TRANS_COUNT_raw at 0x50000078; type CH1_AL3_READ_ADDR_TRIG_t { CH1_AL3_READ_ADDR_TRIG = uint32(0); // @@ -5966,6 +8603,7 @@ // Alias for channel 1 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH1_AL3_READ_ADDR_TRIG_t CH1_AL3_READ_ADDR_TRIG at 0x5000007c; + register uint32 CH1_AL3_READ_ADDR_TRIG_raw at 0x5000007c; type CH2_READ_ADDR_t { CH2_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -5973,6 +8611,7 @@ // DMA Channel 2 Read Address pointer register CH2_READ_ADDR_t CH2_READ_ADDR at 0x50000080; + register uint32 CH2_READ_ADDR_raw at 0x50000080; type CH2_WRITE_ADDR_t { CH2_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -5980,6 +8619,7 @@ // DMA Channel 2 Write Address pointer register CH2_WRITE_ADDR_t CH2_WRITE_ADDR at 0x50000084; + register uint32 CH2_WRITE_ADDR_raw at 0x50000084; type CH2_TRANS_COUNT_t { CH2_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -5987,6 +8627,65 @@ // DMA Channel 2 Transfer Count register CH2_TRANS_COUNT_t CH2_TRANS_COUNT at 0x50000088; + register uint32 CH2_TRANS_COUNT_raw at 0x50000088; + + enum CH2_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH2_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH2_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH2_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -6010,6 +8709,7 @@ // DMA Channel 2 Control and Status register CH2_CTRL_TRIG_t CH2_CTRL_TRIG at 0x5000008c; + register uint32 CH2_CTRL_TRIG_raw at 0x5000008c; type CH2_AL1_CTRL_t { CH2_AL1_CTRL = uint32(0); // @@ -6017,6 +8717,7 @@ // Alias for channel 2 CTRL register register CH2_AL1_CTRL_t CH2_AL1_CTRL at 0x50000090; + register uint32 CH2_AL1_CTRL_raw at 0x50000090; type CH2_AL1_READ_ADDR_t { CH2_AL1_READ_ADDR = uint32(0); // @@ -6024,6 +8725,7 @@ // Alias for channel 2 READ_ADDR register register CH2_AL1_READ_ADDR_t CH2_AL1_READ_ADDR at 0x50000094; + register uint32 CH2_AL1_READ_ADDR_raw at 0x50000094; type CH2_AL1_WRITE_ADDR_t { CH2_AL1_WRITE_ADDR = uint32(0); // @@ -6031,6 +8733,7 @@ // Alias for channel 2 WRITE_ADDR register register CH2_AL1_WRITE_ADDR_t CH2_AL1_WRITE_ADDR at 0x50000098; + register uint32 CH2_AL1_WRITE_ADDR_raw at 0x50000098; type CH2_AL1_TRANS_COUNT_TRIG_t { CH2_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -6038,6 +8741,7 @@ // Alias for channel 2 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH2_AL1_TRANS_COUNT_TRIG_t CH2_AL1_TRANS_COUNT_TRIG at 0x5000009c; + register uint32 CH2_AL1_TRANS_COUNT_TRIG_raw at 0x5000009c; type CH2_AL2_CTRL_t { CH2_AL2_CTRL = uint32(0); // @@ -6045,6 +8749,7 @@ // Alias for channel 2 CTRL register register CH2_AL2_CTRL_t CH2_AL2_CTRL at 0x500000a0; + register uint32 CH2_AL2_CTRL_raw at 0x500000a0; type CH2_AL2_TRANS_COUNT_t { CH2_AL2_TRANS_COUNT = uint32(0); // @@ -6052,6 +8757,7 @@ // Alias for channel 2 TRANS_COUNT register register CH2_AL2_TRANS_COUNT_t CH2_AL2_TRANS_COUNT at 0x500000a4; + register uint32 CH2_AL2_TRANS_COUNT_raw at 0x500000a4; type CH2_AL2_READ_ADDR_t { CH2_AL2_READ_ADDR = uint32(0); // @@ -6059,6 +8765,7 @@ // Alias for channel 2 READ_ADDR register register CH2_AL2_READ_ADDR_t CH2_AL2_READ_ADDR at 0x500000a8; + register uint32 CH2_AL2_READ_ADDR_raw at 0x500000a8; type CH2_AL2_WRITE_ADDR_TRIG_t { CH2_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -6066,6 +8773,7 @@ // Alias for channel 2 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH2_AL2_WRITE_ADDR_TRIG_t CH2_AL2_WRITE_ADDR_TRIG at 0x500000ac; + register uint32 CH2_AL2_WRITE_ADDR_TRIG_raw at 0x500000ac; type CH2_AL3_CTRL_t { CH2_AL3_CTRL = uint32(0); // @@ -6073,6 +8781,7 @@ // Alias for channel 2 CTRL register register CH2_AL3_CTRL_t CH2_AL3_CTRL at 0x500000b0; + register uint32 CH2_AL3_CTRL_raw at 0x500000b0; type CH2_AL3_WRITE_ADDR_t { CH2_AL3_WRITE_ADDR = uint32(0); // @@ -6080,6 +8789,7 @@ // Alias for channel 2 WRITE_ADDR register register CH2_AL3_WRITE_ADDR_t CH2_AL3_WRITE_ADDR at 0x500000b4; + register uint32 CH2_AL3_WRITE_ADDR_raw at 0x500000b4; type CH2_AL3_TRANS_COUNT_t { CH2_AL3_TRANS_COUNT = uint32(0); // @@ -6087,6 +8797,7 @@ // Alias for channel 2 TRANS_COUNT register register CH2_AL3_TRANS_COUNT_t CH2_AL3_TRANS_COUNT at 0x500000b8; + register uint32 CH2_AL3_TRANS_COUNT_raw at 0x500000b8; type CH2_AL3_READ_ADDR_TRIG_t { CH2_AL3_READ_ADDR_TRIG = uint32(0); // @@ -6094,6 +8805,7 @@ // Alias for channel 2 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH2_AL3_READ_ADDR_TRIG_t CH2_AL3_READ_ADDR_TRIG at 0x500000bc; + register uint32 CH2_AL3_READ_ADDR_TRIG_raw at 0x500000bc; type CH3_READ_ADDR_t { CH3_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -6101,6 +8813,7 @@ // DMA Channel 3 Read Address pointer register CH3_READ_ADDR_t CH3_READ_ADDR at 0x500000c0; + register uint32 CH3_READ_ADDR_raw at 0x500000c0; type CH3_WRITE_ADDR_t { CH3_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -6108,6 +8821,7 @@ // DMA Channel 3 Write Address pointer register CH3_WRITE_ADDR_t CH3_WRITE_ADDR at 0x500000c4; + register uint32 CH3_WRITE_ADDR_raw at 0x500000c4; type CH3_TRANS_COUNT_t { CH3_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -6115,6 +8829,65 @@ // DMA Channel 3 Transfer Count register CH3_TRANS_COUNT_t CH3_TRANS_COUNT at 0x500000c8; + register uint32 CH3_TRANS_COUNT_raw at 0x500000c8; + + enum CH3_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH3_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH3_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH3_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -6138,6 +8911,7 @@ // DMA Channel 3 Control and Status register CH3_CTRL_TRIG_t CH3_CTRL_TRIG at 0x500000cc; + register uint32 CH3_CTRL_TRIG_raw at 0x500000cc; type CH3_AL1_CTRL_t { CH3_AL1_CTRL = uint32(0); // @@ -6145,6 +8919,7 @@ // Alias for channel 3 CTRL register register CH3_AL1_CTRL_t CH3_AL1_CTRL at 0x500000d0; + register uint32 CH3_AL1_CTRL_raw at 0x500000d0; type CH3_AL1_READ_ADDR_t { CH3_AL1_READ_ADDR = uint32(0); // @@ -6152,6 +8927,7 @@ // Alias for channel 3 READ_ADDR register register CH3_AL1_READ_ADDR_t CH3_AL1_READ_ADDR at 0x500000d4; + register uint32 CH3_AL1_READ_ADDR_raw at 0x500000d4; type CH3_AL1_WRITE_ADDR_t { CH3_AL1_WRITE_ADDR = uint32(0); // @@ -6159,6 +8935,7 @@ // Alias for channel 3 WRITE_ADDR register register CH3_AL1_WRITE_ADDR_t CH3_AL1_WRITE_ADDR at 0x500000d8; + register uint32 CH3_AL1_WRITE_ADDR_raw at 0x500000d8; type CH3_AL1_TRANS_COUNT_TRIG_t { CH3_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -6166,6 +8943,7 @@ // Alias for channel 3 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH3_AL1_TRANS_COUNT_TRIG_t CH3_AL1_TRANS_COUNT_TRIG at 0x500000dc; + register uint32 CH3_AL1_TRANS_COUNT_TRIG_raw at 0x500000dc; type CH3_AL2_CTRL_t { CH3_AL2_CTRL = uint32(0); // @@ -6173,6 +8951,7 @@ // Alias for channel 3 CTRL register register CH3_AL2_CTRL_t CH3_AL2_CTRL at 0x500000e0; + register uint32 CH3_AL2_CTRL_raw at 0x500000e0; type CH3_AL2_TRANS_COUNT_t { CH3_AL2_TRANS_COUNT = uint32(0); // @@ -6180,6 +8959,7 @@ // Alias for channel 3 TRANS_COUNT register register CH3_AL2_TRANS_COUNT_t CH3_AL2_TRANS_COUNT at 0x500000e4; + register uint32 CH3_AL2_TRANS_COUNT_raw at 0x500000e4; type CH3_AL2_READ_ADDR_t { CH3_AL2_READ_ADDR = uint32(0); // @@ -6187,6 +8967,7 @@ // Alias for channel 3 READ_ADDR register register CH3_AL2_READ_ADDR_t CH3_AL2_READ_ADDR at 0x500000e8; + register uint32 CH3_AL2_READ_ADDR_raw at 0x500000e8; type CH3_AL2_WRITE_ADDR_TRIG_t { CH3_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -6194,6 +8975,7 @@ // Alias for channel 3 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH3_AL2_WRITE_ADDR_TRIG_t CH3_AL2_WRITE_ADDR_TRIG at 0x500000ec; + register uint32 CH3_AL2_WRITE_ADDR_TRIG_raw at 0x500000ec; type CH3_AL3_CTRL_t { CH3_AL3_CTRL = uint32(0); // @@ -6201,6 +8983,7 @@ // Alias for channel 3 CTRL register register CH3_AL3_CTRL_t CH3_AL3_CTRL at 0x500000f0; + register uint32 CH3_AL3_CTRL_raw at 0x500000f0; type CH3_AL3_WRITE_ADDR_t { CH3_AL3_WRITE_ADDR = uint32(0); // @@ -6208,6 +8991,7 @@ // Alias for channel 3 WRITE_ADDR register register CH3_AL3_WRITE_ADDR_t CH3_AL3_WRITE_ADDR at 0x500000f4; + register uint32 CH3_AL3_WRITE_ADDR_raw at 0x500000f4; type CH3_AL3_TRANS_COUNT_t { CH3_AL3_TRANS_COUNT = uint32(0); // @@ -6215,6 +8999,7 @@ // Alias for channel 3 TRANS_COUNT register register CH3_AL3_TRANS_COUNT_t CH3_AL3_TRANS_COUNT at 0x500000f8; + register uint32 CH3_AL3_TRANS_COUNT_raw at 0x500000f8; type CH3_AL3_READ_ADDR_TRIG_t { CH3_AL3_READ_ADDR_TRIG = uint32(0); // @@ -6222,6 +9007,7 @@ // Alias for channel 3 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH3_AL3_READ_ADDR_TRIG_t CH3_AL3_READ_ADDR_TRIG at 0x500000fc; + register uint32 CH3_AL3_READ_ADDR_TRIG_raw at 0x500000fc; type CH4_READ_ADDR_t { CH4_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -6229,6 +9015,7 @@ // DMA Channel 4 Read Address pointer register CH4_READ_ADDR_t CH4_READ_ADDR at 0x50000100; + register uint32 CH4_READ_ADDR_raw at 0x50000100; type CH4_WRITE_ADDR_t { CH4_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -6236,6 +9023,7 @@ // DMA Channel 4 Write Address pointer register CH4_WRITE_ADDR_t CH4_WRITE_ADDR at 0x50000104; + register uint32 CH4_WRITE_ADDR_raw at 0x50000104; type CH4_TRANS_COUNT_t { CH4_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -6243,6 +9031,65 @@ // DMA Channel 4 Transfer Count register CH4_TRANS_COUNT_t CH4_TRANS_COUNT at 0x50000108; + register uint32 CH4_TRANS_COUNT_raw at 0x50000108; + + enum CH4_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH4_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH4_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH4_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -6266,6 +9113,7 @@ // DMA Channel 4 Control and Status register CH4_CTRL_TRIG_t CH4_CTRL_TRIG at 0x5000010c; + register uint32 CH4_CTRL_TRIG_raw at 0x5000010c; type CH4_AL1_CTRL_t { CH4_AL1_CTRL = uint32(0); // @@ -6273,6 +9121,7 @@ // Alias for channel 4 CTRL register register CH4_AL1_CTRL_t CH4_AL1_CTRL at 0x50000110; + register uint32 CH4_AL1_CTRL_raw at 0x50000110; type CH4_AL1_READ_ADDR_t { CH4_AL1_READ_ADDR = uint32(0); // @@ -6280,6 +9129,7 @@ // Alias for channel 4 READ_ADDR register register CH4_AL1_READ_ADDR_t CH4_AL1_READ_ADDR at 0x50000114; + register uint32 CH4_AL1_READ_ADDR_raw at 0x50000114; type CH4_AL1_WRITE_ADDR_t { CH4_AL1_WRITE_ADDR = uint32(0); // @@ -6287,6 +9137,7 @@ // Alias for channel 4 WRITE_ADDR register register CH4_AL1_WRITE_ADDR_t CH4_AL1_WRITE_ADDR at 0x50000118; + register uint32 CH4_AL1_WRITE_ADDR_raw at 0x50000118; type CH4_AL1_TRANS_COUNT_TRIG_t { CH4_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -6294,6 +9145,7 @@ // Alias for channel 4 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH4_AL1_TRANS_COUNT_TRIG_t CH4_AL1_TRANS_COUNT_TRIG at 0x5000011c; + register uint32 CH4_AL1_TRANS_COUNT_TRIG_raw at 0x5000011c; type CH4_AL2_CTRL_t { CH4_AL2_CTRL = uint32(0); // @@ -6301,6 +9153,7 @@ // Alias for channel 4 CTRL register register CH4_AL2_CTRL_t CH4_AL2_CTRL at 0x50000120; + register uint32 CH4_AL2_CTRL_raw at 0x50000120; type CH4_AL2_TRANS_COUNT_t { CH4_AL2_TRANS_COUNT = uint32(0); // @@ -6308,6 +9161,7 @@ // Alias for channel 4 TRANS_COUNT register register CH4_AL2_TRANS_COUNT_t CH4_AL2_TRANS_COUNT at 0x50000124; + register uint32 CH4_AL2_TRANS_COUNT_raw at 0x50000124; type CH4_AL2_READ_ADDR_t { CH4_AL2_READ_ADDR = uint32(0); // @@ -6315,6 +9169,7 @@ // Alias for channel 4 READ_ADDR register register CH4_AL2_READ_ADDR_t CH4_AL2_READ_ADDR at 0x50000128; + register uint32 CH4_AL2_READ_ADDR_raw at 0x50000128; type CH4_AL2_WRITE_ADDR_TRIG_t { CH4_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -6322,6 +9177,7 @@ // Alias for channel 4 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH4_AL2_WRITE_ADDR_TRIG_t CH4_AL2_WRITE_ADDR_TRIG at 0x5000012c; + register uint32 CH4_AL2_WRITE_ADDR_TRIG_raw at 0x5000012c; type CH4_AL3_CTRL_t { CH4_AL3_CTRL = uint32(0); // @@ -6329,6 +9185,7 @@ // Alias for channel 4 CTRL register register CH4_AL3_CTRL_t CH4_AL3_CTRL at 0x50000130; + register uint32 CH4_AL3_CTRL_raw at 0x50000130; type CH4_AL3_WRITE_ADDR_t { CH4_AL3_WRITE_ADDR = uint32(0); // @@ -6336,6 +9193,7 @@ // Alias for channel 4 WRITE_ADDR register register CH4_AL3_WRITE_ADDR_t CH4_AL3_WRITE_ADDR at 0x50000134; + register uint32 CH4_AL3_WRITE_ADDR_raw at 0x50000134; type CH4_AL3_TRANS_COUNT_t { CH4_AL3_TRANS_COUNT = uint32(0); // @@ -6343,6 +9201,7 @@ // Alias for channel 4 TRANS_COUNT register register CH4_AL3_TRANS_COUNT_t CH4_AL3_TRANS_COUNT at 0x50000138; + register uint32 CH4_AL3_TRANS_COUNT_raw at 0x50000138; type CH4_AL3_READ_ADDR_TRIG_t { CH4_AL3_READ_ADDR_TRIG = uint32(0); // @@ -6350,6 +9209,7 @@ // Alias for channel 4 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH4_AL3_READ_ADDR_TRIG_t CH4_AL3_READ_ADDR_TRIG at 0x5000013c; + register uint32 CH4_AL3_READ_ADDR_TRIG_raw at 0x5000013c; type CH5_READ_ADDR_t { CH5_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -6357,6 +9217,7 @@ // DMA Channel 5 Read Address pointer register CH5_READ_ADDR_t CH5_READ_ADDR at 0x50000140; + register uint32 CH5_READ_ADDR_raw at 0x50000140; type CH5_WRITE_ADDR_t { CH5_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -6364,6 +9225,7 @@ // DMA Channel 5 Write Address pointer register CH5_WRITE_ADDR_t CH5_WRITE_ADDR at 0x50000144; + register uint32 CH5_WRITE_ADDR_raw at 0x50000144; type CH5_TRANS_COUNT_t { CH5_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -6371,6 +9233,65 @@ // DMA Channel 5 Transfer Count register CH5_TRANS_COUNT_t CH5_TRANS_COUNT at 0x50000148; + register uint32 CH5_TRANS_COUNT_raw at 0x50000148; + + enum CH5_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH5_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH5_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH5_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -6394,6 +9315,7 @@ // DMA Channel 5 Control and Status register CH5_CTRL_TRIG_t CH5_CTRL_TRIG at 0x5000014c; + register uint32 CH5_CTRL_TRIG_raw at 0x5000014c; type CH5_AL1_CTRL_t { CH5_AL1_CTRL = uint32(0); // @@ -6401,6 +9323,7 @@ // Alias for channel 5 CTRL register register CH5_AL1_CTRL_t CH5_AL1_CTRL at 0x50000150; + register uint32 CH5_AL1_CTRL_raw at 0x50000150; type CH5_AL1_READ_ADDR_t { CH5_AL1_READ_ADDR = uint32(0); // @@ -6408,6 +9331,7 @@ // Alias for channel 5 READ_ADDR register register CH5_AL1_READ_ADDR_t CH5_AL1_READ_ADDR at 0x50000154; + register uint32 CH5_AL1_READ_ADDR_raw at 0x50000154; type CH5_AL1_WRITE_ADDR_t { CH5_AL1_WRITE_ADDR = uint32(0); // @@ -6415,6 +9339,7 @@ // Alias for channel 5 WRITE_ADDR register register CH5_AL1_WRITE_ADDR_t CH5_AL1_WRITE_ADDR at 0x50000158; + register uint32 CH5_AL1_WRITE_ADDR_raw at 0x50000158; type CH5_AL1_TRANS_COUNT_TRIG_t { CH5_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -6422,6 +9347,7 @@ // Alias for channel 5 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH5_AL1_TRANS_COUNT_TRIG_t CH5_AL1_TRANS_COUNT_TRIG at 0x5000015c; + register uint32 CH5_AL1_TRANS_COUNT_TRIG_raw at 0x5000015c; type CH5_AL2_CTRL_t { CH5_AL2_CTRL = uint32(0); // @@ -6429,6 +9355,7 @@ // Alias for channel 5 CTRL register register CH5_AL2_CTRL_t CH5_AL2_CTRL at 0x50000160; + register uint32 CH5_AL2_CTRL_raw at 0x50000160; type CH5_AL2_TRANS_COUNT_t { CH5_AL2_TRANS_COUNT = uint32(0); // @@ -6436,6 +9363,7 @@ // Alias for channel 5 TRANS_COUNT register register CH5_AL2_TRANS_COUNT_t CH5_AL2_TRANS_COUNT at 0x50000164; + register uint32 CH5_AL2_TRANS_COUNT_raw at 0x50000164; type CH5_AL2_READ_ADDR_t { CH5_AL2_READ_ADDR = uint32(0); // @@ -6443,6 +9371,7 @@ // Alias for channel 5 READ_ADDR register register CH5_AL2_READ_ADDR_t CH5_AL2_READ_ADDR at 0x50000168; + register uint32 CH5_AL2_READ_ADDR_raw at 0x50000168; type CH5_AL2_WRITE_ADDR_TRIG_t { CH5_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -6450,6 +9379,7 @@ // Alias for channel 5 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH5_AL2_WRITE_ADDR_TRIG_t CH5_AL2_WRITE_ADDR_TRIG at 0x5000016c; + register uint32 CH5_AL2_WRITE_ADDR_TRIG_raw at 0x5000016c; type CH5_AL3_CTRL_t { CH5_AL3_CTRL = uint32(0); // @@ -6457,6 +9387,7 @@ // Alias for channel 5 CTRL register register CH5_AL3_CTRL_t CH5_AL3_CTRL at 0x50000170; + register uint32 CH5_AL3_CTRL_raw at 0x50000170; type CH5_AL3_WRITE_ADDR_t { CH5_AL3_WRITE_ADDR = uint32(0); // @@ -6464,6 +9395,7 @@ // Alias for channel 5 WRITE_ADDR register register CH5_AL3_WRITE_ADDR_t CH5_AL3_WRITE_ADDR at 0x50000174; + register uint32 CH5_AL3_WRITE_ADDR_raw at 0x50000174; type CH5_AL3_TRANS_COUNT_t { CH5_AL3_TRANS_COUNT = uint32(0); // @@ -6471,6 +9403,7 @@ // Alias for channel 5 TRANS_COUNT register register CH5_AL3_TRANS_COUNT_t CH5_AL3_TRANS_COUNT at 0x50000178; + register uint32 CH5_AL3_TRANS_COUNT_raw at 0x50000178; type CH5_AL3_READ_ADDR_TRIG_t { CH5_AL3_READ_ADDR_TRIG = uint32(0); // @@ -6478,6 +9411,7 @@ // Alias for channel 5 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH5_AL3_READ_ADDR_TRIG_t CH5_AL3_READ_ADDR_TRIG at 0x5000017c; + register uint32 CH5_AL3_READ_ADDR_TRIG_raw at 0x5000017c; type CH6_READ_ADDR_t { CH6_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -6485,6 +9419,7 @@ // DMA Channel 6 Read Address pointer register CH6_READ_ADDR_t CH6_READ_ADDR at 0x50000180; + register uint32 CH6_READ_ADDR_raw at 0x50000180; type CH6_WRITE_ADDR_t { CH6_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -6492,6 +9427,7 @@ // DMA Channel 6 Write Address pointer register CH6_WRITE_ADDR_t CH6_WRITE_ADDR at 0x50000184; + register uint32 CH6_WRITE_ADDR_raw at 0x50000184; type CH6_TRANS_COUNT_t { CH6_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -6499,6 +9435,65 @@ // DMA Channel 6 Transfer Count register CH6_TRANS_COUNT_t CH6_TRANS_COUNT at 0x50000188; + register uint32 CH6_TRANS_COUNT_raw at 0x50000188; + + enum CH6_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH6_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH6_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH6_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -6522,6 +9517,7 @@ // DMA Channel 6 Control and Status register CH6_CTRL_TRIG_t CH6_CTRL_TRIG at 0x5000018c; + register uint32 CH6_CTRL_TRIG_raw at 0x5000018c; type CH6_AL1_CTRL_t { CH6_AL1_CTRL = uint32(0); // @@ -6529,6 +9525,7 @@ // Alias for channel 6 CTRL register register CH6_AL1_CTRL_t CH6_AL1_CTRL at 0x50000190; + register uint32 CH6_AL1_CTRL_raw at 0x50000190; type CH6_AL1_READ_ADDR_t { CH6_AL1_READ_ADDR = uint32(0); // @@ -6536,6 +9533,7 @@ // Alias for channel 6 READ_ADDR register register CH6_AL1_READ_ADDR_t CH6_AL1_READ_ADDR at 0x50000194; + register uint32 CH6_AL1_READ_ADDR_raw at 0x50000194; type CH6_AL1_WRITE_ADDR_t { CH6_AL1_WRITE_ADDR = uint32(0); // @@ -6543,6 +9541,7 @@ // Alias for channel 6 WRITE_ADDR register register CH6_AL1_WRITE_ADDR_t CH6_AL1_WRITE_ADDR at 0x50000198; + register uint32 CH6_AL1_WRITE_ADDR_raw at 0x50000198; type CH6_AL1_TRANS_COUNT_TRIG_t { CH6_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -6550,6 +9549,7 @@ // Alias for channel 6 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH6_AL1_TRANS_COUNT_TRIG_t CH6_AL1_TRANS_COUNT_TRIG at 0x5000019c; + register uint32 CH6_AL1_TRANS_COUNT_TRIG_raw at 0x5000019c; type CH6_AL2_CTRL_t { CH6_AL2_CTRL = uint32(0); // @@ -6557,6 +9557,7 @@ // Alias for channel 6 CTRL register register CH6_AL2_CTRL_t CH6_AL2_CTRL at 0x500001a0; + register uint32 CH6_AL2_CTRL_raw at 0x500001a0; type CH6_AL2_TRANS_COUNT_t { CH6_AL2_TRANS_COUNT = uint32(0); // @@ -6564,6 +9565,7 @@ // Alias for channel 6 TRANS_COUNT register register CH6_AL2_TRANS_COUNT_t CH6_AL2_TRANS_COUNT at 0x500001a4; + register uint32 CH6_AL2_TRANS_COUNT_raw at 0x500001a4; type CH6_AL2_READ_ADDR_t { CH6_AL2_READ_ADDR = uint32(0); // @@ -6571,6 +9573,7 @@ // Alias for channel 6 READ_ADDR register register CH6_AL2_READ_ADDR_t CH6_AL2_READ_ADDR at 0x500001a8; + register uint32 CH6_AL2_READ_ADDR_raw at 0x500001a8; type CH6_AL2_WRITE_ADDR_TRIG_t { CH6_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -6578,6 +9581,7 @@ // Alias for channel 6 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH6_AL2_WRITE_ADDR_TRIG_t CH6_AL2_WRITE_ADDR_TRIG at 0x500001ac; + register uint32 CH6_AL2_WRITE_ADDR_TRIG_raw at 0x500001ac; type CH6_AL3_CTRL_t { CH6_AL3_CTRL = uint32(0); // @@ -6585,6 +9589,7 @@ // Alias for channel 6 CTRL register register CH6_AL3_CTRL_t CH6_AL3_CTRL at 0x500001b0; + register uint32 CH6_AL3_CTRL_raw at 0x500001b0; type CH6_AL3_WRITE_ADDR_t { CH6_AL3_WRITE_ADDR = uint32(0); // @@ -6592,6 +9597,7 @@ // Alias for channel 6 WRITE_ADDR register register CH6_AL3_WRITE_ADDR_t CH6_AL3_WRITE_ADDR at 0x500001b4; + register uint32 CH6_AL3_WRITE_ADDR_raw at 0x500001b4; type CH6_AL3_TRANS_COUNT_t { CH6_AL3_TRANS_COUNT = uint32(0); // @@ -6599,6 +9605,7 @@ // Alias for channel 6 TRANS_COUNT register register CH6_AL3_TRANS_COUNT_t CH6_AL3_TRANS_COUNT at 0x500001b8; + register uint32 CH6_AL3_TRANS_COUNT_raw at 0x500001b8; type CH6_AL3_READ_ADDR_TRIG_t { CH6_AL3_READ_ADDR_TRIG = uint32(0); // @@ -6606,6 +9613,7 @@ // Alias for channel 6 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH6_AL3_READ_ADDR_TRIG_t CH6_AL3_READ_ADDR_TRIG at 0x500001bc; + register uint32 CH6_AL3_READ_ADDR_TRIG_raw at 0x500001bc; type CH7_READ_ADDR_t { CH7_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -6613,6 +9621,7 @@ // DMA Channel 7 Read Address pointer register CH7_READ_ADDR_t CH7_READ_ADDR at 0x500001c0; + register uint32 CH7_READ_ADDR_raw at 0x500001c0; type CH7_WRITE_ADDR_t { CH7_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -6620,6 +9629,7 @@ // DMA Channel 7 Write Address pointer register CH7_WRITE_ADDR_t CH7_WRITE_ADDR at 0x500001c4; + register uint32 CH7_WRITE_ADDR_raw at 0x500001c4; type CH7_TRANS_COUNT_t { CH7_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -6627,6 +9637,65 @@ // DMA Channel 7 Transfer Count register CH7_TRANS_COUNT_t CH7_TRANS_COUNT at 0x500001c8; + register uint32 CH7_TRANS_COUNT_raw at 0x500001c8; + + enum CH7_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH7_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH7_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH7_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -6650,6 +9719,7 @@ // DMA Channel 7 Control and Status register CH7_CTRL_TRIG_t CH7_CTRL_TRIG at 0x500001cc; + register uint32 CH7_CTRL_TRIG_raw at 0x500001cc; type CH7_AL1_CTRL_t { CH7_AL1_CTRL = uint32(0); // @@ -6657,6 +9727,7 @@ // Alias for channel 7 CTRL register register CH7_AL1_CTRL_t CH7_AL1_CTRL at 0x500001d0; + register uint32 CH7_AL1_CTRL_raw at 0x500001d0; type CH7_AL1_READ_ADDR_t { CH7_AL1_READ_ADDR = uint32(0); // @@ -6664,6 +9735,7 @@ // Alias for channel 7 READ_ADDR register register CH7_AL1_READ_ADDR_t CH7_AL1_READ_ADDR at 0x500001d4; + register uint32 CH7_AL1_READ_ADDR_raw at 0x500001d4; type CH7_AL1_WRITE_ADDR_t { CH7_AL1_WRITE_ADDR = uint32(0); // @@ -6671,6 +9743,7 @@ // Alias for channel 7 WRITE_ADDR register register CH7_AL1_WRITE_ADDR_t CH7_AL1_WRITE_ADDR at 0x500001d8; + register uint32 CH7_AL1_WRITE_ADDR_raw at 0x500001d8; type CH7_AL1_TRANS_COUNT_TRIG_t { CH7_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -6678,6 +9751,7 @@ // Alias for channel 7 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH7_AL1_TRANS_COUNT_TRIG_t CH7_AL1_TRANS_COUNT_TRIG at 0x500001dc; + register uint32 CH7_AL1_TRANS_COUNT_TRIG_raw at 0x500001dc; type CH7_AL2_CTRL_t { CH7_AL2_CTRL = uint32(0); // @@ -6685,6 +9759,7 @@ // Alias for channel 7 CTRL register register CH7_AL2_CTRL_t CH7_AL2_CTRL at 0x500001e0; + register uint32 CH7_AL2_CTRL_raw at 0x500001e0; type CH7_AL2_TRANS_COUNT_t { CH7_AL2_TRANS_COUNT = uint32(0); // @@ -6692,6 +9767,7 @@ // Alias for channel 7 TRANS_COUNT register register CH7_AL2_TRANS_COUNT_t CH7_AL2_TRANS_COUNT at 0x500001e4; + register uint32 CH7_AL2_TRANS_COUNT_raw at 0x500001e4; type CH7_AL2_READ_ADDR_t { CH7_AL2_READ_ADDR = uint32(0); // @@ -6699,6 +9775,7 @@ // Alias for channel 7 READ_ADDR register register CH7_AL2_READ_ADDR_t CH7_AL2_READ_ADDR at 0x500001e8; + register uint32 CH7_AL2_READ_ADDR_raw at 0x500001e8; type CH7_AL2_WRITE_ADDR_TRIG_t { CH7_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -6706,6 +9783,7 @@ // Alias for channel 7 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH7_AL2_WRITE_ADDR_TRIG_t CH7_AL2_WRITE_ADDR_TRIG at 0x500001ec; + register uint32 CH7_AL2_WRITE_ADDR_TRIG_raw at 0x500001ec; type CH7_AL3_CTRL_t { CH7_AL3_CTRL = uint32(0); // @@ -6713,6 +9791,7 @@ // Alias for channel 7 CTRL register register CH7_AL3_CTRL_t CH7_AL3_CTRL at 0x500001f0; + register uint32 CH7_AL3_CTRL_raw at 0x500001f0; type CH7_AL3_WRITE_ADDR_t { CH7_AL3_WRITE_ADDR = uint32(0); // @@ -6720,6 +9799,7 @@ // Alias for channel 7 WRITE_ADDR register register CH7_AL3_WRITE_ADDR_t CH7_AL3_WRITE_ADDR at 0x500001f4; + register uint32 CH7_AL3_WRITE_ADDR_raw at 0x500001f4; type CH7_AL3_TRANS_COUNT_t { CH7_AL3_TRANS_COUNT = uint32(0); // @@ -6727,6 +9807,7 @@ // Alias for channel 7 TRANS_COUNT register register CH7_AL3_TRANS_COUNT_t CH7_AL3_TRANS_COUNT at 0x500001f8; + register uint32 CH7_AL3_TRANS_COUNT_raw at 0x500001f8; type CH7_AL3_READ_ADDR_TRIG_t { CH7_AL3_READ_ADDR_TRIG = uint32(0); // @@ -6734,6 +9815,7 @@ // Alias for channel 7 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH7_AL3_READ_ADDR_TRIG_t CH7_AL3_READ_ADDR_TRIG at 0x500001fc; + register uint32 CH7_AL3_READ_ADDR_TRIG_raw at 0x500001fc; type CH8_READ_ADDR_t { CH8_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -6741,6 +9823,7 @@ // DMA Channel 8 Read Address pointer register CH8_READ_ADDR_t CH8_READ_ADDR at 0x50000200; + register uint32 CH8_READ_ADDR_raw at 0x50000200; type CH8_WRITE_ADDR_t { CH8_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -6748,6 +9831,7 @@ // DMA Channel 8 Write Address pointer register CH8_WRITE_ADDR_t CH8_WRITE_ADDR at 0x50000204; + register uint32 CH8_WRITE_ADDR_raw at 0x50000204; type CH8_TRANS_COUNT_t { CH8_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -6755,6 +9839,65 @@ // DMA Channel 8 Transfer Count register CH8_TRANS_COUNT_t CH8_TRANS_COUNT at 0x50000208; + register uint32 CH8_TRANS_COUNT_raw at 0x50000208; + + enum CH8_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH8_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH8_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH8_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -6778,6 +9921,7 @@ // DMA Channel 8 Control and Status register CH8_CTRL_TRIG_t CH8_CTRL_TRIG at 0x5000020c; + register uint32 CH8_CTRL_TRIG_raw at 0x5000020c; type CH8_AL1_CTRL_t { CH8_AL1_CTRL = uint32(0); // @@ -6785,6 +9929,7 @@ // Alias for channel 8 CTRL register register CH8_AL1_CTRL_t CH8_AL1_CTRL at 0x50000210; + register uint32 CH8_AL1_CTRL_raw at 0x50000210; type CH8_AL1_READ_ADDR_t { CH8_AL1_READ_ADDR = uint32(0); // @@ -6792,6 +9937,7 @@ // Alias for channel 8 READ_ADDR register register CH8_AL1_READ_ADDR_t CH8_AL1_READ_ADDR at 0x50000214; + register uint32 CH8_AL1_READ_ADDR_raw at 0x50000214; type CH8_AL1_WRITE_ADDR_t { CH8_AL1_WRITE_ADDR = uint32(0); // @@ -6799,6 +9945,7 @@ // Alias for channel 8 WRITE_ADDR register register CH8_AL1_WRITE_ADDR_t CH8_AL1_WRITE_ADDR at 0x50000218; + register uint32 CH8_AL1_WRITE_ADDR_raw at 0x50000218; type CH8_AL1_TRANS_COUNT_TRIG_t { CH8_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -6806,6 +9953,7 @@ // Alias for channel 8 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH8_AL1_TRANS_COUNT_TRIG_t CH8_AL1_TRANS_COUNT_TRIG at 0x5000021c; + register uint32 CH8_AL1_TRANS_COUNT_TRIG_raw at 0x5000021c; type CH8_AL2_CTRL_t { CH8_AL2_CTRL = uint32(0); // @@ -6813,6 +9961,7 @@ // Alias for channel 8 CTRL register register CH8_AL2_CTRL_t CH8_AL2_CTRL at 0x50000220; + register uint32 CH8_AL2_CTRL_raw at 0x50000220; type CH8_AL2_TRANS_COUNT_t { CH8_AL2_TRANS_COUNT = uint32(0); // @@ -6820,6 +9969,7 @@ // Alias for channel 8 TRANS_COUNT register register CH8_AL2_TRANS_COUNT_t CH8_AL2_TRANS_COUNT at 0x50000224; + register uint32 CH8_AL2_TRANS_COUNT_raw at 0x50000224; type CH8_AL2_READ_ADDR_t { CH8_AL2_READ_ADDR = uint32(0); // @@ -6827,6 +9977,7 @@ // Alias for channel 8 READ_ADDR register register CH8_AL2_READ_ADDR_t CH8_AL2_READ_ADDR at 0x50000228; + register uint32 CH8_AL2_READ_ADDR_raw at 0x50000228; type CH8_AL2_WRITE_ADDR_TRIG_t { CH8_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -6834,6 +9985,7 @@ // Alias for channel 8 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH8_AL2_WRITE_ADDR_TRIG_t CH8_AL2_WRITE_ADDR_TRIG at 0x5000022c; + register uint32 CH8_AL2_WRITE_ADDR_TRIG_raw at 0x5000022c; type CH8_AL3_CTRL_t { CH8_AL3_CTRL = uint32(0); // @@ -6841,6 +9993,7 @@ // Alias for channel 8 CTRL register register CH8_AL3_CTRL_t CH8_AL3_CTRL at 0x50000230; + register uint32 CH8_AL3_CTRL_raw at 0x50000230; type CH8_AL3_WRITE_ADDR_t { CH8_AL3_WRITE_ADDR = uint32(0); // @@ -6848,6 +10001,7 @@ // Alias for channel 8 WRITE_ADDR register register CH8_AL3_WRITE_ADDR_t CH8_AL3_WRITE_ADDR at 0x50000234; + register uint32 CH8_AL3_WRITE_ADDR_raw at 0x50000234; type CH8_AL3_TRANS_COUNT_t { CH8_AL3_TRANS_COUNT = uint32(0); // @@ -6855,6 +10009,7 @@ // Alias for channel 8 TRANS_COUNT register register CH8_AL3_TRANS_COUNT_t CH8_AL3_TRANS_COUNT at 0x50000238; + register uint32 CH8_AL3_TRANS_COUNT_raw at 0x50000238; type CH8_AL3_READ_ADDR_TRIG_t { CH8_AL3_READ_ADDR_TRIG = uint32(0); // @@ -6862,6 +10017,7 @@ // Alias for channel 8 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH8_AL3_READ_ADDR_TRIG_t CH8_AL3_READ_ADDR_TRIG at 0x5000023c; + register uint32 CH8_AL3_READ_ADDR_TRIG_raw at 0x5000023c; type CH9_READ_ADDR_t { CH9_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -6869,6 +10025,7 @@ // DMA Channel 9 Read Address pointer register CH9_READ_ADDR_t CH9_READ_ADDR at 0x50000240; + register uint32 CH9_READ_ADDR_raw at 0x50000240; type CH9_WRITE_ADDR_t { CH9_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -6876,6 +10033,7 @@ // DMA Channel 9 Write Address pointer register CH9_WRITE_ADDR_t CH9_WRITE_ADDR at 0x50000244; + register uint32 CH9_WRITE_ADDR_raw at 0x50000244; type CH9_TRANS_COUNT_t { CH9_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -6883,6 +10041,65 @@ // DMA Channel 9 Transfer Count register CH9_TRANS_COUNT_t CH9_TRANS_COUNT at 0x50000248; + register uint32 CH9_TRANS_COUNT_raw at 0x50000248; + + enum CH9_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH9_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH9_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH9_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -6906,6 +10123,7 @@ // DMA Channel 9 Control and Status register CH9_CTRL_TRIG_t CH9_CTRL_TRIG at 0x5000024c; + register uint32 CH9_CTRL_TRIG_raw at 0x5000024c; type CH9_AL1_CTRL_t { CH9_AL1_CTRL = uint32(0); // @@ -6913,6 +10131,7 @@ // Alias for channel 9 CTRL register register CH9_AL1_CTRL_t CH9_AL1_CTRL at 0x50000250; + register uint32 CH9_AL1_CTRL_raw at 0x50000250; type CH9_AL1_READ_ADDR_t { CH9_AL1_READ_ADDR = uint32(0); // @@ -6920,6 +10139,7 @@ // Alias for channel 9 READ_ADDR register register CH9_AL1_READ_ADDR_t CH9_AL1_READ_ADDR at 0x50000254; + register uint32 CH9_AL1_READ_ADDR_raw at 0x50000254; type CH9_AL1_WRITE_ADDR_t { CH9_AL1_WRITE_ADDR = uint32(0); // @@ -6927,6 +10147,7 @@ // Alias for channel 9 WRITE_ADDR register register CH9_AL1_WRITE_ADDR_t CH9_AL1_WRITE_ADDR at 0x50000258; + register uint32 CH9_AL1_WRITE_ADDR_raw at 0x50000258; type CH9_AL1_TRANS_COUNT_TRIG_t { CH9_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -6934,6 +10155,7 @@ // Alias for channel 9 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH9_AL1_TRANS_COUNT_TRIG_t CH9_AL1_TRANS_COUNT_TRIG at 0x5000025c; + register uint32 CH9_AL1_TRANS_COUNT_TRIG_raw at 0x5000025c; type CH9_AL2_CTRL_t { CH9_AL2_CTRL = uint32(0); // @@ -6941,6 +10163,7 @@ // Alias for channel 9 CTRL register register CH9_AL2_CTRL_t CH9_AL2_CTRL at 0x50000260; + register uint32 CH9_AL2_CTRL_raw at 0x50000260; type CH9_AL2_TRANS_COUNT_t { CH9_AL2_TRANS_COUNT = uint32(0); // @@ -6948,6 +10171,7 @@ // Alias for channel 9 TRANS_COUNT register register CH9_AL2_TRANS_COUNT_t CH9_AL2_TRANS_COUNT at 0x50000264; + register uint32 CH9_AL2_TRANS_COUNT_raw at 0x50000264; type CH9_AL2_READ_ADDR_t { CH9_AL2_READ_ADDR = uint32(0); // @@ -6955,6 +10179,7 @@ // Alias for channel 9 READ_ADDR register register CH9_AL2_READ_ADDR_t CH9_AL2_READ_ADDR at 0x50000268; + register uint32 CH9_AL2_READ_ADDR_raw at 0x50000268; type CH9_AL2_WRITE_ADDR_TRIG_t { CH9_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -6962,6 +10187,7 @@ // Alias for channel 9 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH9_AL2_WRITE_ADDR_TRIG_t CH9_AL2_WRITE_ADDR_TRIG at 0x5000026c; + register uint32 CH9_AL2_WRITE_ADDR_TRIG_raw at 0x5000026c; type CH9_AL3_CTRL_t { CH9_AL3_CTRL = uint32(0); // @@ -6969,6 +10195,7 @@ // Alias for channel 9 CTRL register register CH9_AL3_CTRL_t CH9_AL3_CTRL at 0x50000270; + register uint32 CH9_AL3_CTRL_raw at 0x50000270; type CH9_AL3_WRITE_ADDR_t { CH9_AL3_WRITE_ADDR = uint32(0); // @@ -6976,6 +10203,7 @@ // Alias for channel 9 WRITE_ADDR register register CH9_AL3_WRITE_ADDR_t CH9_AL3_WRITE_ADDR at 0x50000274; + register uint32 CH9_AL3_WRITE_ADDR_raw at 0x50000274; type CH9_AL3_TRANS_COUNT_t { CH9_AL3_TRANS_COUNT = uint32(0); // @@ -6983,6 +10211,7 @@ // Alias for channel 9 TRANS_COUNT register register CH9_AL3_TRANS_COUNT_t CH9_AL3_TRANS_COUNT at 0x50000278; + register uint32 CH9_AL3_TRANS_COUNT_raw at 0x50000278; type CH9_AL3_READ_ADDR_TRIG_t { CH9_AL3_READ_ADDR_TRIG = uint32(0); // @@ -6990,6 +10219,7 @@ // Alias for channel 9 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH9_AL3_READ_ADDR_TRIG_t CH9_AL3_READ_ADDR_TRIG at 0x5000027c; + register uint32 CH9_AL3_READ_ADDR_TRIG_raw at 0x5000027c; type CH10_READ_ADDR_t { CH10_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -6997,6 +10227,7 @@ // DMA Channel 10 Read Address pointer register CH10_READ_ADDR_t CH10_READ_ADDR at 0x50000280; + register uint32 CH10_READ_ADDR_raw at 0x50000280; type CH10_WRITE_ADDR_t { CH10_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -7004,6 +10235,7 @@ // DMA Channel 10 Write Address pointer register CH10_WRITE_ADDR_t CH10_WRITE_ADDR at 0x50000284; + register uint32 CH10_WRITE_ADDR_raw at 0x50000284; type CH10_TRANS_COUNT_t { CH10_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -7011,6 +10243,65 @@ // DMA Channel 10 Transfer Count register CH10_TRANS_COUNT_t CH10_TRANS_COUNT at 0x50000288; + register uint32 CH10_TRANS_COUNT_raw at 0x50000288; + + enum CH10_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH10_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH10_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH10_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -7034,6 +10325,7 @@ // DMA Channel 10 Control and Status register CH10_CTRL_TRIG_t CH10_CTRL_TRIG at 0x5000028c; + register uint32 CH10_CTRL_TRIG_raw at 0x5000028c; type CH10_AL1_CTRL_t { CH10_AL1_CTRL = uint32(0); // @@ -7041,6 +10333,7 @@ // Alias for channel 10 CTRL register register CH10_AL1_CTRL_t CH10_AL1_CTRL at 0x50000290; + register uint32 CH10_AL1_CTRL_raw at 0x50000290; type CH10_AL1_READ_ADDR_t { CH10_AL1_READ_ADDR = uint32(0); // @@ -7048,6 +10341,7 @@ // Alias for channel 10 READ_ADDR register register CH10_AL1_READ_ADDR_t CH10_AL1_READ_ADDR at 0x50000294; + register uint32 CH10_AL1_READ_ADDR_raw at 0x50000294; type CH10_AL1_WRITE_ADDR_t { CH10_AL1_WRITE_ADDR = uint32(0); // @@ -7055,6 +10349,7 @@ // Alias for channel 10 WRITE_ADDR register register CH10_AL1_WRITE_ADDR_t CH10_AL1_WRITE_ADDR at 0x50000298; + register uint32 CH10_AL1_WRITE_ADDR_raw at 0x50000298; type CH10_AL1_TRANS_COUNT_TRIG_t { CH10_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -7062,6 +10357,7 @@ // Alias for channel 10 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH10_AL1_TRANS_COUNT_TRIG_t CH10_AL1_TRANS_COUNT_TRIG at 0x5000029c; + register uint32 CH10_AL1_TRANS_COUNT_TRIG_raw at 0x5000029c; type CH10_AL2_CTRL_t { CH10_AL2_CTRL = uint32(0); // @@ -7069,6 +10365,7 @@ // Alias for channel 10 CTRL register register CH10_AL2_CTRL_t CH10_AL2_CTRL at 0x500002a0; + register uint32 CH10_AL2_CTRL_raw at 0x500002a0; type CH10_AL2_TRANS_COUNT_t { CH10_AL2_TRANS_COUNT = uint32(0); // @@ -7076,6 +10373,7 @@ // Alias for channel 10 TRANS_COUNT register register CH10_AL2_TRANS_COUNT_t CH10_AL2_TRANS_COUNT at 0x500002a4; + register uint32 CH10_AL2_TRANS_COUNT_raw at 0x500002a4; type CH10_AL2_READ_ADDR_t { CH10_AL2_READ_ADDR = uint32(0); // @@ -7083,6 +10381,7 @@ // Alias for channel 10 READ_ADDR register register CH10_AL2_READ_ADDR_t CH10_AL2_READ_ADDR at 0x500002a8; + register uint32 CH10_AL2_READ_ADDR_raw at 0x500002a8; type CH10_AL2_WRITE_ADDR_TRIG_t { CH10_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -7090,6 +10389,7 @@ // Alias for channel 10 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH10_AL2_WRITE_ADDR_TRIG_t CH10_AL2_WRITE_ADDR_TRIG at 0x500002ac; + register uint32 CH10_AL2_WRITE_ADDR_TRIG_raw at 0x500002ac; type CH10_AL3_CTRL_t { CH10_AL3_CTRL = uint32(0); // @@ -7097,6 +10397,7 @@ // Alias for channel 10 CTRL register register CH10_AL3_CTRL_t CH10_AL3_CTRL at 0x500002b0; + register uint32 CH10_AL3_CTRL_raw at 0x500002b0; type CH10_AL3_WRITE_ADDR_t { CH10_AL3_WRITE_ADDR = uint32(0); // @@ -7104,6 +10405,7 @@ // Alias for channel 10 WRITE_ADDR register register CH10_AL3_WRITE_ADDR_t CH10_AL3_WRITE_ADDR at 0x500002b4; + register uint32 CH10_AL3_WRITE_ADDR_raw at 0x500002b4; type CH10_AL3_TRANS_COUNT_t { CH10_AL3_TRANS_COUNT = uint32(0); // @@ -7111,6 +10413,7 @@ // Alias for channel 10 TRANS_COUNT register register CH10_AL3_TRANS_COUNT_t CH10_AL3_TRANS_COUNT at 0x500002b8; + register uint32 CH10_AL3_TRANS_COUNT_raw at 0x500002b8; type CH10_AL3_READ_ADDR_TRIG_t { CH10_AL3_READ_ADDR_TRIG = uint32(0); // @@ -7118,6 +10421,7 @@ // Alias for channel 10 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH10_AL3_READ_ADDR_TRIG_t CH10_AL3_READ_ADDR_TRIG at 0x500002bc; + register uint32 CH10_AL3_READ_ADDR_TRIG_raw at 0x500002bc; type CH11_READ_ADDR_t { CH11_READ_ADDR = uint32(0); // This register updates automatically each time a read completes. The current value is the next address to be read by this channel. @@ -7125,6 +10429,7 @@ // DMA Channel 11 Read Address pointer register CH11_READ_ADDR_t CH11_READ_ADDR at 0x500002c0; + register uint32 CH11_READ_ADDR_raw at 0x500002c0; type CH11_WRITE_ADDR_t { CH11_WRITE_ADDR = uint32(0); // This register updates automatically each time a write completes. The current value is the next address to be written by this channel. @@ -7132,6 +10437,7 @@ // DMA Channel 11 Write Address pointer register CH11_WRITE_ADDR_t CH11_WRITE_ADDR at 0x500002c4; + register uint32 CH11_WRITE_ADDR_raw at 0x500002c4; type CH11_TRANS_COUNT_t { CH11_TRANS_COUNT = uint32(0); // Program the number of bus transfers a channel will perform before halting. Note that, if transfers are larger than one byte in size, this is not equal to the number of bytes transferred (see CTRL_DATA_SIZE). When the channel is active, reading this register shows the number of transfers remaining, updating automatically each time a write transfer completes. Writing this register sets the RELOAD value for the transfer counter. Each time this channel is triggered, the RELOAD value is copied into the live transfer counter. The channel can be started multiple times, and will perform the same number of transfers each time, as programmed by most recent write. The RELOAD value can be observed at CHx_DBG_TCR. If TRANS_COUNT is used as a trigger, the written value is used immediately as the length of the new transfer sequence, as well as being written to RELOAD. @@ -7139,6 +10445,65 @@ // DMA Channel 11 Transfer Count register CH11_TRANS_COUNT_t CH11_TRANS_COUNT at 0x500002c8; + register uint32 CH11_TRANS_COUNT_raw at 0x500002c8; + + enum CH11_CTRL_TRIG_TREQ_SEL { + PIO0_TX0 = 0, // Select PIO0's TX FIFO 0 as TREQ + PIO0_TX1 = 1, // Select PIO0's TX FIFO 1 as TREQ + PIO0_TX2 = 2, // Select PIO0's TX FIFO 2 as TREQ + PIO0_TX3 = 3, // Select PIO0's TX FIFO 3 as TREQ + PIO0_RX0 = 4, // Select PIO0's RX FIFO 0 as TREQ + PIO0_RX1 = 5, // Select PIO0's RX FIFO 1 as TREQ + PIO0_RX2 = 6, // Select PIO0's RX FIFO 2 as TREQ + PIO0_RX3 = 7, // Select PIO0's RX FIFO 3 as TREQ + PIO1_TX0 = 8, // Select PIO1's TX FIFO 0 as TREQ + PIO1_TX1 = 9, // Select PIO1's TX FIFO 1 as TREQ + PIO1_TX2 = 10, // Select PIO1's TX FIFO 2 as TREQ + PIO1_TX3 = 11, // Select PIO1's TX FIFO 3 as TREQ + PIO1_RX0 = 12, // Select PIO1's RX FIFO 0 as TREQ + PIO1_RX1 = 13, // Select PIO1's RX FIFO 1 as TREQ + PIO1_RX2 = 14, // Select PIO1's RX FIFO 2 as TREQ + PIO1_RX3 = 15, // Select PIO1's RX FIFO 3 as TREQ + SPI0_TX = 16, // Select SPI0's TX FIFO as TREQ + SPI0_RX = 17, // Select SPI0's RX FIFO as TREQ + SPI1_TX = 18, // Select SPI1's TX FIFO as TREQ + SPI1_RX = 19, // Select SPI1's RX FIFO as TREQ + UART0_TX = 20, // Select UART0's TX FIFO as TREQ + UART0_RX = 21, // Select UART0's RX FIFO as TREQ + UART1_TX = 22, // Select UART1's TX FIFO as TREQ + UART1_RX = 23, // Select UART1's RX FIFO as TREQ + PWM_WRAP0 = 24, // Select PWM Counter 0's Wrap Value as TREQ + PWM_WRAP1 = 25, // Select PWM Counter 1's Wrap Value as TREQ + PWM_WRAP2 = 26, // Select PWM Counter 2's Wrap Value as TREQ + PWM_WRAP3 = 27, // Select PWM Counter 3's Wrap Value as TREQ + PWM_WRAP4 = 28, // Select PWM Counter 4's Wrap Value as TREQ + PWM_WRAP5 = 29, // Select PWM Counter 5's Wrap Value as TREQ + PWM_WRAP6 = 30, // Select PWM Counter 6's Wrap Value as TREQ + PWM_WRAP7 = 31, // Select PWM Counter 7's Wrap Value as TREQ + I2C0_TX = 32, // Select I2C0's TX FIFO as TREQ + I2C0_RX = 33, // Select I2C0's RX FIFO as TREQ + I2C1_TX = 34, // Select I2C1's TX FIFO as TREQ + I2C1_RX = 35, // Select I2C1's RX FIFO as TREQ + ADC = 36, // Select the ADC as TREQ + XIP_STREAM = 37, // Select the XIP Streaming FIFO as TREQ + XIP_SSITX = 38, // Select the XIP SSI TX FIFO as TREQ + XIP_SSIRX = 39, // Select the XIP SSI RX FIFO as TREQ + TIMER0 = 59, // Select Timer 0 as TREQ + TIMER1 = 60, // Select Timer 1 as TREQ + TIMER2 = 61, // Select Timer 2 as TREQ (Optional) + TIMER3 = 62, // Select Timer 3 as TREQ (Optional) + PERMANENT = 63 // Permanent request, for unpaced transfers. + } + + enum CH11_CTRL_TRIG_RING_SIZE { + RING_NONE = 0 // + } + + enum CH11_CTRL_TRIG_DATA_SIZE { + SIZE_BYTE = 0, // + SIZE_HALFWORD = 1, // + SIZE_WORD = 2 // + } type CH11_CTRL_TRIG_t { EN = false; // DMA Channel Enable. When 1, the channel will respond to triggering events, which will cause it to become BUSY and start transferring data. When 0, the channel will ignore triggers, stop issuing transfers, and pause the current transfer sequence (i.e. BUSY will remain high if already high) @@ -7162,6 +10527,7 @@ // DMA Channel 11 Control and Status register CH11_CTRL_TRIG_t CH11_CTRL_TRIG at 0x500002cc; + register uint32 CH11_CTRL_TRIG_raw at 0x500002cc; type CH11_AL1_CTRL_t { CH11_AL1_CTRL = uint32(0); // @@ -7169,6 +10535,7 @@ // Alias for channel 11 CTRL register register CH11_AL1_CTRL_t CH11_AL1_CTRL at 0x500002d0; + register uint32 CH11_AL1_CTRL_raw at 0x500002d0; type CH11_AL1_READ_ADDR_t { CH11_AL1_READ_ADDR = uint32(0); // @@ -7176,6 +10543,7 @@ // Alias for channel 11 READ_ADDR register register CH11_AL1_READ_ADDR_t CH11_AL1_READ_ADDR at 0x500002d4; + register uint32 CH11_AL1_READ_ADDR_raw at 0x500002d4; type CH11_AL1_WRITE_ADDR_t { CH11_AL1_WRITE_ADDR = uint32(0); // @@ -7183,6 +10551,7 @@ // Alias for channel 11 WRITE_ADDR register register CH11_AL1_WRITE_ADDR_t CH11_AL1_WRITE_ADDR at 0x500002d8; + register uint32 CH11_AL1_WRITE_ADDR_raw at 0x500002d8; type CH11_AL1_TRANS_COUNT_TRIG_t { CH11_AL1_TRANS_COUNT_TRIG = uint32(0); // @@ -7190,6 +10559,7 @@ // Alias for channel 11 TRANS_COUNT register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH11_AL1_TRANS_COUNT_TRIG_t CH11_AL1_TRANS_COUNT_TRIG at 0x500002dc; + register uint32 CH11_AL1_TRANS_COUNT_TRIG_raw at 0x500002dc; type CH11_AL2_CTRL_t { CH11_AL2_CTRL = uint32(0); // @@ -7197,6 +10567,7 @@ // Alias for channel 11 CTRL register register CH11_AL2_CTRL_t CH11_AL2_CTRL at 0x500002e0; + register uint32 CH11_AL2_CTRL_raw at 0x500002e0; type CH11_AL2_TRANS_COUNT_t { CH11_AL2_TRANS_COUNT = uint32(0); // @@ -7204,6 +10575,7 @@ // Alias for channel 11 TRANS_COUNT register register CH11_AL2_TRANS_COUNT_t CH11_AL2_TRANS_COUNT at 0x500002e4; + register uint32 CH11_AL2_TRANS_COUNT_raw at 0x500002e4; type CH11_AL2_READ_ADDR_t { CH11_AL2_READ_ADDR = uint32(0); // @@ -7211,6 +10583,7 @@ // Alias for channel 11 READ_ADDR register register CH11_AL2_READ_ADDR_t CH11_AL2_READ_ADDR at 0x500002e8; + register uint32 CH11_AL2_READ_ADDR_raw at 0x500002e8; type CH11_AL2_WRITE_ADDR_TRIG_t { CH11_AL2_WRITE_ADDR_TRIG = uint32(0); // @@ -7218,6 +10591,7 @@ // Alias for channel 11 WRITE_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH11_AL2_WRITE_ADDR_TRIG_t CH11_AL2_WRITE_ADDR_TRIG at 0x500002ec; + register uint32 CH11_AL2_WRITE_ADDR_TRIG_raw at 0x500002ec; type CH11_AL3_CTRL_t { CH11_AL3_CTRL = uint32(0); // @@ -7225,6 +10599,7 @@ // Alias for channel 11 CTRL register register CH11_AL3_CTRL_t CH11_AL3_CTRL at 0x500002f0; + register uint32 CH11_AL3_CTRL_raw at 0x500002f0; type CH11_AL3_WRITE_ADDR_t { CH11_AL3_WRITE_ADDR = uint32(0); // @@ -7232,6 +10607,7 @@ // Alias for channel 11 WRITE_ADDR register register CH11_AL3_WRITE_ADDR_t CH11_AL3_WRITE_ADDR at 0x500002f4; + register uint32 CH11_AL3_WRITE_ADDR_raw at 0x500002f4; type CH11_AL3_TRANS_COUNT_t { CH11_AL3_TRANS_COUNT = uint32(0); // @@ -7239,6 +10615,7 @@ // Alias for channel 11 TRANS_COUNT register register CH11_AL3_TRANS_COUNT_t CH11_AL3_TRANS_COUNT at 0x500002f8; + register uint32 CH11_AL3_TRANS_COUNT_raw at 0x500002f8; type CH11_AL3_READ_ADDR_TRIG_t { CH11_AL3_READ_ADDR_TRIG = uint32(0); // @@ -7246,62 +10623,79 @@ // Alias for channel 11 READ_ADDR register This is a trigger register (0xc). Writing a nonzero value will reload the channel counter and start the channel. register CH11_AL3_READ_ADDR_TRIG_t CH11_AL3_READ_ADDR_TRIG at 0x500002fc; + register uint32 CH11_AL3_READ_ADDR_TRIG_raw at 0x500002fc; type DMA_INTR_t { - INTR = uint16(0); // Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + INTR = uint16(0); // Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + _res1 = uint16(0); // Reserved, 16 bits } // Interrupt Status (raw) register DMA_INTR_t DMA_INTR at 0x50000400; + register uint32 DMA_INTR_raw at 0x50000400; type INTE0_t { INTE0 = uint16(0); // Set bit n to pass interrupts from channel n to DMA IRQ 0. + _res1 = uint16(0); // Reserved, 16 bits } // Interrupt Enables for IRQ 0 register INTE0_t INTE0 at 0x50000404; + register uint32 INTE0_raw at 0x50000404; type INTF0_t { INTF0 = uint16(0); // Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + _res1 = uint16(0); // Reserved, 16 bits } // Force Interrupts register INTF0_t INTF0 at 0x50000408; + register uint32 INTF0_raw at 0x50000408; type INTS0_t { INTS0 = uint16(0); // Indicates active channel interrupt requests which are currently causing IRQ 0 to be asserted. Channel interrupts can be cleared by writing a bit mask here. + _res1 = uint16(0); // Reserved, 16 bits } // Interrupt Status for IRQ 0 register INTS0_t INTS0 at 0x5000040c; + register uint32 INTS0_raw at 0x5000040c; type DMA_INTR1_t { INTR1 = uint16(0); // Raw interrupt status for DMA Channels 0..15. Bit n corresponds to channel n. Ignores any masking or forcing. Channel interrupts can be cleared by writing a bit mask to INTR, INTS0 or INTS1. Channel interrupts can be routed to either of two system-level IRQs based on INTE0 and INTE1. This can be used vector different channel interrupts to different ISRs: this might be done to allow NVIC IRQ preemption for more time-critical channels, or to spread IRQ load across different cores. It is also valid to ignore this behaviour and just use INTE0/INTS0/IRQ 0. + _res1 = uint16(0); // Reserved, 16 bits } // Interrupt Status (raw) register DMA_INTR1_t DMA_INTR1 at 0x50000410; + register uint32 DMA_INTR1_raw at 0x50000410; type INTE1_t { INTE1 = uint16(0); // Set bit n to pass interrupts from channel n to DMA IRQ 1. + _res1 = uint16(0); // Reserved, 16 bits } // Interrupt Enables for IRQ 1 register INTE1_t INTE1 at 0x50000414; + register uint32 INTE1_raw at 0x50000414; type INTF1_t { INTF1 = uint16(0); // Write 1s to force the corresponding bits in INTE0. The interrupt remains asserted until INTF0 is cleared. + _res1 = uint16(0); // Reserved, 16 bits } // Force Interrupts for IRQ 1 register INTF1_t INTF1 at 0x50000418; + register uint32 INTF1_raw at 0x50000418; type INTS1_t { INTS1 = uint16(0); // Indicates active channel interrupt requests which are currently causing IRQ 1 to be asserted. Channel interrupts can be cleared by writing a bit mask here. + _res1 = uint16(0); // Reserved, 16 bits } // Interrupt Status (masked) for IRQ 1 register INTS1_t INTS1 at 0x5000041c; + register uint32 INTS1_raw at 0x5000041c; type TIMER0_t { Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. @@ -7310,6 +10704,7 @@ // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. register TIMER0_t TIMER0 at 0x50000420; + register uint32 TIMER0_raw at 0x50000420; type TIMER1_t { Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. @@ -7318,6 +10713,7 @@ // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. register TIMER1_t TIMER1 at 0x50000424; + register uint32 TIMER1_raw at 0x50000424; type TIMER2_t { Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. @@ -7326,6 +10722,7 @@ // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. register TIMER2_t TIMER2 at 0x50000428; + register uint32 TIMER2_raw at 0x50000428; type TIMER3_t { Y = uint16(0); // Pacing Timer Divisor. Specifies the Y value for the (X/Y) fractional timer. @@ -7334,13 +10731,25 @@ // Pacing (X/Y) Fractional Timer The pacing timer produces TREQ assertions at a rate set by ((X/Y) * sys_clk). This equation is evaluated every sys_clk cycles and therefore can only generate TREQs at a rate of 1 per sys_clk (i.e. permanent TREQ) or less. register TIMER3_t TIMER3 at 0x5000042c; + register uint32 TIMER3_raw at 0x5000042c; type MULTI_CHAN_TRIGGER_t { MULTI_CHAN_TRIGGER = uint16(0); // Each bit in this register corresponds to a DMA channel. Writing a 1 to the relevant bit is the same as writing to that channel's trigger register; the channel will start if it is currently enabled and not already busy. + _res1 = uint16(0); // Reserved, 16 bits } // Trigger one or more channels simultaneously register MULTI_CHAN_TRIGGER_t MULTI_CHAN_TRIGGER at 0x50000430; + register uint32 MULTI_CHAN_TRIGGER_raw at 0x50000430; + + enum SNIFF_CTRL_CALC { + CRC32 = 0, // Calculate a CRC-32 (IEEE802.3 polynomial) + CRC32R = 1, // Calculate a CRC-32 (IEEE802.3 polynomial) with bit reversed data + CRC16 = 2, // Calculate a CRC-16-CCITT + CRC16R = 3, // Calculate a CRC-16-CCITT with bit reversed data + EVEN = 14, // XOR reduction over all data. == 1 if the total 1 population count is odd. + SUM = 15 // Calculate a simple 32-bit checksum (addition with a 32 bit accumulator) + } type SNIFF_CTRL_t { EN = false; // Enable sniffer @@ -7349,10 +10758,12 @@ BSWAP = false; // Locally perform a byte reverse on the sniffed data, before feeding into checksum. Note that the sniff hardware is downstream of the DMA channel byteswap performed in the read master: if channel CTRL_BSWAP and SNIFF_CTRL_BSWAP are both enabled, their effects cancel from the sniffer's point of view. OUT_REV = false; // If set, the result appears bit-reversed when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. OUT_INV = false; // If set, the result appears inverted (bitwise complement) when read. This does not affect the way the checksum is calculated; the result is transformed on-the-fly between the result register and the bus. + _res1 = uint20(0); // Reserved, 20 bits } // Sniffer Control register SNIFF_CTRL_t SNIFF_CTRL at 0x50000434; + register uint32 SNIFF_CTRL_raw at 0x50000434; type SNIFF_DATA_t { SNIFF_DATA = uint32(0); // Write an initial seed value here before starting a DMA transfer on the channel indicated by SNIFF_CTRL_DMACH. The hardware will update this register each time it observes a read from the indicated channel. Once the channel completes, the final result can be read from this register. @@ -7360,36 +10771,45 @@ // Data accumulator for sniff hardware register SNIFF_DATA_t SNIFF_DATA at 0x50000438; + register uint32 SNIFF_DATA_raw at 0x50000438; type FIFO_LEVELS_t { TDF_LVL = uint8(0); // Current Transfer-Data-FIFO fill level WAF_LVL = uint8(0); // Current Write-Address-FIFO fill level RAF_LVL = uint8(0); // Current Read-Address-FIFO fill level + _res1 = uint8(0); // Reserved, 8 bits } // Debug RAF, WAF, TDF levels register FIFO_LEVELS_t FIFO_LEVELS at 0x50000440; + register uint32 FIFO_LEVELS_raw at 0x50000440; type CHAN_ABORT_t { CHAN_ABORT = uint16(0); // Each bit corresponds to a channel. Writing a 1 aborts whatever transfer sequence is in progress on that channel. The bit will remain high until any in-flight transfers have been flushed through the address and data FIFOs. After writing, this register must be polled until it returns all-zero. Until this point, it is unsafe to restart the channel. + _res1 = uint16(0); // Reserved, 16 bits } // Abort an in-progress transfer sequence on one or more channels register CHAN_ABORT_t CHAN_ABORT at 0x50000444; + register uint32 CHAN_ABORT_raw at 0x50000444; type N_CHANNELS_t { N_CHANNELS = uint5(0); // + _res1 = uint27(0); // Reserved, 27 bits } // The number of channels this DMA instance is equipped with. This DMA supports up to 16 hardware channels, but can be configured with as few as one, to minimise silicon area. register N_CHANNELS_t N_CHANNELS at 0x50000448; + register uint32 N_CHANNELS_raw at 0x50000448; type CH0_DBG_CTDREQ_t { CH0_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH0_DBG_CTDREQ_t CH0_DBG_CTDREQ at 0x50000800; + register uint32 CH0_DBG_CTDREQ_raw at 0x50000800; type CH0_DBG_TCR_t { CH0_DBG_TCR = uint32(0); // @@ -7397,13 +10817,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH0_DBG_TCR_t CH0_DBG_TCR at 0x50000804; + register uint32 CH0_DBG_TCR_raw at 0x50000804; type CH1_DBG_CTDREQ_t { CH1_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH1_DBG_CTDREQ_t CH1_DBG_CTDREQ at 0x50000840; + register uint32 CH1_DBG_CTDREQ_raw at 0x50000840; type CH1_DBG_TCR_t { CH1_DBG_TCR = uint32(0); // @@ -7411,13 +10834,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH1_DBG_TCR_t CH1_DBG_TCR at 0x50000844; + register uint32 CH1_DBG_TCR_raw at 0x50000844; type CH2_DBG_CTDREQ_t { CH2_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH2_DBG_CTDREQ_t CH2_DBG_CTDREQ at 0x50000880; + register uint32 CH2_DBG_CTDREQ_raw at 0x50000880; type CH2_DBG_TCR_t { CH2_DBG_TCR = uint32(0); // @@ -7425,13 +10851,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH2_DBG_TCR_t CH2_DBG_TCR at 0x50000884; + register uint32 CH2_DBG_TCR_raw at 0x50000884; type CH3_DBG_CTDREQ_t { CH3_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH3_DBG_CTDREQ_t CH3_DBG_CTDREQ at 0x500008c0; + register uint32 CH3_DBG_CTDREQ_raw at 0x500008c0; type CH3_DBG_TCR_t { CH3_DBG_TCR = uint32(0); // @@ -7439,13 +10868,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH3_DBG_TCR_t CH3_DBG_TCR at 0x500008c4; + register uint32 CH3_DBG_TCR_raw at 0x500008c4; type CH4_DBG_CTDREQ_t { CH4_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH4_DBG_CTDREQ_t CH4_DBG_CTDREQ at 0x50000900; + register uint32 CH4_DBG_CTDREQ_raw at 0x50000900; type CH4_DBG_TCR_t { CH4_DBG_TCR = uint32(0); // @@ -7453,13 +10885,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH4_DBG_TCR_t CH4_DBG_TCR at 0x50000904; + register uint32 CH4_DBG_TCR_raw at 0x50000904; type CH5_DBG_CTDREQ_t { CH5_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH5_DBG_CTDREQ_t CH5_DBG_CTDREQ at 0x50000940; + register uint32 CH5_DBG_CTDREQ_raw at 0x50000940; type CH5_DBG_TCR_t { CH5_DBG_TCR = uint32(0); // @@ -7467,13 +10902,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH5_DBG_TCR_t CH5_DBG_TCR at 0x50000944; + register uint32 CH5_DBG_TCR_raw at 0x50000944; type CH6_DBG_CTDREQ_t { CH6_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH6_DBG_CTDREQ_t CH6_DBG_CTDREQ at 0x50000980; + register uint32 CH6_DBG_CTDREQ_raw at 0x50000980; type CH6_DBG_TCR_t { CH6_DBG_TCR = uint32(0); // @@ -7481,13 +10919,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH6_DBG_TCR_t CH6_DBG_TCR at 0x50000984; + register uint32 CH6_DBG_TCR_raw at 0x50000984; type CH7_DBG_CTDREQ_t { CH7_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH7_DBG_CTDREQ_t CH7_DBG_CTDREQ at 0x500009c0; + register uint32 CH7_DBG_CTDREQ_raw at 0x500009c0; type CH7_DBG_TCR_t { CH7_DBG_TCR = uint32(0); // @@ -7495,13 +10936,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH7_DBG_TCR_t CH7_DBG_TCR at 0x500009c4; + register uint32 CH7_DBG_TCR_raw at 0x500009c4; type CH8_DBG_CTDREQ_t { CH8_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH8_DBG_CTDREQ_t CH8_DBG_CTDREQ at 0x50000a00; + register uint32 CH8_DBG_CTDREQ_raw at 0x50000a00; type CH8_DBG_TCR_t { CH8_DBG_TCR = uint32(0); // @@ -7509,13 +10953,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH8_DBG_TCR_t CH8_DBG_TCR at 0x50000a04; + register uint32 CH8_DBG_TCR_raw at 0x50000a04; type CH9_DBG_CTDREQ_t { CH9_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH9_DBG_CTDREQ_t CH9_DBG_CTDREQ at 0x50000a40; + register uint32 CH9_DBG_CTDREQ_raw at 0x50000a40; type CH9_DBG_TCR_t { CH9_DBG_TCR = uint32(0); // @@ -7523,13 +10970,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH9_DBG_TCR_t CH9_DBG_TCR at 0x50000a44; + register uint32 CH9_DBG_TCR_raw at 0x50000a44; type CH10_DBG_CTDREQ_t { CH10_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH10_DBG_CTDREQ_t CH10_DBG_CTDREQ at 0x50000a80; + register uint32 CH10_DBG_CTDREQ_raw at 0x50000a80; type CH10_DBG_TCR_t { CH10_DBG_TCR = uint32(0); // @@ -7537,13 +10987,16 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH10_DBG_TCR_t CH10_DBG_TCR at 0x50000a84; + register uint32 CH10_DBG_TCR_raw at 0x50000a84; type CH11_DBG_CTDREQ_t { CH11_DBG_CTDREQ = uint6(0); // + _res1 = uint26(0); // Reserved, 26 bits } // Read: get channel DREQ counter (i.e. how many accesses the DMA expects it can perform on the peripheral without overflow/underflow. Write any value: clears the counter, and cause channel to re-initiate DREQ handshake. register CH11_DBG_CTDREQ_t CH11_DBG_CTDREQ at 0x50000ac0; + register uint32 CH11_DBG_CTDREQ_raw at 0x50000ac0; type CH11_DBG_TCR_t { CH11_DBG_TCR = uint32(0); // @@ -7551,6 +11004,7 @@ // Read to get channel TRANS_COUNT reload value, i.e. the length of the next transfer register CH11_DBG_TCR_t CH11_DBG_TCR at 0x50000ac4; + register uint32 CH11_DBG_TCR_raw at 0x50000ac4; /* Types and registers for TIMER @@ -7563,6 +11017,7 @@ // Write to bits 63:32 of time always write timelw before timehw register TIMEHW_t TIMEHW at 0x40054000; + register uint32 TIMEHW_raw at 0x40054000; type TIMELW_t { TIMELW = uint32(0); // @@ -7570,6 +11025,7 @@ // Write to bits 31:0 of time writes do not get copied to time until timehw is written register TIMELW_t TIMELW at 0x40054004; + register uint32 TIMELW_raw at 0x40054004; type TIMEHR_t { TIMEHR = uint32(0); // @@ -7577,6 +11033,7 @@ // Read from bits 63:32 of time always read timelr before timehr register TIMEHR_t TIMEHR at 0x40054008; + register uint32 TIMEHR_raw at 0x40054008; type TIMELR_t { TIMELR = uint32(0); // @@ -7584,6 +11041,7 @@ // Read from bits 31:0 of time register TIMELR_t TIMELR at 0x4005400c; + register uint32 TIMELR_raw at 0x4005400c; type ALARM0_t { ALARM0 = uint32(0); // @@ -7591,6 +11049,7 @@ // Arm alarm 0, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM0 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. register ALARM0_t ALARM0 at 0x40054010; + register uint32 ALARM0_raw at 0x40054010; type ALARM1_t { ALARM1 = uint32(0); // @@ -7598,6 +11057,7 @@ // Arm alarm 1, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM1 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. register ALARM1_t ALARM1 at 0x40054014; + register uint32 ALARM1_raw at 0x40054014; type ALARM2_t { ALARM2 = uint32(0); // @@ -7605,6 +11065,7 @@ // Arm alarm 2, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM2 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. register ALARM2_t ALARM2 at 0x40054018; + register uint32 ALARM2_raw at 0x40054018; type ALARM3_t { ALARM3 = uint32(0); // @@ -7612,13 +11073,16 @@ // Arm alarm 3, and configure the time it will fire. Once armed, the alarm fires when TIMER_ALARM3 == TIMELR. The alarm will disarm itself once it fires, and can be disarmed early using the ARMED status register. register ALARM3_t ALARM3 at 0x4005401c; + register uint32 ALARM3_raw at 0x4005401c; type ARMED_t { ARMED = uint4(0); // + _res1 = uint28(0); // Reserved, 28 bits } // Indicates the armed/disarmed status of each alarm. A write to the corresponding ALARMx register arms the alarm. Alarms automatically disarm upon firing, but writing ones here will disarm immediately without waiting to fire. register ARMED_t ARMED at 0x40054020; + register uint32 ARMED_raw at 0x40054020; type TIMERAWH_t { TIMERAWH = uint32(0); // @@ -7626,6 +11090,7 @@ // Raw read from bits 63:32 of time (no side effects) register TIMERAWH_t TIMERAWH at 0x40054024; + register uint32 TIMERAWH_raw at 0x40054024; type TIMERAWL_t { TIMERAWL = uint32(0); // @@ -7633,68 +11098,88 @@ // Raw read from bits 31:0 of time (no side effects) register TIMERAWL_t TIMERAWL at 0x40054028; + register uint32 TIMERAWL_raw at 0x40054028; type DBGPAUSE_t { _res1 = false; // Reserved, 1 bits DBG0 = false; // Pause when processor 0 is in debug mode DBG1 = false; // Pause when processor 1 is in debug mode + _res2 = uint29(0); // Reserved, 29 bits } // Set bits high to enable pause when the corresponding debug ports are active register DBGPAUSE_t DBGPAUSE at 0x4005402c; + register uint32 DBGPAUSE_raw at 0x4005402c; type PAUSE_t { PAUSE = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Set high to pause the timer register PAUSE_t PAUSE at 0x40054030; + register uint32 PAUSE_raw at 0x40054030; type TIMER_INTR_t { ALARM_0 = false; // ALARM_1 = false; // ALARM_2 = false; // ALARM_3 = false; // + _res1 = uint28(0); // Reserved, 28 bits } // Raw Interrupts register TIMER_INTR_t TIMER_INTR at 0x40054034; + register uint32 TIMER_INTR_raw at 0x40054034; type TIMER_INTE_t { ALARM_0 = false; // ALARM_1 = false; // ALARM_2 = false; // ALARM_3 = false; // + _res1 = uint28(0); // Reserved, 28 bits } // Interrupt Enable register TIMER_INTE_t TIMER_INTE at 0x40054038; + register uint32 TIMER_INTE_raw at 0x40054038; type TIMER_INTF_t { ALARM_0 = false; // ALARM_1 = false; // ALARM_2 = false; // ALARM_3 = false; // + _res1 = uint28(0); // Reserved, 28 bits } // Interrupt Force register TIMER_INTF_t TIMER_INTF at 0x4005403c; + register uint32 TIMER_INTF_raw at 0x4005403c; type TIMER_INTS_t { ALARM_0 = false; // ALARM_1 = false; // ALARM_2 = false; // ALARM_3 = false; // + _res1 = uint28(0); // Reserved, 28 bits } // Interrupt status after masking & forcing register TIMER_INTS_t TIMER_INTS at 0x40054040; + register uint32 TIMER_INTS_raw at 0x40054040; /* Types and registers for PWM Simple PWM */ + enum CH0_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } + type CH0_CSR_t { EN = false; // Enable the PWM channel. PH_CORRECT = false; // 1: Enable phase-correct modulation. 0: Trailing-edge @@ -7703,25 +11188,31 @@ DIVMODE = uint2(0); // PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits } // Control and status register register CH0_CSR_t CH0_CSR at 0x40050000; + register uint32 CH0_CSR_raw at 0x40050000; type CH0_DIV_t { - FRAC = uint4(0); // - INT = uint8(0); // + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits } // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. register CH0_DIV_t CH0_DIV at 0x40050004; + register uint32 CH0_DIV_raw at 0x40050004; type CH0_CTR_t { CH0_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Direct access to the PWM counter register CH0_CTR_t CH0_CTR at 0x40050008; + register uint32 CH0_CTR_raw at 0x40050008; type CH0_CC_t { A = uint16(0); // @@ -7730,13 +11221,23 @@ // Counter compare values register CH0_CC_t CH0_CC at 0x4005000c; + register uint32 CH0_CC_raw at 0x4005000c; type CH0_TOP_t { CH0_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Counter wrap value register CH0_TOP_t CH0_TOP at 0x40050010; + register uint32 CH0_TOP_raw at 0x40050010; + + enum CH1_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } type CH1_CSR_t { EN = false; // Enable the PWM channel. @@ -7746,25 +11247,31 @@ DIVMODE = uint2(0); // PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits } // Control and status register register CH1_CSR_t CH1_CSR at 0x40050014; + register uint32 CH1_CSR_raw at 0x40050014; type CH1_DIV_t { - FRAC = uint4(0); // - INT = uint8(0); // + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits } // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. register CH1_DIV_t CH1_DIV at 0x40050018; + register uint32 CH1_DIV_raw at 0x40050018; type CH1_CTR_t { CH1_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Direct access to the PWM counter register CH1_CTR_t CH1_CTR at 0x4005001c; + register uint32 CH1_CTR_raw at 0x4005001c; type CH1_CC_t { A = uint16(0); // @@ -7773,13 +11280,23 @@ // Counter compare values register CH1_CC_t CH1_CC at 0x40050020; + register uint32 CH1_CC_raw at 0x40050020; type CH1_TOP_t { CH1_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Counter wrap value register CH1_TOP_t CH1_TOP at 0x40050024; + register uint32 CH1_TOP_raw at 0x40050024; + + enum CH2_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } type CH2_CSR_t { EN = false; // Enable the PWM channel. @@ -7789,25 +11306,31 @@ DIVMODE = uint2(0); // PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits } // Control and status register register CH2_CSR_t CH2_CSR at 0x40050028; + register uint32 CH2_CSR_raw at 0x40050028; type CH2_DIV_t { - FRAC = uint4(0); // - INT = uint8(0); // + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits } // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. register CH2_DIV_t CH2_DIV at 0x4005002c; + register uint32 CH2_DIV_raw at 0x4005002c; type CH2_CTR_t { CH2_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Direct access to the PWM counter register CH2_CTR_t CH2_CTR at 0x40050030; + register uint32 CH2_CTR_raw at 0x40050030; type CH2_CC_t { A = uint16(0); // @@ -7816,13 +11339,23 @@ // Counter compare values register CH2_CC_t CH2_CC at 0x40050034; + register uint32 CH2_CC_raw at 0x40050034; type CH2_TOP_t { CH2_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Counter wrap value register CH2_TOP_t CH2_TOP at 0x40050038; + register uint32 CH2_TOP_raw at 0x40050038; + + enum CH3_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } type CH3_CSR_t { EN = false; // Enable the PWM channel. @@ -7832,25 +11365,31 @@ DIVMODE = uint2(0); // PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits } // Control and status register register CH3_CSR_t CH3_CSR at 0x4005003c; + register uint32 CH3_CSR_raw at 0x4005003c; type CH3_DIV_t { - FRAC = uint4(0); // - INT = uint8(0); // + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits } // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. register CH3_DIV_t CH3_DIV at 0x40050040; + register uint32 CH3_DIV_raw at 0x40050040; type CH3_CTR_t { CH3_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Direct access to the PWM counter register CH3_CTR_t CH3_CTR at 0x40050044; + register uint32 CH3_CTR_raw at 0x40050044; type CH3_CC_t { A = uint16(0); // @@ -7859,13 +11398,23 @@ // Counter compare values register CH3_CC_t CH3_CC at 0x40050048; + register uint32 CH3_CC_raw at 0x40050048; type CH3_TOP_t { CH3_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Counter wrap value register CH3_TOP_t CH3_TOP at 0x4005004c; + register uint32 CH3_TOP_raw at 0x4005004c; + + enum CH4_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } type CH4_CSR_t { EN = false; // Enable the PWM channel. @@ -7875,25 +11424,31 @@ DIVMODE = uint2(0); // PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits } // Control and status register register CH4_CSR_t CH4_CSR at 0x40050050; + register uint32 CH4_CSR_raw at 0x40050050; type CH4_DIV_t { - FRAC = uint4(0); // - INT = uint8(0); // + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits } // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. register CH4_DIV_t CH4_DIV at 0x40050054; + register uint32 CH4_DIV_raw at 0x40050054; type CH4_CTR_t { CH4_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Direct access to the PWM counter register CH4_CTR_t CH4_CTR at 0x40050058; + register uint32 CH4_CTR_raw at 0x40050058; type CH4_CC_t { A = uint16(0); // @@ -7902,13 +11457,23 @@ // Counter compare values register CH4_CC_t CH4_CC at 0x4005005c; + register uint32 CH4_CC_raw at 0x4005005c; type CH4_TOP_t { CH4_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Counter wrap value register CH4_TOP_t CH4_TOP at 0x40050060; + register uint32 CH4_TOP_raw at 0x40050060; + + enum CH5_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } type CH5_CSR_t { EN = false; // Enable the PWM channel. @@ -7918,25 +11483,31 @@ DIVMODE = uint2(0); // PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits } // Control and status register register CH5_CSR_t CH5_CSR at 0x40050064; + register uint32 CH5_CSR_raw at 0x40050064; type CH5_DIV_t { - FRAC = uint4(0); // - INT = uint8(0); // + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits } // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. register CH5_DIV_t CH5_DIV at 0x40050068; + register uint32 CH5_DIV_raw at 0x40050068; type CH5_CTR_t { CH5_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Direct access to the PWM counter register CH5_CTR_t CH5_CTR at 0x4005006c; + register uint32 CH5_CTR_raw at 0x4005006c; type CH5_CC_t { A = uint16(0); // @@ -7945,13 +11516,23 @@ // Counter compare values register CH5_CC_t CH5_CC at 0x40050070; + register uint32 CH5_CC_raw at 0x40050070; type CH5_TOP_t { CH5_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Counter wrap value register CH5_TOP_t CH5_TOP at 0x40050074; + register uint32 CH5_TOP_raw at 0x40050074; + + enum CH6_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } type CH6_CSR_t { EN = false; // Enable the PWM channel. @@ -7961,25 +11542,31 @@ DIVMODE = uint2(0); // PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits } // Control and status register register CH6_CSR_t CH6_CSR at 0x40050078; + register uint32 CH6_CSR_raw at 0x40050078; type CH6_DIV_t { - FRAC = uint4(0); // - INT = uint8(0); // + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits } // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. register CH6_DIV_t CH6_DIV at 0x4005007c; + register uint32 CH6_DIV_raw at 0x4005007c; type CH6_CTR_t { CH6_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Direct access to the PWM counter register CH6_CTR_t CH6_CTR at 0x40050080; + register uint32 CH6_CTR_raw at 0x40050080; type CH6_CC_t { A = uint16(0); // @@ -7988,13 +11575,23 @@ // Counter compare values register CH6_CC_t CH6_CC at 0x40050084; + register uint32 CH6_CC_raw at 0x40050084; type CH6_TOP_t { CH6_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Counter wrap value register CH6_TOP_t CH6_TOP at 0x40050088; + register uint32 CH6_TOP_raw at 0x40050088; + + enum CH7_CSR_DIVMODE { + div = 0, // Free-running counting at rate dictated by fractional divider + level = 1, // Fractional divider operation is gated by the PWM B pin. + rise = 2, // Counter advances with each rising edge of the PWM B pin. + fall = 3 // Counter advances with each falling edge of the PWM B pin. + } type CH7_CSR_t { EN = false; // Enable the PWM channel. @@ -8004,25 +11601,31 @@ DIVMODE = uint2(0); // PH_RET = false; // Retard the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running. PH_ADV = false; // Advance the phase of the counter by 1 count, while it is running. Self-clearing. Write a 1, and poll until low. Counter must be running at less than full speed (div_int + div_frac / 16 > 1) + _res1 = uint24(0); // Reserved, 24 bits } // Control and status register register CH7_CSR_t CH7_CSR at 0x4005008c; + register uint32 CH7_CSR_raw at 0x4005008c; type CH7_DIV_t { - FRAC = uint4(0); // - INT = uint8(0); // + FRAC = uint4(0); // + INT = uint8(0); // + _res1 = uint20(0); // Reserved, 20 bits } // INT and FRAC form a fixed-point fractional number. Counting rate is system clock frequency divided by this number. Fractional division uses simple 1st-order sigma-delta. register CH7_DIV_t CH7_DIV at 0x40050090; + register uint32 CH7_DIV_raw at 0x40050090; type CH7_CTR_t { CH7_CTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Direct access to the PWM counter register CH7_CTR_t CH7_CTR at 0x40050094; + register uint32 CH7_CTR_raw at 0x40050094; type CH7_CC_t { A = uint16(0); // @@ -8031,83 +11634,96 @@ // Counter compare values register CH7_CC_t CH7_CC at 0x40050098; + register uint32 CH7_CC_raw at 0x40050098; type CH7_TOP_t { CH7_TOP = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Counter wrap value register CH7_TOP_t CH7_TOP at 0x4005009c; + register uint32 CH7_TOP_raw at 0x4005009c; type EN_t { - CH0 = false; // - CH1 = false; // - CH2 = false; // - CH3 = false; // - CH4 = false; // - CH5 = false; // - CH6 = false; // - CH7 = false; // + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + _res1 = uint24(0); // Reserved, 24 bits } // This register aliases the CSR_EN bits for all channels. Writing to this register allows multiple channels to be enabled or disabled simultaneously, so they can run in perfect sync. For each channel, there is only one physical EN register bit, which can be accessed through here or CHx_CSR. register EN_t EN at 0x400500a0; + register uint32 EN_raw at 0x400500a0; type PWM_INTR_t { - CH0 = false; // - CH1 = false; // - CH2 = false; // - CH3 = false; // - CH4 = false; // - CH5 = false; // - CH6 = false; // - CH7 = false; // + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + _res1 = uint24(0); // Reserved, 24 bits } // Raw Interrupts register PWM_INTR_t PWM_INTR at 0x400500a4; + register uint32 PWM_INTR_raw at 0x400500a4; type PWM_INTE_t { - CH0 = false; // - CH1 = false; // - CH2 = false; // - CH3 = false; // - CH4 = false; // - CH5 = false; // - CH6 = false; // - CH7 = false; // + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + _res1 = uint24(0); // Reserved, 24 bits } // Interrupt Enable register PWM_INTE_t PWM_INTE at 0x400500a8; + register uint32 PWM_INTE_raw at 0x400500a8; type PWM_INTF_t { - CH0 = false; // - CH1 = false; // - CH2 = false; // - CH3 = false; // - CH4 = false; // - CH5 = false; // - CH6 = false; // - CH7 = false; // + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + _res1 = uint24(0); // Reserved, 24 bits } // Interrupt Force register PWM_INTF_t PWM_INTF at 0x400500ac; + register uint32 PWM_INTF_raw at 0x400500ac; type PWM_INTS_t { - CH0 = false; // - CH1 = false; // - CH2 = false; // - CH3 = false; // - CH4 = false; // - CH5 = false; // - CH6 = false; // - CH7 = false; // + CH0 = false; // + CH1 = false; // + CH2 = false; // + CH3 = false; // + CH4 = false; // + CH5 = false; // + CH6 = false; // + CH7 = false; // + _res1 = uint24(0); // Reserved, 24 bits } // Interrupt status after masking & forcing register PWM_INTS_t PWM_INTS at 0x400500b0; + register uint32 PWM_INTS_raw at 0x400500b0; /* Types and registers for ADC @@ -8127,17 +11743,21 @@ AINSEL = uint3(0); // Select analog mux input. Updated automatically in round-robin mode. _res3 = false; // Reserved, 1 bits RROBIN = uint5(0); // Round-robin sampling. 1 bit per channel. Set all bits to 0 to disable. Otherwise, the ADC will cycle through each enabled channel in a round-robin fashion. The first channel to be sampled will be the one currently indicated by AINSEL. AINSEL will be updated after each conversion with the newly-selected channel. + _res4 = uint11(0); // Reserved, 11 bits } // ADC Control and Status register ADC_CS_t ADC_CS at 0x4004c000; + register uint32 ADC_CS_raw at 0x4004c000; type RESULT_t { RESULT = uint12(0); // + _res1 = uint20(0); // Reserved, 20 bits } // Result of most recent ADC conversion register RESULT_t RESULT at 0x4004c004; + register uint32 RESULT_raw at 0x4004c004; type FCS_t { EN = false; // If 1: write result to the FIFO after each conversion. @@ -8153,61 +11773,121 @@ LEVEL = uint4(0); // The number of conversion results currently waiting in the FIFO _res3 = uint4(0); // Reserved, 4 bits THRESH = uint4(0); // DREQ/IRQ asserted when level >= threshold + _res4 = uint4(0); // Reserved, 4 bits } // FIFO control and status register FCS_t FCS at 0x4004c008; + register uint32 FCS_raw at 0x4004c008; type FIFO_t { VAL = uint12(0); // _res1 = uint3(0); // Reserved, 3 bits ERR = false; // 1 if this particular sample experienced a conversion error. Remains in the same location if the sample is shifted. + _res2 = uint16(0); // Reserved, 16 bits } // Conversion result FIFO register FIFO_t FIFO at 0x4004c00c; + register uint32 FIFO_raw at 0x4004c00c; type ADC_DIV_t { - FRAC = uint8(0); // Fractional part of clock divisor. First-order delta-sigma. - INT = uint16(0); // Integer part of clock divisor. + FRAC = uint8(0); // Fractional part of clock divisor. First-order delta-sigma. + INT = uint16(0); // Integer part of clock divisor. + _res1 = uint8(0); // Reserved, 8 bits } // Clock divider. If non-zero, CS_START_MANY will start conversions at regular intervals rather than back-to-back. The divider is reset when either of these fields are written. Total period is 1 + INT + FRAC / 256 register ADC_DIV_t ADC_DIV at 0x4004c010; + register uint32 ADC_DIV_raw at 0x4004c010; type ADC_INTR_t { - FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + _res1 = uint31(0); // Reserved, 31 bits } // Raw Interrupts register ADC_INTR_t ADC_INTR at 0x4004c014; + register uint32 ADC_INTR_raw at 0x4004c014; type ADC_INTE_t { - FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + _res1 = uint31(0); // Reserved, 31 bits } // Interrupt Enable register ADC_INTE_t ADC_INTE at 0x4004c018; + register uint32 ADC_INTE_raw at 0x4004c018; type ADC_INTF_t { - FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + _res1 = uint31(0); // Reserved, 31 bits } // Interrupt Force register ADC_INTF_t ADC_INTF at 0x4004c01c; + register uint32 ADC_INTF_raw at 0x4004c01c; type ADC_INTS_t { - FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + FIFO = false; // Triggered when the sample FIFO reaches a certain level. This level can be programmed via the FCS_THRESH field. + _res1 = uint31(0); // Reserved, 31 bits } // Interrupt status after masking & forcing register ADC_INTS_t ADC_INTS at 0x4004c020; + register uint32 ADC_INTS_raw at 0x4004c020; /* Types and registers for I2C0 DW_apb_i2c address block List of configuration constants for the Synopsys I2C hardware (you may see references to these in I2C register header; these are *fixed* values, set at hardware design time): IC_ULTRA_FAST_MODE ................ 0x0 IC_UFM_TBUF_CNT_DEFAULT ........... 0x8 IC_UFM_SCL_LOW_COUNT .............. 0x0008 IC_UFM_SCL_HIGH_COUNT ............. 0x0006 IC_TX_TL .......................... 0x0 IC_TX_CMD_BLOCK ................... 0x1 IC_HAS_DMA ........................ 0x1 IC_HAS_ASYNC_FIFO ................. 0x0 IC_SMBUS_ARP ...................... 0x0 IC_FIRST_DATA_BYTE_STATUS ......... 0x1 IC_INTR_IO ........................ 0x1 IC_MASTER_MODE .................... 0x1 IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1 IC_INTR_POL ....................... 0x1 IC_OPTIONAL_SAR ................... 0x0 IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055 IC_DEFAULT_SLAVE_ADDR ............. 0x055 IC_DEFAULT_HS_SPKLEN .............. 0x1 IC_FS_SCL_HIGH_COUNT .............. 0x0006 IC_HS_SCL_LOW_COUNT ............... 0x0008 IC_DEVICE_ID_VALUE ................ 0x0 IC_10BITADDR_MASTER ............... 0x0 IC_CLK_FREQ_OPTIMIZATION .......... 0x0 IC_DEFAULT_FS_SPKLEN .............. 0x7 IC_ADD_ENCODED_PARAMS ............. 0x0 IC_DEFAULT_SDA_HOLD ............... 0x000001 IC_DEFAULT_SDA_SETUP .............. 0x64 IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0 IC_CLOCK_PERIOD ................... 100 IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1 IC_RESTART_EN ..................... 0x1 IC_TX_CMD_BLOCK_DEFAULT ........... 0x0 IC_BUS_CLEAR_FEATURE .............. 0x0 IC_CAP_LOADING .................... 100 IC_FS_SCL_LOW_COUNT ............... 0x000d APB_DATA_WIDTH .................... 32 IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff IC_SLV_DATA_NACK_ONLY ............. 0x1 IC_10BITADDR_SLAVE ................ 0x0 IC_CLK_TYPE ....................... 0x0 IC_SMBUS_UDID_MSB ................. 0x0 IC_SMBUS_SUSPEND_ALERT ............ 0x0 IC_HS_SCL_HIGH_COUNT .............. 0x0006 IC_SLV_RESTART_DET_EN ............. 0x1 IC_SMBUS .......................... 0x0 IC_OPTIONAL_SAR_DEFAULT ........... 0x0 IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0 IC_USE_COUNTS ..................... 0x0 IC_RX_BUFFER_DEPTH ................ 16 IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff IC_RX_FULL_HLD_BUS_EN ............. 0x1 IC_SLAVE_DISABLE .................. 0x1 IC_RX_TL .......................... 0x0 IC_DEVICE_ID ...................... 0x0 IC_HC_COUNT_VALUES ................ 0x0 I2C_DYNAMIC_TAR_UPDATE ............ 0 IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff IC_HS_MASTER_CODE ................. 0x1 IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff IC_SS_SCL_HIGH_COUNT .............. 0x0028 IC_SS_SCL_LOW_COUNT ............... 0x002f IC_MAX_SPEED_MODE ................. 0x2 IC_STAT_FOR_CLK_STRETCH ........... 0x0 IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0 IC_DEFAULT_UFM_SPKLEN ............. 0x1 IC_TX_BUFFER_DEPTH ................ 16 */ + enum IC_CON_RX_FIFO_FULL_HLD_CTRL { + DISABLED = 0, // Overflow when RX_FIFO is full + ENABLED = 1 // Hold bus when RX_FIFO is full + } + + enum IC_CON_TX_EMPTY_CTRL { + DISABLED = 0, // Default behaviour of TX_EMPTY interrupt + ENABLED = 1 // Controlled generation of TX_EMPTY interrupt + } + + enum IC_CON_STOP_DET_IFADDRESSED { + DISABLED = 0, // slave issues STOP_DET intr always + ENABLED = 1 // slave issues STOP_DET intr only if addressed + } + + enum IC_CON_IC_SLAVE_DISABLE { + SLAVE_ENABLED = 0, // Slave mode is enabled + SLAVE_DISABLED = 1 // Slave mode is disabled + } + + enum IC_CON_IC_RESTART_EN { + DISABLED = 0, // Master restart disabled + ENABLED = 1 // Master restart enabled + } + + enum IC_CON_IC_10BITADDR_MASTER { + ADDR_7BITS = 0, // Master 7Bit addressing mode + ADDR_10BITS = 1 // Master 10Bit addressing mode + } + + enum IC_CON_IC_10BITADDR_SLAVE { + ADDR_7BITS = 0, // Slave 7Bit addressing + ADDR_10BITS = 1 // Slave 10Bit addressing + } + + enum IC_CON_SPEED { + STANDARD = 1, // Standard Speed mode of operation + FAST = 2, // Fast or Fast Plus mode of operation + HIGH = 3 // High Speed mode of operation + } + + enum IC_CON_MASTER_MODE { + DISABLED = 0, // Master mode is disabled + ENABLED = 1 // Master mode is enabled + } + type IC_CON_t { MASTER_MODE = false; // This bit controls whether the DW_apb_i2c master is enabled. NOTE: Software should ensure that if this bit is written with '1' then bit 6 should also be written with a '1'. SPEED = uint2(0); // These bits control at which speed the DW_apb_i2c operates; its setting is relevant only if one is operating the DW_apb_i2c in master mode. Hardware protects against illegal values being programmed by software. These bits must be programmed appropriately for slave mode also, as it is used to capture correct value of spike filter as per the speed mode. This register should be programmed only with a value in the range of 1 to IC_MAX_SPEED_MODE; otherwise, hardware updates this register with the value of IC_MAX_SPEED_MODE. 1: standard mode (100 kbit/s) 2: fast mode (<=400 kbit/s) or fast mode plus (<=1000Kbit/s) 3: high speed mode (3.4 Mbit/s) Note: This field is not applicable when IC_ULTRA_FAST_MODE=1 @@ -8219,26 +11899,62 @@ TX_EMPTY_CTRL = false; // This bit controls the generation of the TX_EMPTY interrupt, as described in the IC_RAW_INTR_STAT register. Reset value: 0x0. RX_FIFO_FULL_HLD_CTRL = false; // This bit controls whether DW_apb_i2c should hold the bus when the Rx FIFO is physically full to its RX_BUFFER_DEPTH, as described in the IC_RX_FULL_HLD_BUS_EN parameter. Reset value: 0x0. STOP_DET_IF_MASTER_ACTIVE = false; // Master issues the STOP_DET interrupt irrespective of whether master is active or not + _res1 = uint21(0); // Reserved, 21 bits } // I2C0 I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only. register IC_CON_t I2C0_IC_CON at 0x40044000; + register uint32 I2C0_IC_CON_raw at 0x40044000; + + enum IC_TAR_SPECIAL { + DISABLED = 0, // Disables programming of GENERAL_CALL or START_BYTE transmission + ENABLED = 1 // Enables programming of GENERAL_CALL or START_BYTE transmission + } + + enum IC_TAR_GC_OR_START { + GENERAL_CALL = 0, // GENERAL_CALL byte transmission + START_BYTE = 1 // START byte transmission + } type IC_TAR_t { IC_TAR = uint10(0); // This is the target address for any master transaction. When transmitting a General Call, these bits are ignored. To generate a START BYTE, the CPU needs to write only once into these bits. If the IC_TAR and IC_SAR are the same, loopback exists but the FIFOs are shared between master and slave, so full loopback is not feasible. Only one direction loopback mode is supported (simplex), not duplex. A master cannot transmit to itself; it can transmit to only a slave. GC_OR_START = false; // If bit 11 (SPECIAL) is set to 1 and bit 13(Device-ID) is set to 0, then this bit indicates whether a General Call or START byte command is to be performed by the DW_apb_i2c. - 0: General Call Address - after issuing a General Call, only writes may be performed. Attempting to issue a read command results in setting bit 6 (TX_ABRT) of the IC_RAW_INTR_STAT register. The DW_apb_i2c remains in General Call mode until the SPECIAL bit value (bit 11) is cleared. - 1: START BYTE Reset value: 0x0 SPECIAL = false; // This bit indicates whether software performs a Device-ID or General Call or START BYTE command. - 0: ignore bit 10 GC_OR_START and use IC_TAR normally - 1: perform special I2C command as specified in Device_ID or GC_OR_START bit Reset value: 0x0 + _res1 = uint20(0); // Reserved, 20 bits } // I2C0 I2C Target Address Register This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0. Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only. register IC_TAR_t I2C0_IC_TAR at 0x40044004; + register uint32 I2C0_IC_TAR_raw at 0x40044004; type IC_SAR_t { IC_SAR = uint10(0); // The IC_SAR holds the slave address when the I2C is operating as a slave. For 7-bit addressing, only IC_SAR[6:0] is used. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. Note: The default values cannot be any of the reserved address locations: that is, 0x00 to 0x07, or 0x78 to 0x7f. The correct operation of the device is not guaranteed if you program the IC_SAR or IC_TAR to a reserved value. Refer to <> for a complete list of these reserved values. + _res1 = uint22(0); // Reserved, 22 bits } // I2C0 I2C Slave Address Register register IC_SAR_t I2C0_IC_SAR at 0x40044008; + register uint32 I2C0_IC_SAR_raw at 0x40044008; + + enum IC_DATA_CMD_FIRST_DATA_BYTE { + INACTIVE = 0, // Sequential data byte received + ACTIVE = 1 // Non sequential data byte received + } + + enum IC_DATA_CMD_RESTART { + DISABLE = 0, // Don't Issue RESTART before this command + ENABLE = 1 // Issue RESTART before this command + } + + enum IC_DATA_CMD_STOP { + DISABLE = 0, // Don't Issue STOP after this command + ENABLE = 1 // Issue STOP after this command + } + + enum IC_DATA_CMD_CMD { + WRITE = 0, // Master Write Command + READ = 1 // Master Read Command + } type IC_DATA_CMD_t { DAT = uint8(0); // This register contains the data to be transmitted or received on the I2C bus. If you are writing to this register and want to perform a read, bits 7:0 (DAT) are ignored by the DW_apb_i2c. However, when you read this register, these bits return the value of data received on the DW_apb_i2c interface. Reset value: 0x0 @@ -8246,38 +11962,113 @@ STOP = false; // This bit controls whether a STOP is issued after the byte is sent or received. - 1 - STOP is issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master immediately tries to start a new transfer by issuing a START and arbitrating for the bus. - 0 - STOP is not issued after this byte, regardless of whether or not the Tx FIFO is empty. If the Tx FIFO is not empty, the master continues the current transfer by sending/receiving data bytes according to the value of the CMD bit. If the Tx FIFO is empty, the master holds the SCL line low and stalls the bus until a new command is available in the Tx FIFO. Reset value: 0x0 RESTART = false; // This bit controls whether a RESTART is issued before the byte is sent or received. 1 - If IC_RESTART_EN is 1, a RESTART is issued before the data is sent/received (according to the value of CMD), regardless of whether or not the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. 0 - If IC_RESTART_EN is 1, a RESTART is issued only if the transfer direction is changing from the previous command; if IC_RESTART_EN is 0, a STOP followed by a START is issued instead. Reset value: 0x0 FIRST_DATA_BYTE = false; // Indicates the first data byte received after the address phase for receive transfer in Master receiver or Slave receiver mode. Reset value : 0x0 NOTE: In case of APB_DATA_WIDTH=8, 1. The user has to perform two APB Reads to IC_DATA_CMD in order to get status on 11 bit. 2. In order to read the 11 bit, the user has to perform the first data byte read [7:0] (offset 0x10) and then perform the second read [15:8] (offset 0x11) in order to know the status of 11 bit (whether the data received in previous read is a first data byte or not). 3. The 11th bit is an optional read field, user can ignore 2nd byte read [15:8] (offset 0x11) if not interested in FIRST_DATA_BYTE status. + _res1 = uint20(0); // Reserved, 20 bits } // I2C0 I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO. The size of the register changes as follows: Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging. register IC_DATA_CMD_t I2C0_IC_DATA_CMD at 0x40044010; + register uint32 I2C0_IC_DATA_CMD_raw at 0x40044010; type IC_SS_SCL_HCNT_t { IC_SS_SCL_HCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration'. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. NOTE: This register must not be programmed to a value higher than 65525, because DW_apb_i2c uses a 16-bit counter to flag an I2C bus idle condition when this counter reaches a value of IC_SS_SCL_HCNT + 10. + _res1 = uint16(0); // Reserved, 16 bits } // I2C0 Standard Speed I2C Clock SCL High Count Register register IC_SS_SCL_HCNT_t I2C0_IC_SS_SCL_HCNT at 0x40044014; + register uint32 I2C0_IC_SS_SCL_HCNT_raw at 0x40044014; type IC_SS_SCL_LCNT_t { IC_SS_SCL_LCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for standard speed. For more information, refer to 'IC_CLK Frequency Configuration' This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 8; hardware prevents values less than this being written, and if attempted, results in 8 being set. For designs with APB_DATA_WIDTH = 8, the order of programming is important to ensure the correct operation of DW_apb_i2c. The lower byte must be programmed first, and then the upper byte is programmed. + _res1 = uint16(0); // Reserved, 16 bits } // I2C0 Standard Speed I2C Clock SCL Low Count Register register IC_SS_SCL_LCNT_t I2C0_IC_SS_SCL_LCNT at 0x40044018; + register uint32 I2C0_IC_SS_SCL_LCNT_raw at 0x40044018; type IC_FS_SCL_HCNT_t { IC_FS_SCL_HCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock high-period count for fast mode or fast mode plus. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 6; hardware prevents values less than this being written, and if attempted results in 6 being set. For designs with APB_DATA_WIDTH == 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. + _res1 = uint16(0); // Reserved, 16 bits } // I2C0 Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register register IC_FS_SCL_HCNT_t I2C0_IC_FS_SCL_HCNT at 0x4004401c; + register uint32 I2C0_IC_FS_SCL_HCNT_raw at 0x4004401c; type IC_FS_SCL_LCNT_t { IC_FS_SCL_LCNT = uint16(0); // This register must be set before any I2C bus transaction can take place to ensure proper I/O timing. This register sets the SCL clock low period count for fast speed. It is used in high-speed mode to send the Master Code and START BYTE or General CALL. For more information, refer to 'IC_CLK Frequency Configuration'. This register goes away and becomes read-only returning 0s if IC_MAX_SPEED_MODE = standard. This register can be written only when the I2C interface is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 8; hardware prevents values less than this being written, and if attempted results in 8 being set. For designs with APB_DATA_WIDTH = 8 the order of programming is important to ensure the correct operation of the DW_apb_i2c. The lower byte must be programmed first. Then the upper byte is programmed. If the value is less than 8 then the count value gets changed to 8. + _res1 = uint16(0); // Reserved, 16 bits } // I2C0 Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register register IC_FS_SCL_LCNT_t I2C0_IC_FS_SCL_LCNT at 0x40044020; + register uint32 I2C0_IC_FS_SCL_LCNT_raw at 0x40044020; + + enum IC_INTR_STAT_R_RESTART_DET { + INACTIVE = 0, // R_RESTART_DET interrupt is inactive + ACTIVE = 1 // R_RESTART_DET interrupt is active + } + + enum IC_INTR_STAT_R_GEN_CALL { + INACTIVE = 0, // R_GEN_CALL interrupt is inactive + ACTIVE = 1 // R_GEN_CALL interrupt is active + } + + enum IC_INTR_STAT_R_START_DET { + INACTIVE = 0, // R_START_DET interrupt is inactive + ACTIVE = 1 // R_START_DET interrupt is active + } + + enum IC_INTR_STAT_R_STOP_DET { + INACTIVE = 0, // R_STOP_DET interrupt is inactive + ACTIVE = 1 // R_STOP_DET interrupt is active + } + + enum IC_INTR_STAT_R_ACTIVITY { + INACTIVE = 0, // R_ACTIVITY interrupt is inactive + ACTIVE = 1 // R_ACTIVITY interrupt is active + } + + enum IC_INTR_STAT_R_RX_DONE { + INACTIVE = 0, // R_RX_DONE interrupt is inactive + ACTIVE = 1 // R_RX_DONE interrupt is active + } + + enum IC_INTR_STAT_R_TX_ABRT { + INACTIVE = 0, // R_TX_ABRT interrupt is inactive + ACTIVE = 1 // R_TX_ABRT interrupt is active + } + + enum IC_INTR_STAT_R_RD_REQ { + INACTIVE = 0, // R_RD_REQ interrupt is inactive + ACTIVE = 1 // R_RD_REQ interrupt is active + } + + enum IC_INTR_STAT_R_TX_EMPTY { + INACTIVE = 0, // R_TX_EMPTY interrupt is inactive + ACTIVE = 1 // R_TX_EMPTY interrupt is active + } + + enum IC_INTR_STAT_R_TX_OVER { + INACTIVE = 0, // R_TX_OVER interrupt is inactive + ACTIVE = 1 // R_TX_OVER interrupt is active + } + + enum IC_INTR_STAT_R_RX_FULL { + INACTIVE = 0, // R_RX_FULL interrupt is inactive + ACTIVE = 1 // R_RX_FULL interrupt is active + } + + enum IC_INTR_STAT_R_RX_OVER { + INACTIVE = 0, // R_RX_OVER interrupt is inactive + ACTIVE = 1 // R_RX_OVER interrupt is active + } + + enum IC_INTR_STAT_R_RX_UNDER { + INACTIVE = 0, // RX_UNDER interrupt is inactive + ACTIVE = 1 // RX_UNDER interrupt is active + } type IC_INTR_STAT_t { R_RX_UNDER = false; // See IC_RAW_INTR_STAT for a detailed description of R_RX_UNDER bit. Reset value: 0x0 @@ -8293,29 +12084,163 @@ R_START_DET = false; // See IC_RAW_INTR_STAT for a detailed description of R_START_DET bit. Reset value: 0x0 R_GEN_CALL = false; // See IC_RAW_INTR_STAT for a detailed description of R_GEN_CALL bit. Reset value: 0x0 R_RESTART_DET = false; // See IC_RAW_INTR_STAT for a detailed description of R_RESTART_DET bit. Reset value: 0x0 + _res1 = uint19(0); // Reserved, 19 bits + } + + // I2C0 I2C Interrupt Status Register Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. + register IC_INTR_STAT_t I2C0_IC_INTR_STAT at 0x4004402c; + register uint32 I2C0_IC_INTR_STAT_raw at 0x4004402c; + + enum IC_INTR_MASK_M_RESTART_DET { + ENABLED = 0, // RESTART_DET interrupt is masked + DISABLED = 1 // RESTART_DET interrupt is unmasked + } + + enum IC_INTR_MASK_M_GEN_CALL { + ENABLED = 0, // GEN_CALL interrupt is masked + DISABLED = 1 // GEN_CALL interrupt is unmasked + } + + enum IC_INTR_MASK_M_START_DET { + ENABLED = 0, // START_DET interrupt is masked + DISABLED = 1 // START_DET interrupt is unmasked + } + + enum IC_INTR_MASK_M_STOP_DET { + ENABLED = 0, // STOP_DET interrupt is masked + DISABLED = 1 // STOP_DET interrupt is unmasked + } + + enum IC_INTR_MASK_M_ACTIVITY { + ENABLED = 0, // ACTIVITY interrupt is masked + DISABLED = 1 // ACTIVITY interrupt is unmasked + } + + enum IC_INTR_MASK_M_RX_DONE { + ENABLED = 0, // RX_DONE interrupt is masked + DISABLED = 1 // RX_DONE interrupt is unmasked + } + + enum IC_INTR_MASK_M_TX_ABRT { + ENABLED = 0, // TX_ABORT interrupt is masked + DISABLED = 1 // TX_ABORT interrupt is unmasked + } + + enum IC_INTR_MASK_M_RD_REQ { + ENABLED = 0, // RD_REQ interrupt is masked + DISABLED = 1 // RD_REQ interrupt is unmasked + } + + enum IC_INTR_MASK_M_TX_EMPTY { + ENABLED = 0, // TX_EMPTY interrupt is masked + DISABLED = 1 // TX_EMPTY interrupt is unmasked + } + + enum IC_INTR_MASK_M_TX_OVER { + ENABLED = 0, // TX_OVER interrupt is masked + DISABLED = 1 // TX_OVER interrupt is unmasked + } + + enum IC_INTR_MASK_M_RX_FULL { + ENABLED = 0, // RX_FULL interrupt is masked + DISABLED = 1 // RX_FULL interrupt is unmasked + } + + enum IC_INTR_MASK_M_RX_OVER { + ENABLED = 0, // RX_OVER interrupt is masked + DISABLED = 1 // RX_OVER interrupt is unmasked + } + + enum IC_INTR_MASK_M_RX_UNDER { + ENABLED = 0, // RX_UNDER interrupt is masked + DISABLED = 1 // RX_UNDER interrupt is unmasked + } + + type IC_INTR_MASK_t { + M_RX_UNDER = false; // This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RX_OVER = false; // This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RX_FULL = false; // This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_TX_OVER = false; // This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_TX_EMPTY = false; // This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RD_REQ = false; // This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_TX_ABRT = false; // This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RX_DONE = false; // This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_ACTIVITY = false; // This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register. Reset value: 0x0 + M_STOP_DET = false; // This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 + M_START_DET = false; // This bit masks the R_START_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 + M_GEN_CALL = false; // This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register. Reset value: 0x1 + M_RESTART_DET = false; // This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 + _res1 = uint19(0); // Reserved, 19 bits + } + + // I2C0 I2C Interrupt Mask Register. These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. + register IC_INTR_MASK_t I2C0_IC_INTR_MASK at 0x40044030; + register uint32 I2C0_IC_INTR_MASK_raw at 0x40044030; + + enum IC_RAW_INTR_STAT_RESTART_DET { + INACTIVE = 0, // RESTART_DET interrupt is inactive + ACTIVE = 1 // RESTART_DET interrupt is active + } + + enum IC_RAW_INTR_STAT_GEN_CALL { + INACTIVE = 0, // GEN_CALL interrupt is inactive + ACTIVE = 1 // GEN_CALL interrupt is active + } + + enum IC_RAW_INTR_STAT_START_DET { + INACTIVE = 0, // START_DET interrupt is inactive + ACTIVE = 1 // START_DET interrupt is active + } + + enum IC_RAW_INTR_STAT_STOP_DET { + INACTIVE = 0, // STOP_DET interrupt is inactive + ACTIVE = 1 // STOP_DET interrupt is active + } + + enum IC_RAW_INTR_STAT_ACTIVITY { + INACTIVE = 0, // RAW_INTR_ACTIVITY interrupt is inactive + ACTIVE = 1 // RAW_INTR_ACTIVITY interrupt is active + } + + enum IC_RAW_INTR_STAT_RX_DONE { + INACTIVE = 0, // RX_DONE interrupt is inactive + ACTIVE = 1 // RX_DONE interrupt is active + } + + enum IC_RAW_INTR_STAT_TX_ABRT { + INACTIVE = 0, // TX_ABRT interrupt is inactive + ACTIVE = 1 // TX_ABRT interrupt is active + } + + enum IC_RAW_INTR_STAT_RD_REQ { + INACTIVE = 0, // RD_REQ interrupt is inactive + ACTIVE = 1 // RD_REQ interrupt is active + } + + enum IC_RAW_INTR_STAT_TX_EMPTY { + INACTIVE = 0, // TX_EMPTY interrupt is inactive + ACTIVE = 1 // TX_EMPTY interrupt is active } - // I2C0 I2C Interrupt Status Register Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. - register IC_INTR_STAT_t I2C0_IC_INTR_STAT at 0x4004402c; + enum IC_RAW_INTR_STAT_TX_OVER { + INACTIVE = 0, // TX_OVER interrupt is inactive + ACTIVE = 1 // TX_OVER interrupt is active + } - type IC_INTR_MASK_t { - M_RX_UNDER = false; // This bit masks the R_RX_UNDER interrupt in IC_INTR_STAT register. Reset value: 0x1 - M_RX_OVER = false; // This bit masks the R_RX_OVER interrupt in IC_INTR_STAT register. Reset value: 0x1 - M_RX_FULL = false; // This bit masks the R_RX_FULL interrupt in IC_INTR_STAT register. Reset value: 0x1 - M_TX_OVER = false; // This bit masks the R_TX_OVER interrupt in IC_INTR_STAT register. Reset value: 0x1 - M_TX_EMPTY = false; // This bit masks the R_TX_EMPTY interrupt in IC_INTR_STAT register. Reset value: 0x1 - M_RD_REQ = false; // This bit masks the R_RD_REQ interrupt in IC_INTR_STAT register. Reset value: 0x1 - M_TX_ABRT = false; // This bit masks the R_TX_ABRT interrupt in IC_INTR_STAT register. Reset value: 0x1 - M_RX_DONE = false; // This bit masks the R_RX_DONE interrupt in IC_INTR_STAT register. Reset value: 0x1 - M_ACTIVITY = false; // This bit masks the R_ACTIVITY interrupt in IC_INTR_STAT register. Reset value: 0x0 - M_STOP_DET = false; // This bit masks the R_STOP_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 - M_START_DET = false; // This bit masks the R_START_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 - M_GEN_CALL = false; // This bit masks the R_GEN_CALL interrupt in IC_INTR_STAT register. Reset value: 0x1 - M_RESTART_DET = false; // This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT register. Reset value: 0x0 + enum IC_RAW_INTR_STAT_RX_FULL { + INACTIVE = 0, // RX_FULL interrupt is inactive + ACTIVE = 1 // RX_FULL interrupt is active } - // I2C0 I2C Interrupt Mask Register. These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. - register IC_INTR_MASK_t I2C0_IC_INTR_MASK at 0x40044030; + enum IC_RAW_INTR_STAT_RX_OVER { + INACTIVE = 0, // RX_OVER interrupt is inactive + ACTIVE = 1 // RX_OVER interrupt is active + } + + enum IC_RAW_INTR_STAT_RX_UNDER { + INACTIVE = 0, // RX_UNDER interrupt is inactive + ACTIVE = 1 // RX_UNDER interrupt is active + } type IC_RAW_INTR_STAT_t { RX_UNDER = false; // Set if the processor attempts to read the receive buffer when it is empty by reading from the IC_DATA_CMD register. If the module is disabled (IC_ENABLE[0]=0), this bit keeps its level until the master or slave state machines go into idle, and when ic_en goes to 0, this interrupt is cleared. Reset value: 0x0 @@ -8331,110 +12256,190 @@ START_DET = false; // Indicates whether a START or RESTART condition has occurred on the I2C interface regardless of whether DW_apb_i2c is operating in slave or master mode. Reset value: 0x0 GEN_CALL = false; // Set only when a General Call address is received and it is acknowledged. It stays set until it is cleared either by disabling DW_apb_i2c or when the CPU reads bit 0 of the IC_CLR_GEN_CALL register. DW_apb_i2c stores the received data in the Rx buffer. Reset value: 0x0 RESTART_DET = false; // Indicates whether a RESTART condition has occurred on the I2C interface when DW_apb_i2c is operating in Slave mode and the slave is being addressed. Enabled only when IC_SLV_RESTART_DET_EN=1. Note: However, in high-speed mode or during a START BYTE transfer, the RESTART comes before the address field as per the I2C protocol. In this case, the slave is not the addressed slave when the RESTART is issued, therefore DW_apb_i2c does not generate the RESTART_DET interrupt. Reset value: 0x0 + _res1 = uint19(0); // Reserved, 19 bits } // I2C0 I2C Raw Interrupt Status Register Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c. register IC_RAW_INTR_STAT_t I2C0_IC_RAW_INTR_STAT at 0x40044034; + register uint32 I2C0_IC_RAW_INTR_STAT_raw at 0x40044034; type IC_RX_TL_t { RX_TL = uint8(0); // Receive FIFO Threshold Level. Controls the level of entries (or above) that triggers the RX_FULL interrupt (bit 2 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that hardware does not allow this value to be set to a value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 1 entry, and a value of 255 sets the threshold for 256 entries. + _res1 = uint24(0); // Reserved, 24 bits } // I2C0 I2C Receive FIFO Threshold Register register IC_RX_TL_t I2C0_IC_RX_TL at 0x40044038; + register uint32 I2C0_IC_RX_TL_raw at 0x40044038; type IC_TX_TL_t { TX_TL = uint8(0); // Transmit FIFO Threshold Level. Controls the level of entries (or below) that trigger the TX_EMPTY interrupt (bit 4 in IC_RAW_INTR_STAT register). The valid range is 0-255, with the additional restriction that it may not be set to value larger than the depth of the buffer. If an attempt is made to do that, the actual value set will be the maximum depth of the buffer. A value of 0 sets the threshold for 0 entries, and a value of 255 sets the threshold for 255 entries. + _res1 = uint24(0); // Reserved, 24 bits } // I2C0 I2C Transmit FIFO Threshold Register register IC_TX_TL_t I2C0_IC_TX_TL at 0x4004403c; + register uint32 I2C0_IC_TX_TL_raw at 0x4004403c; type IC_CLR_INTR_t { CLR_INTR = false; // Read this register to clear the combined interrupt, all individual interrupts, and the IC_TX_ABRT_SOURCE register. This bit does not clear hardware clearable interrupts but software clearable interrupts. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear Combined and Individual Interrupt Register register IC_CLR_INTR_t I2C0_IC_CLR_INTR at 0x40044040; + register uint32 I2C0_IC_CLR_INTR_raw at 0x40044040; type IC_CLR_RX_UNDER_t { CLR_RX_UNDER = false; // Read this register to clear the RX_UNDER interrupt (bit 0) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear RX_UNDER Interrupt Register register IC_CLR_RX_UNDER_t I2C0_IC_CLR_RX_UNDER at 0x40044044; + register uint32 I2C0_IC_CLR_RX_UNDER_raw at 0x40044044; type IC_CLR_RX_OVER_t { CLR_RX_OVER = false; // Read this register to clear the RX_OVER interrupt (bit 1) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear RX_OVER Interrupt Register register IC_CLR_RX_OVER_t I2C0_IC_CLR_RX_OVER at 0x40044048; + register uint32 I2C0_IC_CLR_RX_OVER_raw at 0x40044048; type IC_CLR_TX_OVER_t { CLR_TX_OVER = false; // Read this register to clear the TX_OVER interrupt (bit 3) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear TX_OVER Interrupt Register register IC_CLR_TX_OVER_t I2C0_IC_CLR_TX_OVER at 0x4004404c; + register uint32 I2C0_IC_CLR_TX_OVER_raw at 0x4004404c; type IC_CLR_RD_REQ_t { CLR_RD_REQ = false; // Read this register to clear the RD_REQ interrupt (bit 5) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear RD_REQ Interrupt Register register IC_CLR_RD_REQ_t I2C0_IC_CLR_RD_REQ at 0x40044050; + register uint32 I2C0_IC_CLR_RD_REQ_raw at 0x40044050; type IC_CLR_TX_ABRT_t { CLR_TX_ABRT = false; // Read this register to clear the TX_ABRT interrupt (bit 6) of the IC_RAW_INTR_STAT register, and the IC_TX_ABRT_SOURCE register. This also releases the TX FIFO from the flushed/reset state, allowing more writes to the TX FIFO. Refer to Bit 9 of the IC_TX_ABRT_SOURCE register for an exception to clearing IC_TX_ABRT_SOURCE. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear TX_ABRT Interrupt Register register IC_CLR_TX_ABRT_t I2C0_IC_CLR_TX_ABRT at 0x40044054; + register uint32 I2C0_IC_CLR_TX_ABRT_raw at 0x40044054; type IC_CLR_RX_DONE_t { CLR_RX_DONE = false; // Read this register to clear the RX_DONE interrupt (bit 7) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear RX_DONE Interrupt Register register IC_CLR_RX_DONE_t I2C0_IC_CLR_RX_DONE at 0x40044058; + register uint32 I2C0_IC_CLR_RX_DONE_raw at 0x40044058; type IC_CLR_ACTIVITY_t { CLR_ACTIVITY = false; // Reading this register clears the ACTIVITY interrupt if the I2C is not active anymore. If the I2C module is still active on the bus, the ACTIVITY interrupt bit continues to be set. It is automatically cleared by hardware if the module is disabled and if there is no further activity on the bus. The value read from this register to get status of the ACTIVITY interrupt (bit 8) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear ACTIVITY Interrupt Register register IC_CLR_ACTIVITY_t I2C0_IC_CLR_ACTIVITY at 0x4004405c; + register uint32 I2C0_IC_CLR_ACTIVITY_raw at 0x4004405c; type IC_CLR_STOP_DET_t { CLR_STOP_DET = false; // Read this register to clear the STOP_DET interrupt (bit 9) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear STOP_DET Interrupt Register register IC_CLR_STOP_DET_t I2C0_IC_CLR_STOP_DET at 0x40044060; + register uint32 I2C0_IC_CLR_STOP_DET_raw at 0x40044060; type IC_CLR_START_DET_t { CLR_START_DET = false; // Read this register to clear the START_DET interrupt (bit 10) of the IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear START_DET Interrupt Register register IC_CLR_START_DET_t I2C0_IC_CLR_START_DET at 0x40044064; + register uint32 I2C0_IC_CLR_START_DET_raw at 0x40044064; type IC_CLR_GEN_CALL_t { CLR_GEN_CALL = false; // Read this register to clear the GEN_CALL interrupt (bit 11) of IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear GEN_CALL Interrupt Register register IC_CLR_GEN_CALL_t I2C0_IC_CLR_GEN_CALL at 0x40044068; + register uint32 I2C0_IC_CLR_GEN_CALL_raw at 0x40044068; + + enum IC_ENABLE_TX_CMD_BLOCK { + NOT_BLOCKED = 0, // Tx Command execution not blocked + BLOCKED = 1 // Tx Command execution blocked + } + + enum IC_ENABLE_ABORT { + DISABLE = 0, // ABORT operation not in progress + ENABLED = 1 // ABORT operation in progress + } + + enum IC_ENABLE_ENABLE { + DISABLED = 0, // I2C is disabled + ENABLED = 1 // I2C is enabled + } type IC_ENABLE_t { ENABLE = false; // Controls whether the DW_apb_i2c is enabled. - 0: Disables DW_apb_i2c (TX and RX FIFOs are held in an erased state) - 1: Enables DW_apb_i2c Software can disable DW_apb_i2c while it is active. However, it is important that care be taken to ensure that DW_apb_i2c is disabled properly. A recommended procedure is described in 'Disabling DW_apb_i2c'. When DW_apb_i2c is disabled, the following occurs: - The TX FIFO and RX FIFO get flushed. - Status bits in the IC_INTR_STAT register are still active until DW_apb_i2c goes into IDLE state. If the module is transmitting, it stops as well as deletes the contents of the transmit buffer after the current transfer is complete. If the module is receiving, the DW_apb_i2c stops the current transfer at the end of the current byte and does not acknowledge the transfer. In systems with asynchronous pclk and ic_clk when IC_CLK_TYPE parameter set to asynchronous (1), there is a two ic_clk delay when enabling or disabling the DW_apb_i2c. For a detailed description on how to disable DW_apb_i2c, refer to 'Disabling DW_apb_i2c' Reset value: 0x0 ABORT = false; // When set, the controller initiates the transfer abort. - 0: ABORT not initiated or ABORT done - 1: ABORT operation in progress The software can abort the I2C transfer in master mode by setting this bit. The software can set this bit only when ENABLE is already set; otherwise, the controller ignores any write to ABORT bit. The software cannot clear the ABORT bit once set. In response to an ABORT, the controller issues a STOP and flushes the Tx FIFO after completing the current transfer, then sets the TX_ABORT interrupt after the abort operation. The ABORT bit is cleared automatically after the abort operation. For a detailed description on how to abort I2C transfers, refer to 'Aborting I2C Transfers'. Reset value: 0x0 TX_CMD_BLOCK = false; // In Master mode: - 1'b1: Blocks the transmission of data on I2C bus even if Tx FIFO has data to transmit. - 1'b0: The transmission of data starts on I2C bus automatically, as soon as the first data is available in the Tx FIFO. Note: To block the execution of Master commands, set the TX_CMD_BLOCK bit only when Tx FIFO is empty (IC_STATUS[2]==1) and Master is in Idle state (IC_STATUS[5] == 0). Any further commands put in the Tx FIFO are not executed until TX_CMD_BLOCK bit is unset. Reset value: IC_TX_CMD_BLOCK_DEFAULT + _res1 = uint29(0); // Reserved, 29 bits } // I2C0 I2C Enable Register register IC_ENABLE_t I2C0_IC_ENABLE at 0x4004406c; + register uint32 I2C0_IC_ENABLE_raw at 0x4004406c; + + enum IC_STATUS_SLV_ACTIVITY { + IDLE = 0, // Slave is idle + ACTIVE = 1 // Slave not idle + } + + enum IC_STATUS_MST_ACTIVITY { + IDLE = 0, // Master is idle + ACTIVE = 1 // Master not idle + } + + enum IC_STATUS_RFF { + NOT_FULL = 0, // Rx FIFO not full + FULL = 1 // Rx FIFO is full + } + + enum IC_STATUS_RFNE { + EMPTY = 0, // Rx FIFO is empty + NOT_EMPTY = 1 // Rx FIFO not empty + } + + enum IC_STATUS_TFE { + NON_EMPTY = 0, // Tx FIFO not empty + EMPTY = 1 // Tx FIFO is empty + } + + enum IC_STATUS_TFNF { + FULL = 0, // Tx FIFO is full + NOT_FULL = 1 // Tx FIFO not full + } + + enum IC_STATUS_ACTIVITY { + INACTIVE = 0, // I2C is idle + ACTIVE = 1 // I2C is active + } type IC_STATUS_t { ACTIVITY = false; // I2C Activity Status. Reset value: 0x0 @@ -8444,32 +12449,125 @@ RFF = false; // Receive FIFO Completely Full. When the receive FIFO is completely full, this bit is set. When the receive FIFO contains one or more empty location, this bit is cleared. - 0: Receive FIFO is not full - 1: Receive FIFO is full Reset value: 0x0 MST_ACTIVITY = false; // Master FSM Activity Status. When the Master Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Master FSM is in IDLE state so the Master part of DW_apb_i2c is not Active - 1: Master FSM is not in IDLE state so the Master part of DW_apb_i2c is Active Note: IC_STATUS[0]-that is, ACTIVITY bit-is the OR of SLV_ACTIVITY and MST_ACTIVITY bits. Reset value: 0x0 SLV_ACTIVITY = false; // Slave FSM Activity Status. When the Slave Finite State Machine (FSM) is not in the IDLE state, this bit is set. - 0: Slave FSM is in IDLE state so the Slave part of DW_apb_i2c is not Active - 1: Slave FSM is not in IDLE state so the Slave part of DW_apb_i2c is Active Reset value: 0x0 + _res1 = uint25(0); // Reserved, 25 bits } // I2C0 I2C Status Register This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt. When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 register IC_STATUS_t I2C0_IC_STATUS at 0x40044070; + register uint32 I2C0_IC_STATUS_raw at 0x40044070; type IC_TXFLR_t { TXFLR = uint5(0); // Transmit FIFO Level. Contains the number of valid data entries in the transmit FIFO. Reset value: 0x0 + _res1 = uint27(0); // Reserved, 27 bits } // I2C0 I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO. register IC_TXFLR_t I2C0_IC_TXFLR at 0x40044074; + register uint32 I2C0_IC_TXFLR_raw at 0x40044074; type IC_RXFLR_t { RXFLR = uint5(0); // Receive FIFO Level. Contains the number of valid data entries in the receive FIFO. Reset value: 0x0 + _res1 = uint27(0); // Reserved, 27 bits } // I2C0 I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO. register IC_RXFLR_t I2C0_IC_RXFLR at 0x40044078; + register uint32 I2C0_IC_RXFLR_raw at 0x40044078; type IC_SDA_HOLD_t { IC_SDA_TX_HOLD = uint16(0); // Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a transmitter. Reset value: IC_DEFAULT_SDA_HOLD[15:0]. IC_SDA_RX_HOLD = uint8(0); // Sets the required SDA hold time in units of ic_clk period, when DW_apb_i2c acts as a receiver. Reset value: IC_DEFAULT_SDA_HOLD[23:16]. + _res1 = uint8(0); // Reserved, 8 bits } // I2C0 I2C SDA Hold Time Length Register The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW). The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode. Writes to this register succeed only when IC_ENABLE[0]=0. The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented. The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles. register IC_SDA_HOLD_t I2C0_IC_SDA_HOLD at 0x4004407c; + register uint32 I2C0_IC_SDA_HOLD_raw at 0x4004407c; + + enum IC_TX_ABRT_SOURCE_ABRT_USER_ABRT { + ABRT_USER_ABRT_VOID = 0, // Transfer abort detected by master- scenario not present + ABRT_USER_ABRT_GENERATED = 1 // Transfer abort detected by master + } + + enum IC_TX_ABRT_SOURCE_ABRT_SLVRD_INTX { + ABRT_SLVRD_INTX_VOID = 0, // Slave trying to transmit to remote master in read mode- scenario not present + ABRT_SLVRD_INTX_GENERATED = 1 // Slave trying to transmit to remote master in read mode + } + + enum IC_TX_ABRT_SOURCE_ABRT_SLV_ARBLOST { + ABRT_SLV_ARBLOST_VOID = 0, // Slave lost arbitration to remote master- scenario not present + ABRT_SLV_ARBLOST_GENERATED = 1 // Slave lost arbitration to remote master + } + + enum IC_TX_ABRT_SOURCE_ABRT_SLVFLUSH_TXFIFO { + ABRT_SLVFLUSH_TXFIFO_VOID = 0, // Slave flushes existing data in TX-FIFO upon getting read command- scenario not present + ABRT_SLVFLUSH_TXFIFO_GENERATED = 1 // Slave flushes existing data in TX-FIFO upon getting read command + } + + enum IC_TX_ABRT_SOURCE_ARB_LOST { + ABRT_LOST_VOID = 0, // Master or Slave-Transmitter lost arbitration- scenario not present + ABRT_LOST_GENERATED = 1 // Master or Slave-Transmitter lost arbitration + } + + enum IC_TX_ABRT_SOURCE_ABRT_MASTER_DIS { + ABRT_MASTER_DIS_VOID = 0, // User initiating master operation when MASTER disabled- scenario not present + ABRT_MASTER_DIS_GENERATED = 1 // User initiating master operation when MASTER disabled + } + + enum IC_TX_ABRT_SOURCE_ABRT_10B_RD_NORSTRT { + ABRT_10B_RD_VOID = 0, // Master not trying to read in 10Bit addressing mode when RESTART disabled + ABRT_10B_RD_GENERATED = 1 // Master trying to read in 10Bit addressing mode when RESTART disabled + } + + enum IC_TX_ABRT_SOURCE_ABRT_SBYTE_NORSTRT { + ABRT_SBYTE_NORSTRT_VOID = 0, // User trying to send START byte when RESTART disabled- scenario not present + ABRT_SBYTE_NORSTRT_GENERATED = 1 // User trying to send START byte when RESTART disabled + } + + enum IC_TX_ABRT_SOURCE_ABRT_HS_NORSTRT { + ABRT_HS_NORSTRT_VOID = 0, // User trying to switch Master to HS mode when RESTART disabled- scenario not present + ABRT_HS_NORSTRT_GENERATED = 1 // User trying to switch Master to HS mode when RESTART disabled + } + + enum IC_TX_ABRT_SOURCE_ABRT_SBYTE_ACKDET { + ABRT_SBYTE_ACKDET_VOID = 0, // ACK detected for START byte- scenario not present + ABRT_SBYTE_ACKDET_GENERATED = 1 // ACK detected for START byte + } + + enum IC_TX_ABRT_SOURCE_ABRT_HS_ACKDET { + ABRT_HS_ACK_VOID = 0, // HS Master code ACKed in HS Mode- scenario not present + ABRT_HS_ACK_GENERATED = 1 // HS Master code ACKed in HS Mode + } + + enum IC_TX_ABRT_SOURCE_ABRT_GCALL_READ { + ABRT_GCALL_READ_VOID = 0, // GCALL is followed by read from bus-scenario not present + ABRT_GCALL_READ_GENERATED = 1 // GCALL is followed by read from bus + } + + enum IC_TX_ABRT_SOURCE_ABRT_GCALL_NOACK { + ABRT_GCALL_NOACK_VOID = 0, // GCALL not ACKed by any slave-scenario not present + ABRT_GCALL_NOACK_GENERATED = 1 // GCALL not ACKed by any slave + } + + enum IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK { + ABRT_TXDATA_NOACK_VOID = 0, // Transmitted data non-ACKed by addressed slave-scenario not present + ABRT_TXDATA_NOACK_GENERATED = 1 // Transmitted data not ACKed by addressed slave + } + + enum IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK { + INACTIVE = 0, // This abort is not generated + ACTIVE = 1 // Byte 2 of 10Bit Address not ACKed by any slave + } + + enum IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK { + INACTIVE = 0, // This abort is not generated + ACTIVE = 1 // Byte 1 of 10Bit Address not ACKed by any slave + } + + enum IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK { + INACTIVE = 0, // This abort is not generated + ACTIVE = 1 // This abort is generated because of NOACK for 7-bit address + } type IC_TX_ABRT_SOURCE_t { ABRT_7B_ADDR_NOACK = false; // This field indicates that the Master is in 7-bit addressing mode and the address sent was not acknowledged by any slave. Reset value: 0x0 Role of DW_apb_i2c: Master-Transmitter or Master-Receiver @@ -8495,72 +12593,126 @@ // I2C0 I2C Transmit Abort Source Register This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted. register IC_TX_ABRT_SOURCE_t I2C0_IC_TX_ABRT_SOURCE at 0x40044080; + register uint32 I2C0_IC_TX_ABRT_SOURCE_raw at 0x40044080; + + enum IC_SLV_DATA_NACK_ONLY_NACK { + DISABLED = 0, // Slave receiver generates NACK normally + ENABLED = 1 // Slave receiver generates NACK upon data reception only + } type IC_SLV_DATA_NACK_ONLY_t { - NACK = false; // Generate NACK. This NACK generation only occurs when DW_apb_i2c is a slave-receiver. If this register is set to a value of 1, it can only generate a NACK after a data byte is received; hence, the data transfer is aborted and the data received is not pushed to the receive buffer. When the register is set to a value of 0, it generates NACK/ACK, depending on normal criteria. - 1: generate NACK after data byte received - 0: generate NACK/ACK normally Reset value: 0x0 + NACK = false; // Generate NACK. This NACK generation only occurs when DW_apb_i2c is a slave-receiver. If this register is set to a value of 1, it can only generate a NACK after a data byte is received; hence, the data transfer is aborted and the data received is not pushed to the receive buffer. When the register is set to a value of 0, it generates NACK/ACK, depending on normal criteria. - 1: generate NACK after data byte received - 0: generate NACK/ACK normally Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Generate Slave Data NACK Register The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect. A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit. register IC_SLV_DATA_NACK_ONLY_t I2C0_IC_SLV_DATA_NACK_ONLY at 0x40044084; + register uint32 I2C0_IC_SLV_DATA_NACK_ONLY_raw at 0x40044084; + + enum IC_DMA_CR_TDMAE { + DISABLED = 0, // transmit FIFO DMA channel disabled + ENABLED = 1 // Transmit FIFO DMA channel enabled + } + + enum IC_DMA_CR_RDMAE { + DISABLED = 0, // Receive FIFO DMA channel disabled + ENABLED = 1 // Receive FIFO DMA channel enabled + } type IC_DMA_CR_t { RDMAE = false; // Receive DMA Enable. This bit enables/disables the receive FIFO DMA channel. Reset value: 0x0 TDMAE = false; // Transmit DMA Enable. This bit enables/disables the transmit FIFO DMA channel. Reset value: 0x0 + _res1 = uint30(0); // Reserved, 30 bits } // I2C0 DMA Control Register The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE. register IC_DMA_CR_t I2C0_IC_DMA_CR at 0x40044088; + register uint32 I2C0_IC_DMA_CR_raw at 0x40044088; type IC_DMA_TDLR_t { DMATDL = uint4(0); // Transmit Data Level. This bit field controls the level at which a DMA request is made by the transmit logic. It is equal to the watermark level; that is, the dma_tx_req signal is generated when the number of valid data entries in the transmit FIFO is equal to or below this field value, and TDMAE = 1. Reset value: 0x0 + _res1 = uint28(0); // Reserved, 28 bits } // I2C0 DMA Transmit Data Level Register register IC_DMA_TDLR_t I2C0_IC_DMA_TDLR at 0x4004408c; + register uint32 I2C0_IC_DMA_TDLR_raw at 0x4004408c; type IC_DMA_RDLR_t { DMARDL = uint4(0); // Receive Data Level. This bit field controls the level at which a DMA request is made by the receive logic. The watermark level = DMARDL+1; that is, dma_rx_req is generated when the number of valid data entries in the receive FIFO is equal to or more than this field value + 1, and RDMAE =1. For instance, when DMARDL is 0, then dma_rx_req is asserted when 1 or more data entries are present in the receive FIFO. Reset value: 0x0 + _res1 = uint28(0); // Reserved, 28 bits } // I2C0 I2C Receive Data Level Register register IC_DMA_RDLR_t I2C0_IC_DMA_RDLR at 0x40044090; + register uint32 I2C0_IC_DMA_RDLR_raw at 0x40044090; type IC_SDA_SETUP_t { SDA_SETUP = uint8(0); // SDA Setup. It is recommended that if the required delay is 1000ns, then for an ic_clk frequency of 10 MHz, IC_SDA_SETUP should be programmed to a value of 11. IC_SDA_SETUP must be programmed with a minimum value of 2. + _res1 = uint24(0); // Reserved, 24 bits } // I2C0 I2C SDA Setup Register This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2. Writes to this register succeed only when IC_ENABLE[0] = 0. Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter. register IC_SDA_SETUP_t I2C0_IC_SDA_SETUP at 0x40044094; + register uint32 I2C0_IC_SDA_SETUP_raw at 0x40044094; + + enum IC_ACK_GENERAL_CALL_ACK_GEN_CALL { + DISABLED = 0, // Generate NACK for a General Call + ENABLED = 1 // Generate ACK for a General Call + } type IC_ACK_GENERAL_CALL_t { ACK_GEN_CALL = false; // ACK General Call. When set to 1, DW_apb_i2c responds with a ACK (by asserting ic_data_oe) when it receives a General Call. Otherwise, DW_apb_i2c responds with a NACK (by negating ic_data_oe). + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 I2C ACK General Call Register The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address. This register is applicable only when the DW_apb_i2c is in slave mode. register IC_ACK_GENERAL_CALL_t I2C0_IC_ACK_GENERAL_CALL at 0x40044098; + register uint32 I2C0_IC_ACK_GENERAL_CALL_raw at 0x40044098; + + enum IC_ENABLE_STATUS_SLV_RX_DATA_LOST { + INACTIVE = 0, // Slave RX Data is not lost + ACTIVE = 1 // Slave RX Data is lost + } + + enum IC_ENABLE_STATUS_SLV_DISABLED_WHILE_BUSY { + INACTIVE = 0, // Slave is disabled when it is idle + ACTIVE = 1 // Slave is disabled when it is active + } + + enum IC_ENABLE_STATUS_IC_EN { + DISABLED = 0, // I2C disabled + ENABLED = 1 // I2C enabled + } type IC_ENABLE_STATUS_t { IC_EN = false; // ic_en Status. This bit always reflects the value driven on the output port ic_en. - When read as 1, DW_apb_i2c is deemed to be in an enabled state. - When read as 0, DW_apb_i2c is deemed completely inactive. Note: The CPU can safely read this bit anytime. When this bit is read as 0, the CPU can safely read SLV_RX_DATA_LOST (bit 2) and SLV_DISABLED_WHILE_BUSY (bit 1). Reset value: 0x0 SLV_DISABLED_WHILE_BUSY = false; // Slave Disabled While Busy (Transmit, Receive). This bit indicates if a potential or active Slave operation has been aborted due to the setting bit 0 of the IC_ENABLE register from 1 to 0. This bit is set when the CPU writes a 0 to the IC_ENABLE register while: (a) DW_apb_i2c is receiving the address byte of the Slave-Transmitter operation from a remote master; OR, (b) address and data bytes of the Slave-Receiver operation from a remote master. When read as 1, DW_apb_i2c is deemed to have forced a NACK during any part of an I2C transfer, irrespective of whether the I2C address matches the slave address set in DW_apb_i2c (IC_SAR register) OR if the transfer is completed before IC_ENABLE is set to 0 but has not taken effect. Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit will also be set to 1. When read as 0, DW_apb_i2c is deemed to have been disabled when there is master activity, or when the I2C bus is idle. Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. Reset value: 0x0 SLV_RX_DATA_LOST = false; // Slave Received Data Lost. This bit indicates if a Slave-Receiver operation has been aborted with at least one data byte received from an I2C transfer due to the setting bit 0 of IC_ENABLE from 1 to 0. When read as 1, DW_apb_i2c is deemed to have been actively engaged in an aborted I2C transfer (with matching address) and the data phase of the I2C transfer has been entered, even though a data byte has been responded with a NACK. Note: If the remote I2C master terminates the transfer with a STOP condition before the DW_apb_i2c has a chance to NACK a transfer, and IC_ENABLE[0] has been set to 0, then this bit is also set to 1. When read as 0, DW_apb_i2c is deemed to have been disabled without being actively involved in the data phase of a Slave-Receiver transfer. Note: The CPU can safely read this bit when IC_EN (bit 0) is read as 0. Reset value: 0x0 + _res1 = uint29(0); // Reserved, 29 bits } // I2C0 I2C Enable Status Register The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled. If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1. If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'. Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities. register IC_ENABLE_STATUS_t I2C0_IC_ENABLE_STATUS at 0x4004409c; + register uint32 I2C0_IC_ENABLE_STATUS_raw at 0x4004409c; type IC_FS_SPKLEN_t { IC_FS_SPKLEN = uint8(0); // This register must be set before any I2C bus transaction can take place to ensure stable operation. This register sets the duration, measured in ic_clk cycles, of the longest spike in the SCL or SDA lines that will be filtered out by the spike suppression logic. This register can be written only when the I2C interface is disabled which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. The minimum valid value is 1; hardware prevents values less than this being written, and if attempted results in 1 being set. or more information, refer to 'Spike Suppression'. + _res1 = uint24(0); // Reserved, 24 bits } // I2C0 I2C SS, FS or FM+ spike suppression limit This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1. register IC_FS_SPKLEN_t I2C0_IC_FS_SPKLEN at 0x400440a0; + register uint32 I2C0_IC_FS_SPKLEN_raw at 0x400440a0; type IC_CLR_RESTART_DET_t { CLR_RESTART_DET = false; // Read this register to clear the RESTART_DET interrupt (bit 12) of IC_RAW_INTR_STAT register. Reset value: 0x0 + _res1 = uint31(0); // Reserved, 31 bits } // I2C0 Clear RESTART_DET Interrupt Register register IC_CLR_RESTART_DET_t I2C0_IC_CLR_RESTART_DET at 0x400440a8; + register uint32 I2C0_IC_CLR_RESTART_DET_raw at 0x400440a8; type IC_COMP_PARAM_1_t { APB_DATA_WIDTH = uint2(0); // APB data bus width is 32 bits @@ -8571,10 +12723,12 @@ ADD_ENCODED_PARAMS = false; // Encoded parameters not visible RX_BUFFER_DEPTH = uint8(0); // RX Buffer Depth = 16 TX_BUFFER_DEPTH = uint8(0); // TX Buffer Depth = 16 + _res1 = uint8(0); // Reserved, 8 bits } // I2C0 Component Parameter Register 1 Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters register IC_COMP_PARAM_1_t I2C0_IC_COMP_PARAM_1 at 0x400440f4; + register uint32 I2C0_IC_COMP_PARAM_1_raw at 0x400440f4; type IC_COMP_VERSION_t { IC_COMP_VERSION = uint32(0); // @@ -8582,6 +12736,7 @@ // I2C0 I2C Component Version Register register IC_COMP_VERSION_t I2C0_IC_COMP_VERSION at 0x400440f8; + register uint32 I2C0_IC_COMP_VERSION_raw at 0x400440f8; type IC_COMP_TYPE_t { IC_COMP_TYPE = uint32(0); // Designware Component Type number = 0x44_57_01_40. This assigned unique hex value is constant and is derived from the two ASCII letters 'DW' followed by a 16-bit unsigned number. @@ -8589,345 +12744,442 @@ // I2C0 I2C Component Type Register register IC_COMP_TYPE_t I2C0_IC_COMP_TYPE at 0x400440fc; + register uint32 I2C0_IC_COMP_TYPE_raw at 0x400440fc; /* Types and registers for I2C1 */ // I2C1 I2C Control Register. This register can be written only when the DW_apb_i2c is disabled, which corresponds to the IC_ENABLE[0] register being set to 0. Writes at other times have no effect. Read/Write Access: - bit 10 is read only. - bit 11 is read only - bit 16 is read only - bit 17 is read only - bits 18 and 19 are read only. register IC_CON_t I2C1_IC_CON at 0x40048000; + register uint32 I2C1_IC_CON_raw at 0x40048000; // I2C1 I2C Target Address Register This register is 12 bits wide, and bits 31:12 are reserved. This register can be written to only when IC_ENABLE[0] is set to 0. Note: If the software or application is aware that the DW_apb_i2c is not using the TAR address for the pending commands in the Tx FIFO, then it is possible to update the TAR address even while the Tx FIFO has entries (IC_STATUS[2]= 0). - It is not necessary to perform any write to this register if DW_apb_i2c is enabled as an I2C slave only. register IC_TAR_t I2C1_IC_TAR at 0x40048004; + register uint32 I2C1_IC_TAR_raw at 0x40048004; // I2C1 I2C Slave Address Register register IC_SAR_t I2C1_IC_SAR at 0x40048008; + register uint32 I2C1_IC_SAR_raw at 0x40048008; // I2C1 I2C Rx/Tx Data Buffer and Command Register; this is the register the CPU writes to when filling the TX FIFO and the CPU reads from when retrieving bytes from RX FIFO. The size of the register changes as follows: Write: - 11 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=1 - 9 bits when IC_EMPTYFIFO_HOLD_MASTER_EN=0 Read: - 12 bits when IC_FIRST_DATA_BYTE_STATUS = 1 - 8 bits when IC_FIRST_DATA_BYTE_STATUS = 0 Note: In order for the DW_apb_i2c to continue acknowledging reads, a read command should be written for every byte that is to be received; otherwise the DW_apb_i2c will stop acknowledging. register IC_DATA_CMD_t I2C1_IC_DATA_CMD at 0x40048010; + register uint32 I2C1_IC_DATA_CMD_raw at 0x40048010; // I2C1 Standard Speed I2C Clock SCL High Count Register register IC_SS_SCL_HCNT_t I2C1_IC_SS_SCL_HCNT at 0x40048014; + register uint32 I2C1_IC_SS_SCL_HCNT_raw at 0x40048014; // I2C1 Standard Speed I2C Clock SCL Low Count Register register IC_SS_SCL_LCNT_t I2C1_IC_SS_SCL_LCNT at 0x40048018; + register uint32 I2C1_IC_SS_SCL_LCNT_raw at 0x40048018; // I2C1 Fast Mode or Fast Mode Plus I2C Clock SCL High Count Register register IC_FS_SCL_HCNT_t I2C1_IC_FS_SCL_HCNT at 0x4004801c; + register uint32 I2C1_IC_FS_SCL_HCNT_raw at 0x4004801c; // I2C1 Fast Mode or Fast Mode Plus I2C Clock SCL Low Count Register register IC_FS_SCL_LCNT_t I2C1_IC_FS_SCL_LCNT at 0x40048020; + register uint32 I2C1_IC_FS_SCL_LCNT_raw at 0x40048020; // I2C1 I2C Interrupt Status Register Each bit in this register has a corresponding mask bit in the IC_INTR_MASK register. These bits are cleared by reading the matching interrupt clear register. The unmasked raw versions of these bits are available in the IC_RAW_INTR_STAT register. register IC_INTR_STAT_t I2C1_IC_INTR_STAT at 0x4004802c; + register uint32 I2C1_IC_INTR_STAT_raw at 0x4004802c; // I2C1 I2C Interrupt Mask Register. These bits mask their corresponding interrupt status bits. This register is active low; a value of 0 masks the interrupt, whereas a value of 1 unmasks the interrupt. register IC_INTR_MASK_t I2C1_IC_INTR_MASK at 0x40048030; + register uint32 I2C1_IC_INTR_MASK_raw at 0x40048030; // I2C1 I2C Raw Interrupt Status Register Unlike the IC_INTR_STAT register, these bits are not masked so they always show the true status of the DW_apb_i2c. register IC_RAW_INTR_STAT_t I2C1_IC_RAW_INTR_STAT at 0x40048034; + register uint32 I2C1_IC_RAW_INTR_STAT_raw at 0x40048034; // I2C1 I2C Receive FIFO Threshold Register register IC_RX_TL_t I2C1_IC_RX_TL at 0x40048038; + register uint32 I2C1_IC_RX_TL_raw at 0x40048038; // I2C1 I2C Transmit FIFO Threshold Register register IC_TX_TL_t I2C1_IC_TX_TL at 0x4004803c; + register uint32 I2C1_IC_TX_TL_raw at 0x4004803c; // I2C1 Clear Combined and Individual Interrupt Register register IC_CLR_INTR_t I2C1_IC_CLR_INTR at 0x40048040; + register uint32 I2C1_IC_CLR_INTR_raw at 0x40048040; // I2C1 Clear RX_UNDER Interrupt Register register IC_CLR_RX_UNDER_t I2C1_IC_CLR_RX_UNDER at 0x40048044; + register uint32 I2C1_IC_CLR_RX_UNDER_raw at 0x40048044; // I2C1 Clear RX_OVER Interrupt Register register IC_CLR_RX_OVER_t I2C1_IC_CLR_RX_OVER at 0x40048048; + register uint32 I2C1_IC_CLR_RX_OVER_raw at 0x40048048; // I2C1 Clear TX_OVER Interrupt Register register IC_CLR_TX_OVER_t I2C1_IC_CLR_TX_OVER at 0x4004804c; + register uint32 I2C1_IC_CLR_TX_OVER_raw at 0x4004804c; // I2C1 Clear RD_REQ Interrupt Register register IC_CLR_RD_REQ_t I2C1_IC_CLR_RD_REQ at 0x40048050; + register uint32 I2C1_IC_CLR_RD_REQ_raw at 0x40048050; // I2C1 Clear TX_ABRT Interrupt Register register IC_CLR_TX_ABRT_t I2C1_IC_CLR_TX_ABRT at 0x40048054; + register uint32 I2C1_IC_CLR_TX_ABRT_raw at 0x40048054; // I2C1 Clear RX_DONE Interrupt Register register IC_CLR_RX_DONE_t I2C1_IC_CLR_RX_DONE at 0x40048058; + register uint32 I2C1_IC_CLR_RX_DONE_raw at 0x40048058; // I2C1 Clear ACTIVITY Interrupt Register register IC_CLR_ACTIVITY_t I2C1_IC_CLR_ACTIVITY at 0x4004805c; + register uint32 I2C1_IC_CLR_ACTIVITY_raw at 0x4004805c; // I2C1 Clear STOP_DET Interrupt Register register IC_CLR_STOP_DET_t I2C1_IC_CLR_STOP_DET at 0x40048060; + register uint32 I2C1_IC_CLR_STOP_DET_raw at 0x40048060; // I2C1 Clear START_DET Interrupt Register register IC_CLR_START_DET_t I2C1_IC_CLR_START_DET at 0x40048064; + register uint32 I2C1_IC_CLR_START_DET_raw at 0x40048064; // I2C1 Clear GEN_CALL Interrupt Register register IC_CLR_GEN_CALL_t I2C1_IC_CLR_GEN_CALL at 0x40048068; + register uint32 I2C1_IC_CLR_GEN_CALL_raw at 0x40048068; // I2C1 I2C Enable Register register IC_ENABLE_t I2C1_IC_ENABLE at 0x4004806c; + register uint32 I2C1_IC_ENABLE_raw at 0x4004806c; // I2C1 I2C Status Register This is a read-only register used to indicate the current transfer status and FIFO status. The status register may be read at any time. None of the bits in this register request an interrupt. When the I2C is disabled by writing 0 in bit 0 of the IC_ENABLE register: - Bits 1 and 2 are set to 1 - Bits 3 and 10 are set to 0 When the master or slave state machines goes to idle and ic_en=0: - Bits 5 and 6 are set to 0 register IC_STATUS_t I2C1_IC_STATUS at 0x40048070; + register uint32 I2C1_IC_STATUS_raw at 0x40048070; // I2C1 I2C Transmit FIFO Level Register This register contains the number of valid data entries in the transmit FIFO buffer. It is cleared whenever: - The I2C is disabled - There is a transmit abort - that is, TX_ABRT bit is set in the IC_RAW_INTR_STAT register - The slave bulk transmit mode is aborted The register increments whenever data is placed into the transmit FIFO and decrements when data is taken from the transmit FIFO. register IC_TXFLR_t I2C1_IC_TXFLR at 0x40048074; + register uint32 I2C1_IC_TXFLR_raw at 0x40048074; // I2C1 I2C Receive FIFO Level Register This register contains the number of valid data entries in the receive FIFO buffer. It is cleared whenever: - The I2C is disabled - Whenever there is a transmit abort caused by any of the events tracked in IC_TX_ABRT_SOURCE The register increments whenever data is placed into the receive FIFO and decrements when data is taken from the receive FIFO. register IC_RXFLR_t I2C1_IC_RXFLR at 0x40048078; + register uint32 I2C1_IC_RXFLR_raw at 0x40048078; // I2C1 I2C SDA Hold Time Length Register The bits [15:0] of this register are used to control the hold time of SDA during transmit in both slave and master mode (after SCL goes from HIGH to LOW). The bits [23:16] of this register are used to extend the SDA transition (if any) whenever SCL is HIGH in the receiver in either master or slave mode. Writes to this register succeed only when IC_ENABLE[0]=0. The values in this register are in units of ic_clk period. The value programmed in IC_SDA_TX_HOLD must be greater than the minimum hold time in each mode (one cycle in master mode, seven cycles in slave mode) for the value to be implemented. The programmed SDA hold time during transmit (IC_SDA_TX_HOLD) cannot exceed at any time the duration of the low part of scl. Therefore the programmed value cannot be larger than N_SCL_LOW-2, where N_SCL_LOW is the duration of the low part of the scl period measured in ic_clk cycles. register IC_SDA_HOLD_t I2C1_IC_SDA_HOLD at 0x4004807c; + register uint32 I2C1_IC_SDA_HOLD_raw at 0x4004807c; // I2C1 I2C Transmit Abort Source Register This register has 32 bits that indicate the source of the TX_ABRT bit. Except for Bit 9, this register is cleared whenever the IC_CLR_TX_ABRT register or the IC_CLR_INTR register is read. To clear Bit 9, the source of the ABRT_SBYTE_NORSTRT must be fixed first; RESTART must be enabled (IC_CON[5]=1), the SPECIAL bit must be cleared (IC_TAR[11]), or the GC_OR_START bit must be cleared (IC_TAR[10]). Once the source of the ABRT_SBYTE_NORSTRT is fixed, then this bit can be cleared in the same manner as other bits in this register. If the source of the ABRT_SBYTE_NORSTRT is not fixed before attempting to clear this bit, Bit 9 clears for one cycle and is then re-asserted. register IC_TX_ABRT_SOURCE_t I2C1_IC_TX_ABRT_SOURCE at 0x40048080; + register uint32 I2C1_IC_TX_ABRT_SOURCE_raw at 0x40048080; // I2C1 Generate Slave Data NACK Register The register is used to generate a NACK for the data part of a transfer when DW_apb_i2c is acting as a slave-receiver. This register only exists when the IC_SLV_DATA_NACK_ONLY parameter is set to 1. When this parameter disabled, this register does not exist and writing to the register's address has no effect. A write can occur on this register if both of the following conditions are met: - DW_apb_i2c is disabled (IC_ENABLE[0] = 0) - Slave part is inactive (IC_STATUS[6] = 0) Note: The IC_STATUS[6] is a register read-back location for the internal slv_activity signal; the user should poll this before writing the ic_slv_data_nack_only bit. register IC_SLV_DATA_NACK_ONLY_t I2C1_IC_SLV_DATA_NACK_ONLY at 0x40048084; + register uint32 I2C1_IC_SLV_DATA_NACK_ONLY_raw at 0x40048084; // I2C1 DMA Control Register The register is used to enable the DMA Controller interface operation. There is a separate bit for transmit and receive. This can be programmed regardless of the state of IC_ENABLE. register IC_DMA_CR_t I2C1_IC_DMA_CR at 0x40048088; + register uint32 I2C1_IC_DMA_CR_raw at 0x40048088; // I2C1 DMA Transmit Data Level Register register IC_DMA_TDLR_t I2C1_IC_DMA_TDLR at 0x4004808c; + register uint32 I2C1_IC_DMA_TDLR_raw at 0x4004808c; // I2C1 I2C Receive Data Level Register register IC_DMA_RDLR_t I2C1_IC_DMA_RDLR at 0x40048090; + register uint32 I2C1_IC_DMA_RDLR_raw at 0x40048090; // I2C1 I2C SDA Setup Register This register controls the amount of time delay (in terms of number of ic_clk clock periods) introduced in the rising edge of SCL - relative to SDA changing - when DW_apb_i2c services a read request in a slave-transmitter operation. The relevant I2C requirement is tSU:DAT (note 4) as detailed in the I2C Bus Specification. This register must be programmed with a value equal to or greater than 2. Writes to this register succeed only when IC_ENABLE[0] = 0. Note: The length of setup time is calculated using [(IC_SDA_SETUP - 1) * (ic_clk_period)], so if the user requires 10 ic_clk periods of setup time, they should program a value of 11. The IC_SDA_SETUP register is only used by the DW_apb_i2c when operating as a slave transmitter. register IC_SDA_SETUP_t I2C1_IC_SDA_SETUP at 0x40048094; + register uint32 I2C1_IC_SDA_SETUP_raw at 0x40048094; // I2C1 I2C ACK General Call Register The register controls whether DW_apb_i2c responds with a ACK or NACK when it receives an I2C General Call address. This register is applicable only when the DW_apb_i2c is in slave mode. register IC_ACK_GENERAL_CALL_t I2C1_IC_ACK_GENERAL_CALL at 0x40048098; + register uint32 I2C1_IC_ACK_GENERAL_CALL_raw at 0x40048098; // I2C1 I2C Enable Status Register The register is used to report the DW_apb_i2c hardware status when the IC_ENABLE[0] register is set from 1 to 0; that is, when DW_apb_i2c is disabled. If IC_ENABLE[0] has been set to 1, bits 2:1 are forced to 0, and bit 0 is forced to 1. If IC_ENABLE[0] has been set to 0, bits 2:1 is only be valid as soon as bit 0 is read as '0'. Note: When IC_ENABLE[0] has been set to 0, a delay occurs for bit 0 to be read as 0 because disabling the DW_apb_i2c depends on I2C bus activities. register IC_ENABLE_STATUS_t I2C1_IC_ENABLE_STATUS at 0x4004809c; + register uint32 I2C1_IC_ENABLE_STATUS_raw at 0x4004809c; // I2C1 I2C SS, FS or FM+ spike suppression limit This register is used to store the duration, measured in ic_clk cycles, of the longest spike that is filtered out by the spike suppression logic when the component is operating in SS, FS or FM+ modes. The relevant I2C requirement is tSP (table 4) as detailed in the I2C Bus Specification. This register must be programmed with a minimum value of 1. register IC_FS_SPKLEN_t I2C1_IC_FS_SPKLEN at 0x400480a0; + register uint32 I2C1_IC_FS_SPKLEN_raw at 0x400480a0; // I2C1 Clear RESTART_DET Interrupt Register register IC_CLR_RESTART_DET_t I2C1_IC_CLR_RESTART_DET at 0x400480a8; + register uint32 I2C1_IC_CLR_RESTART_DET_raw at 0x400480a8; // I2C1 Component Parameter Register 1 Note This register is not implemented and therefore reads as 0. If it was implemented it would be a constant read-only register that contains encoded information about the component's parameter settings. Fields shown below are the settings for those parameters register IC_COMP_PARAM_1_t I2C1_IC_COMP_PARAM_1 at 0x400480f4; + register uint32 I2C1_IC_COMP_PARAM_1_raw at 0x400480f4; // I2C1 I2C Component Version Register register IC_COMP_VERSION_t I2C1_IC_COMP_VERSION at 0x400480f8; + register uint32 I2C1_IC_COMP_VERSION_raw at 0x400480f8; // I2C1 I2C Component Type Register register IC_COMP_TYPE_t I2C1_IC_COMP_TYPE at 0x400480fc; + register uint32 I2C1_IC_COMP_TYPE_raw at 0x400480fc; /* Types and registers for SPI0 */ type SSPCR0_t { - DSS = uint4(0); // Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. 1110 15-bit data. 1111 16-bit data. - FRF = uint2(0); // Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame format. 10 National Microwire frame format. 11 Reserved, undefined operation. - SPO = false; // SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. - SPH = false; // SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. - SCR = uint8(0); // Serial clock rate. The value SCR is used to generate the transmit and receive bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and SCR is a value from 0-255. + DSS = uint4(0); // Data Size Select: 0000 Reserved, undefined operation. 0001 Reserved, undefined operation. 0010 Reserved, undefined operation. 0011 4-bit data. 0100 5-bit data. 0101 6-bit data. 0110 7-bit data. 0111 8-bit data. 1000 9-bit data. 1001 10-bit data. 1010 11-bit data. 1011 12-bit data. 1100 13-bit data. 1101 14-bit data. 1110 15-bit data. 1111 16-bit data. + FRF = uint2(0); // Frame format: 00 Motorola SPI frame format. 01 TI synchronous serial frame format. 10 National Microwire frame format. 11 Reserved, undefined operation. + SPO = false; // SSPCLKOUT polarity, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + SPH = false; // SSPCLKOUT phase, applicable to Motorola SPI frame format only. See Motorola SPI frame format on page 2-10. + SCR = uint8(0); // Serial clock rate. The value SCR is used to generate the transmit and receive bit rate of the PrimeCell SSP. The bit rate is: F SSPCLK CPSDVSR x (1+SCR) where CPSDVSR is an even value from 2-254, programmed through the SSPCPSR register and SCR is a value from 0-255. + _res1 = uint16(0); // Reserved, 16 bits } // SPI0 Control register 0, SSPCR0 on page 3-4 register SSPCR0_t SPI0_SSPCR0 at 0x4003c000; + register uint32 SPI0_SSPCR0_raw at 0x4003c000; type SSPCR1_t { - LBM = false; // Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit serial shifter is connected to input of receive serial shifter internally. - SSE = false; // Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation enabled. - MS = false; // Master or slave mode select. This bit can be modified only when the PrimeCell SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device configured as slave. - SOD = false; // Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast a message to all slaves in the system while ensuring that only one slave drives data onto its serial output line. In such systems the RXD lines from multiple slaves could be tied together. To operate in such systems, the SOD bit can be set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD output in slave mode. + LBM = false; // Loop back mode: 0 Normal serial port operation enabled. 1 Output of transmit serial shifter is connected to input of receive serial shifter internally. + SSE = false; // Synchronous serial port enable: 0 SSP operation disabled. 1 SSP operation enabled. + MS = false; // Master or slave mode select. This bit can be modified only when the PrimeCell SSP is disabled, SSE=0: 0 Device configured as master, default. 1 Device configured as slave. + SOD = false; // Slave-mode output disable. This bit is relevant only in the slave mode, MS=1. In multiple-slave systems, it is possible for an PrimeCell SSP master to broadcast a message to all slaves in the system while ensuring that only one slave drives data onto its serial output line. In such systems the RXD lines from multiple slaves could be tied together. To operate in such systems, the SOD bit can be set if the PrimeCell SSP slave is not supposed to drive the SSPTXD line: 0 SSP can drive the SSPTXD output in slave mode. 1 SSP must not drive the SSPTXD output in slave mode. + _res1 = uint28(0); // Reserved, 28 bits } // SPI0 Control register 1, SSPCR1 on page 3-5 register SSPCR1_t SPI0_SSPCR1 at 0x4003c004; + register uint32 SPI0_SSPCR1_raw at 0x4003c004; type SSPDR_t { - DATA = uint16(0); // Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must right-justify data when the PrimeCell SSP is programmed for a data size that is less than 16 bits. Unused bits at the top are ignored by transmit logic. The receive logic automatically right-justifies. + DATA = uint16(0); // Transmit/Receive FIFO: Read Receive FIFO. Write Transmit FIFO. You must right-justify data when the PrimeCell SSP is programmed for a data size that is less than 16 bits. Unused bits at the top are ignored by transmit logic. The receive logic automatically right-justifies. + _res1 = uint16(0); // Reserved, 16 bits } // SPI0 Data register, SSPDR on page 3-6 register SSPDR_t SPI0_SSPDR at 0x4003c008; + register uint32 SPI0_SSPDR_raw at 0x4003c008; type SSPSR_t { - TFE = false; // Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. - TNF = false; // Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not full. - RNE = false; // Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not empty. - RFF = false; // Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. - BSY = false; // PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting and/or receiving a frame or the transmit FIFO is not empty. + TFE = false; // Transmit FIFO empty, RO: 0 Transmit FIFO is not empty. 1 Transmit FIFO is empty. + TNF = false; // Transmit FIFO not full, RO: 0 Transmit FIFO is full. 1 Transmit FIFO is not full. + RNE = false; // Receive FIFO not empty, RO: 0 Receive FIFO is empty. 1 Receive FIFO is not empty. + RFF = false; // Receive FIFO full, RO: 0 Receive FIFO is not full. 1 Receive FIFO is full. + BSY = false; // PrimeCell SSP busy flag, RO: 0 SSP is idle. 1 SSP is currently transmitting and/or receiving a frame or the transmit FIFO is not empty. + _res1 = uint27(0); // Reserved, 27 bits } // SPI0 Status register, SSPSR on page 3-7 register SSPSR_t SPI0_SSPSR at 0x4003c00c; + register uint32 SPI0_SSPSR_raw at 0x4003c00c; type SSPCPSR_t { CPSDVSR = uint8(0); // Clock prescale divisor. Must be an even number from 2-254, depending on the frequency of SSPCLK. The least significant bit always returns zero on reads. + _res1 = uint24(0); // Reserved, 24 bits } // SPI0 Clock prescale register, SSPCPSR on page 3-8 register SSPCPSR_t SPI0_SSPCPSR at 0x4003c010; + register uint32 SPI0_SSPCPSR_raw at 0x4003c010; type SSPIMSC_t { RORIM = false; // Receive overrun interrupt mask: 0 Receive FIFO written to while full condition interrupt is masked. 1 Receive FIFO written to while full condition interrupt is not masked. RTIM = false; // Receive timeout interrupt mask: 0 Receive FIFO not empty and no read prior to timeout period interrupt is masked. 1 Receive FIFO not empty and no read prior to timeout period interrupt is not masked. RXIM = false; // Receive FIFO interrupt mask: 0 Receive FIFO half full or less condition interrupt is masked. 1 Receive FIFO half full or less condition interrupt is not masked. TXIM = false; // Transmit FIFO interrupt mask: 0 Transmit FIFO half empty or less condition interrupt is masked. 1 Transmit FIFO half empty or less condition interrupt is not masked. + _res1 = uint28(0); // Reserved, 28 bits } // SPI0 Interrupt mask set or clear register, SSPIMSC on page 3-9 register SSPIMSC_t SPI0_SSPIMSC at 0x4003c014; + register uint32 SPI0_SSPIMSC_raw at 0x4003c014; type SSPRIS_t { RORRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPRORINTR interrupt RTRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPRTINTR interrupt RXRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPRXINTR interrupt TXRIS = false; // Gives the raw interrupt state, prior to masking, of the SSPTXINTR interrupt + _res1 = uint28(0); // Reserved, 28 bits } // SPI0 Raw interrupt status register, SSPRIS on page 3-10 register SSPRIS_t SPI0_SSPRIS at 0x4003c018; + register uint32 SPI0_SSPRIS_raw at 0x4003c018; type SSPMIS_t { RORMIS = false; // Gives the receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt RTMIS = false; // Gives the receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt RXMIS = false; // Gives the receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt TXMIS = false; // Gives the transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt + _res1 = uint28(0); // Reserved, 28 bits } // SPI0 Masked interrupt status register, SSPMIS on page 3-11 register SSPMIS_t SPI0_SSPMIS at 0x4003c01c; + register uint32 SPI0_SSPMIS_raw at 0x4003c01c; type SSPICR_t { RORIC = false; // Clears the SSPRORINTR interrupt RTIC = false; // Clears the SSPRTINTR interrupt + _res1 = uint30(0); // Reserved, 30 bits } // SPI0 Interrupt clear register, SSPICR on page 3-11 register SSPICR_t SPI0_SSPICR at 0x4003c020; + register uint32 SPI0_SSPICR_raw at 0x4003c020; type SSPDMACR_t { RXDMAE = false; // Receive DMA Enable. If this bit is set to 1, DMA for the receive FIFO is enabled. TXDMAE = false; // Transmit DMA Enable. If this bit is set to 1, DMA for the transmit FIFO is enabled. + _res1 = uint30(0); // Reserved, 30 bits } // SPI0 DMA control register, SSPDMACR on page 3-12 register SSPDMACR_t SPI0_SSPDMACR at 0x4003c024; + register uint32 SPI0_SSPDMACR_raw at 0x4003c024; type SSPPERIPHID0_t { PARTNUMBER0 = uint8(0); // These bits read back as 0x22 + _res1 = uint24(0); // Reserved, 24 bits } // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 register SSPPERIPHID0_t SPI0_SSPPERIPHID0 at 0x4003cfe0; + register uint32 SPI0_SSPPERIPHID0_raw at 0x4003cfe0; type SSPPERIPHID1_t { PARTNUMBER1 = uint4(0); // These bits read back as 0x0 DESIGNER0 = uint4(0); // These bits read back as 0x1 + _res1 = uint24(0); // Reserved, 24 bits } // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 register SSPPERIPHID1_t SPI0_SSPPERIPHID1 at 0x4003cfe4; + register uint32 SPI0_SSPPERIPHID1_raw at 0x4003cfe4; type SSPPERIPHID2_t { DESIGNER1 = uint4(0); // These bits read back as 0x4 REVISION = uint4(0); // These bits return the peripheral revision + _res1 = uint24(0); // Reserved, 24 bits } // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 register SSPPERIPHID2_t SPI0_SSPPERIPHID2 at 0x4003cfe8; + register uint32 SPI0_SSPPERIPHID2_raw at 0x4003cfe8; type SSPPERIPHID3_t { CONFIGURATION = uint8(0); // These bits read back as 0x00 + _res1 = uint24(0); // Reserved, 24 bits } // SPI0 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 register SSPPERIPHID3_t SPI0_SSPPERIPHID3 at 0x4003cfec; + register uint32 SPI0_SSPPERIPHID3_raw at 0x4003cfec; type SSPPCELLID0_t { SSPPCELLID0 = uint8(0); // These bits read back as 0x0D + _res1 = uint24(0); // Reserved, 24 bits } // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 register SSPPCELLID0_t SPI0_SSPPCELLID0 at 0x4003cff0; + register uint32 SPI0_SSPPCELLID0_raw at 0x4003cff0; type SSPPCELLID1_t { SSPPCELLID1 = uint8(0); // These bits read back as 0xF0 + _res1 = uint24(0); // Reserved, 24 bits } // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 register SSPPCELLID1_t SPI0_SSPPCELLID1 at 0x4003cff4; + register uint32 SPI0_SSPPCELLID1_raw at 0x4003cff4; type SSPPCELLID2_t { SSPPCELLID2 = uint8(0); // These bits read back as 0x05 + _res1 = uint24(0); // Reserved, 24 bits } // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 register SSPPCELLID2_t SPI0_SSPPCELLID2 at 0x4003cff8; + register uint32 SPI0_SSPPCELLID2_raw at 0x4003cff8; type SSPPCELLID3_t { SSPPCELLID3 = uint8(0); // These bits read back as 0xB1 + _res1 = uint24(0); // Reserved, 24 bits } // SPI0 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 register SSPPCELLID3_t SPI0_SSPPCELLID3 at 0x4003cffc; + register uint32 SPI0_SSPPCELLID3_raw at 0x4003cffc; /* Types and registers for SPI1 */ // SPI1 Control register 0, SSPCR0 on page 3-4 register SSPCR0_t SPI1_SSPCR0 at 0x40040000; + register uint32 SPI1_SSPCR0_raw at 0x40040000; // SPI1 Control register 1, SSPCR1 on page 3-5 register SSPCR1_t SPI1_SSPCR1 at 0x40040004; + register uint32 SPI1_SSPCR1_raw at 0x40040004; // SPI1 Data register, SSPDR on page 3-6 register SSPDR_t SPI1_SSPDR at 0x40040008; + register uint32 SPI1_SSPDR_raw at 0x40040008; // SPI1 Status register, SSPSR on page 3-7 register SSPSR_t SPI1_SSPSR at 0x4004000c; + register uint32 SPI1_SSPSR_raw at 0x4004000c; // SPI1 Clock prescale register, SSPCPSR on page 3-8 register SSPCPSR_t SPI1_SSPCPSR at 0x40040010; + register uint32 SPI1_SSPCPSR_raw at 0x40040010; // SPI1 Interrupt mask set or clear register, SSPIMSC on page 3-9 register SSPIMSC_t SPI1_SSPIMSC at 0x40040014; + register uint32 SPI1_SSPIMSC_raw at 0x40040014; // SPI1 Raw interrupt status register, SSPRIS on page 3-10 register SSPRIS_t SPI1_SSPRIS at 0x40040018; + register uint32 SPI1_SSPRIS_raw at 0x40040018; // SPI1 Masked interrupt status register, SSPMIS on page 3-11 register SSPMIS_t SPI1_SSPMIS at 0x4004001c; + register uint32 SPI1_SSPMIS_raw at 0x4004001c; // SPI1 Interrupt clear register, SSPICR on page 3-11 register SSPICR_t SPI1_SSPICR at 0x40040020; + register uint32 SPI1_SSPICR_raw at 0x40040020; // SPI1 DMA control register, SSPDMACR on page 3-12 register SSPDMACR_t SPI1_SSPDMACR at 0x40040024; + register uint32 SPI1_SSPDMACR_raw at 0x40040024; // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 register SSPPERIPHID0_t SPI1_SSPPERIPHID0 at 0x40040fe0; + register uint32 SPI1_SSPPERIPHID0_raw at 0x40040fe0; // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 register SSPPERIPHID1_t SPI1_SSPPERIPHID1 at 0x40040fe4; + register uint32 SPI1_SSPPERIPHID1_raw at 0x40040fe4; // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 register SSPPERIPHID2_t SPI1_SSPPERIPHID2 at 0x40040fe8; + register uint32 SPI1_SSPPERIPHID2_raw at 0x40040fe8; // SPI1 Peripheral identification registers, SSPPeriphID0-3 on page 3-13 register SSPPERIPHID3_t SPI1_SSPPERIPHID3 at 0x40040fec; + register uint32 SPI1_SSPPERIPHID3_raw at 0x40040fec; // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 register SSPPCELLID0_t SPI1_SSPPCELLID0 at 0x40040ff0; + register uint32 SPI1_SSPPCELLID0_raw at 0x40040ff0; // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 register SSPPCELLID1_t SPI1_SSPPCELLID1 at 0x40040ff4; + register uint32 SPI1_SSPPCELLID1_raw at 0x40040ff4; // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 register SSPPCELLID2_t SPI1_SSPPCELLID2 at 0x40040ff8; + register uint32 SPI1_SSPPCELLID2_raw at 0x40040ff8; // SPI1 PrimeCell identification registers, SSPPCellID0-3 on page 3-16 register SSPPCELLID3_t SPI1_SSPPCELLID3 at 0x40040ffc; + register uint32 SPI1_SSPPCELLID3_raw at 0x40040ffc; /* Types and registers for PIO0 @@ -8938,10 +13190,12 @@ SM_ENABLE = uint4(0); // Enable/disable each of the four state machines by writing 1/0 to each of these four bits. When disabled, a state machine will cease executing instructions, except those written directly to SMx_INSTR by the system. Multiple bits can be set/cleared at once to run/halt multiple state machines simultaneously. SM_RESTART = uint4(0); // Write 1 to instantly clear internal SM state which may be otherwise difficult to access and will affect future execution. Specifically, the following are cleared: input and output shift counters; the contents of the input shift register; the delay counter; the waiting-on-IRQ state; any stalled instruction written to SMx_INSTR or run by OUT/MOV EXEC; any pin write left asserted due to OUT_STICKY. The program counter, the contents of the output shift register and the X/Y scratch registers are not affected. CLKDIV_RESTART = uint4(0); // Restart a state machine's clock divider from an initial phase of 0. Clock dividers are free-running, so once started, their output (including fractional jitter) is completely determined by the integer/fractional divisor configured in SMx_CLKDIV. This means that, if multiple clock dividers with the same divisor are restarted simultaneously, by writing multiple 1 bits to this field, the execution clocks of those state machines will run in precise lockstep. Note that setting/clearing SM_ENABLE does not stop the clock divider from running, so once multiple state machines' clocks are synchronised, it is safe to disable/reenable a state machine, whilst keeping the clock dividers in sync. Note also that CLKDIV_RESTART can be written to whilst the state machine is running, and this is useful to resynchronise clock dividers after the divisors (SMx_CLKDIV) have been changed on-the-fly. + _res1 = uint20(0); // Reserved, 20 bits } // PIO0 PIO control register register PIO0_CTRL_t PIO0_PIO0_CTRL at 0x50200000; + register uint32 PIO0_PIO0_CTRL_raw at 0x50200000; type FSTAT_t { RXFULL = uint4(0); // State machine RX FIFO is full @@ -8951,10 +13205,12 @@ TXFULL = uint4(0); // State machine TX FIFO is full _res3 = uint4(0); // Reserved, 4 bits TXEMPTY = uint4(0); // State machine TX FIFO is empty + _res4 = uint4(0); // Reserved, 4 bits } // PIO0 FIFO status register register FSTAT_t PIO0_FSTAT at 0x50200004; + register uint32 PIO0_FSTAT_raw at 0x50200004; type FDEBUG_t { RXSTALL = uint4(0); // State machine has stalled on full RX FIFO during a blocking PUSH, or an IN with autopush enabled. This flag is also set when a nonblocking PUSH to a full FIFO took place, in which case the state machine has dropped data. Write 1 to clear. @@ -8964,10 +13220,12 @@ TXOVER = uint4(0); // TX FIFO overflow (i.e. write-on-full by the system) has occurred. Write 1 to clear. Note that write-on-full does not alter the state or contents of the FIFO in any way, but the data that the system attempted to write is dropped, so if this flag is set, your software has quite likely dropped some data on the floor. _res3 = uint4(0); // Reserved, 4 bits TXSTALL = uint4(0); // State machine has stalled on empty TX FIFO during a blocking PULL, or an OUT with autopull enabled. Write 1 to clear. + _res4 = uint4(0); // Reserved, 4 bits } // PIO0 FIFO debug register register FDEBUG_t PIO0_FDEBUG at 0x50200008; + register uint32 PIO0_FDEBUG_raw at 0x50200008; type FLEVEL_t { TX0 = uint4(0); // @@ -8982,6 +13240,7 @@ // PIO0 FIFO levels register FLEVEL_t PIO0_FLEVEL at 0x5020000c; + register uint32 PIO0_FLEVEL_raw at 0x5020000c; type TXF0_t { TXF0 = uint32(0); // @@ -8989,6 +13248,7 @@ // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. register TXF0_t PIO0_TXF0 at 0x50200010; + register uint32 PIO0_TXF0_raw at 0x50200010; type TXF1_t { TXF1 = uint32(0); // @@ -8996,6 +13256,7 @@ // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. register TXF1_t PIO0_TXF1 at 0x50200014; + register uint32 PIO0_TXF1_raw at 0x50200014; type TXF2_t { TXF2 = uint32(0); // @@ -9003,6 +13264,7 @@ // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. register TXF2_t PIO0_TXF2 at 0x50200018; + register uint32 PIO0_TXF2_raw at 0x50200018; type TXF3_t { TXF3 = uint32(0); // @@ -9010,6 +13272,7 @@ // PIO0 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. register TXF3_t PIO0_TXF3 at 0x5020001c; + register uint32 PIO0_TXF3_raw at 0x5020001c; type RXF0_t { RXF0 = uint32(0); // @@ -9017,6 +13280,7 @@ // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. register RXF0_t PIO0_RXF0 at 0x50200020; + register uint32 PIO0_RXF0_raw at 0x50200020; type RXF1_t { RXF1 = uint32(0); // @@ -9024,6 +13288,7 @@ // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. register RXF1_t PIO0_RXF1 at 0x50200024; + register uint32 PIO0_RXF1_raw at 0x50200024; type RXF2_t { RXF2 = uint32(0); // @@ -9031,6 +13296,7 @@ // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. register RXF2_t PIO0_RXF2 at 0x50200028; + register uint32 PIO0_RXF2_raw at 0x50200028; type RXF3_t { RXF3 = uint32(0); // @@ -9038,20 +13304,25 @@ // PIO0 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. register RXF3_t PIO0_RXF3 at 0x5020002c; + register uint32 PIO0_RXF3_raw at 0x5020002c; type IRQ_t { - IRQ = uint8(0); // + IRQ = uint8(0); // + _res1 = uint24(0); // Reserved, 24 bits } // PIO0 State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag. Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE. register IRQ_t PIO0_IRQ at 0x50200030; + register uint32 PIO0_IRQ_raw at 0x50200030; type IRQ_FORCE_t { IRQ_FORCE = uint8(0); // + _res1 = uint24(0); // Reserved, 24 bits } // PIO0 Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. register IRQ_FORCE_t PIO0_IRQ_FORCE at 0x50200034; + register uint32 PIO0_IRQ_FORCE_raw at 0x50200034; type INPUT_SYNC_BYPASS_t { INPUT_SYNC_BYPASS = uint32(0); // @@ -9059,6 +13330,7 @@ // PIO0 There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. 0 -> input is synchronized (default) 1 -> synchronizer is bypassed If in doubt, leave this register as all zeroes. register INPUT_SYNC_BYPASS_t PIO0_INPUT_SYNC_BYPASS at 0x50200038; + register uint32 PIO0_INPUT_SYNC_BYPASS_raw at 0x50200038; type DBG_PADOUT_t { DBG_PADOUT = uint32(0); // @@ -9066,6 +13338,7 @@ // PIO0 Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. register DBG_PADOUT_t PIO0_DBG_PADOUT at 0x5020003c; + register uint32 PIO0_DBG_PADOUT_raw at 0x5020003c; type DBG_PADOE_t { DBG_PADOE = uint32(0); // @@ -9073,6 +13346,7 @@ // PIO0 Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. register DBG_PADOE_t PIO0_DBG_PADOE at 0x50200040; + register uint32 PIO0_DBG_PADOE_raw at 0x50200040; type DBG_CFGINFO_t { FIFO_DEPTH = uint6(0); // The depth of the state machine TX/RX FIFOs, measured in words. Joining fifos via SHIFTCTRL_FJOIN gives one FIFO with double this depth. @@ -9080,234 +13354,300 @@ SM_COUNT = uint4(0); // The number of state machines this PIO instance is equipped with. _res2 = uint4(0); // Reserved, 4 bits IMEM_SIZE = uint6(0); // The size of the instruction memory, measured in units of one instruction + _res3 = uint10(0); // Reserved, 10 bits } // PIO0 The PIO hardware has some free parameters that may vary between chip products. These should be provided in the chip datasheet, but are also exposed here. register DBG_CFGINFO_t PIO0_DBG_CFGINFO at 0x50200044; + register uint32 PIO0_DBG_CFGINFO_raw at 0x50200044; type INSTR_MEM0_t { INSTR_MEM0 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 0 register INSTR_MEM0_t PIO0_INSTR_MEM0 at 0x50200048; + register uint32 PIO0_INSTR_MEM0_raw at 0x50200048; type INSTR_MEM1_t { INSTR_MEM1 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 1 register INSTR_MEM1_t PIO0_INSTR_MEM1 at 0x5020004c; + register uint32 PIO0_INSTR_MEM1_raw at 0x5020004c; type INSTR_MEM2_t { INSTR_MEM2 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 2 register INSTR_MEM2_t PIO0_INSTR_MEM2 at 0x50200050; + register uint32 PIO0_INSTR_MEM2_raw at 0x50200050; type INSTR_MEM3_t { INSTR_MEM3 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 3 register INSTR_MEM3_t PIO0_INSTR_MEM3 at 0x50200054; + register uint32 PIO0_INSTR_MEM3_raw at 0x50200054; type INSTR_MEM4_t { INSTR_MEM4 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 4 register INSTR_MEM4_t PIO0_INSTR_MEM4 at 0x50200058; + register uint32 PIO0_INSTR_MEM4_raw at 0x50200058; type INSTR_MEM5_t { INSTR_MEM5 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 5 register INSTR_MEM5_t PIO0_INSTR_MEM5 at 0x5020005c; + register uint32 PIO0_INSTR_MEM5_raw at 0x5020005c; type INSTR_MEM6_t { INSTR_MEM6 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 6 register INSTR_MEM6_t PIO0_INSTR_MEM6 at 0x50200060; + register uint32 PIO0_INSTR_MEM6_raw at 0x50200060; type INSTR_MEM7_t { INSTR_MEM7 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 7 register INSTR_MEM7_t PIO0_INSTR_MEM7 at 0x50200064; + register uint32 PIO0_INSTR_MEM7_raw at 0x50200064; type INSTR_MEM8_t { INSTR_MEM8 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 8 register INSTR_MEM8_t PIO0_INSTR_MEM8 at 0x50200068; + register uint32 PIO0_INSTR_MEM8_raw at 0x50200068; type INSTR_MEM9_t { INSTR_MEM9 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 9 register INSTR_MEM9_t PIO0_INSTR_MEM9 at 0x5020006c; + register uint32 PIO0_INSTR_MEM9_raw at 0x5020006c; type INSTR_MEM10_t { INSTR_MEM10 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 10 register INSTR_MEM10_t PIO0_INSTR_MEM10 at 0x50200070; + register uint32 PIO0_INSTR_MEM10_raw at 0x50200070; type INSTR_MEM11_t { INSTR_MEM11 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 11 register INSTR_MEM11_t PIO0_INSTR_MEM11 at 0x50200074; + register uint32 PIO0_INSTR_MEM11_raw at 0x50200074; type INSTR_MEM12_t { INSTR_MEM12 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 12 register INSTR_MEM12_t PIO0_INSTR_MEM12 at 0x50200078; + register uint32 PIO0_INSTR_MEM12_raw at 0x50200078; type INSTR_MEM13_t { INSTR_MEM13 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 13 register INSTR_MEM13_t PIO0_INSTR_MEM13 at 0x5020007c; + register uint32 PIO0_INSTR_MEM13_raw at 0x5020007c; type INSTR_MEM14_t { INSTR_MEM14 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 14 register INSTR_MEM14_t PIO0_INSTR_MEM14 at 0x50200080; + register uint32 PIO0_INSTR_MEM14_raw at 0x50200080; type INSTR_MEM15_t { INSTR_MEM15 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 15 register INSTR_MEM15_t PIO0_INSTR_MEM15 at 0x50200084; + register uint32 PIO0_INSTR_MEM15_raw at 0x50200084; type INSTR_MEM16_t { INSTR_MEM16 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 16 register INSTR_MEM16_t PIO0_INSTR_MEM16 at 0x50200088; + register uint32 PIO0_INSTR_MEM16_raw at 0x50200088; type INSTR_MEM17_t { INSTR_MEM17 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 17 register INSTR_MEM17_t PIO0_INSTR_MEM17 at 0x5020008c; + register uint32 PIO0_INSTR_MEM17_raw at 0x5020008c; type INSTR_MEM18_t { INSTR_MEM18 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 18 register INSTR_MEM18_t PIO0_INSTR_MEM18 at 0x50200090; + register uint32 PIO0_INSTR_MEM18_raw at 0x50200090; type INSTR_MEM19_t { INSTR_MEM19 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 19 register INSTR_MEM19_t PIO0_INSTR_MEM19 at 0x50200094; + register uint32 PIO0_INSTR_MEM19_raw at 0x50200094; type INSTR_MEM20_t { INSTR_MEM20 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 20 register INSTR_MEM20_t PIO0_INSTR_MEM20 at 0x50200098; + register uint32 PIO0_INSTR_MEM20_raw at 0x50200098; type INSTR_MEM21_t { INSTR_MEM21 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 21 register INSTR_MEM21_t PIO0_INSTR_MEM21 at 0x5020009c; + register uint32 PIO0_INSTR_MEM21_raw at 0x5020009c; type INSTR_MEM22_t { INSTR_MEM22 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 22 register INSTR_MEM22_t PIO0_INSTR_MEM22 at 0x502000a0; + register uint32 PIO0_INSTR_MEM22_raw at 0x502000a0; type INSTR_MEM23_t { INSTR_MEM23 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 23 register INSTR_MEM23_t PIO0_INSTR_MEM23 at 0x502000a4; + register uint32 PIO0_INSTR_MEM23_raw at 0x502000a4; type INSTR_MEM24_t { INSTR_MEM24 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 24 register INSTR_MEM24_t PIO0_INSTR_MEM24 at 0x502000a8; + register uint32 PIO0_INSTR_MEM24_raw at 0x502000a8; type INSTR_MEM25_t { INSTR_MEM25 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 25 register INSTR_MEM25_t PIO0_INSTR_MEM25 at 0x502000ac; + register uint32 PIO0_INSTR_MEM25_raw at 0x502000ac; type INSTR_MEM26_t { INSTR_MEM26 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 26 register INSTR_MEM26_t PIO0_INSTR_MEM26 at 0x502000b0; + register uint32 PIO0_INSTR_MEM26_raw at 0x502000b0; type INSTR_MEM27_t { INSTR_MEM27 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 27 register INSTR_MEM27_t PIO0_INSTR_MEM27 at 0x502000b4; + register uint32 PIO0_INSTR_MEM27_raw at 0x502000b4; type INSTR_MEM28_t { INSTR_MEM28 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 28 register INSTR_MEM28_t PIO0_INSTR_MEM28 at 0x502000b8; + register uint32 PIO0_INSTR_MEM28_raw at 0x502000b8; type INSTR_MEM29_t { INSTR_MEM29 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 29 register INSTR_MEM29_t PIO0_INSTR_MEM29 at 0x502000bc; + register uint32 PIO0_INSTR_MEM29_raw at 0x502000bc; type INSTR_MEM30_t { INSTR_MEM30 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 30 register INSTR_MEM30_t PIO0_INSTR_MEM30 at 0x502000c0; + register uint32 PIO0_INSTR_MEM30_raw at 0x502000c0; type INSTR_MEM31_t { INSTR_MEM31 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Write-only access to instruction memory location 31 register INSTR_MEM31_t PIO0_INSTR_MEM31 at 0x502000c4; + register uint32 PIO0_INSTR_MEM31_raw at 0x502000c4; type SM0_CLKDIV_t { _res1 = uint8(0); // Reserved, 8 bits @@ -9317,6 +13657,12 @@ // PIO0 Clock divisor register for state machine 0 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) register SM0_CLKDIV_t PIO0_SM0_CLKDIV at 0x502000c8; + register uint32 PIO0_SM0_CLKDIV_raw at 0x502000c8; + + enum SM0_EXECCTRL_STATUS_SEL { + TXLEVEL = 0, // All-ones if TX FIFO level < N, otherwise all-zeroes + RXLEVEL = 1 // All-ones if RX FIFO level < N, otherwise all-zeroes + } type SM0_EXECCTRL_t { STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction @@ -9335,6 +13681,7 @@ // PIO0 Execution/behavioural settings for state machine 0 register SM0_EXECCTRL_t PIO0_SM0_EXECCTRL at 0x502000cc; + register uint32 PIO0_SM0_EXECCTRL_raw at 0x502000cc; type SM0_SHIFTCTRL_t { _res1 = uint16(0); // Reserved, 16 bits @@ -9350,20 +13697,25 @@ // PIO0 Control behaviour of the input/output shift registers for state machine 0 register SM0_SHIFTCTRL_t PIO0_SM0_SHIFTCTRL at 0x502000d0; + register uint32 PIO0_SM0_SHIFTCTRL_raw at 0x502000d0; type SM0_ADDR_t { SM0_ADDR = uint5(0); // + _res1 = uint27(0); // Reserved, 27 bits } // PIO0 Current instruction address of state machine 0 register SM0_ADDR_t PIO0_SM0_ADDR at 0x502000d4; + register uint32 PIO0_SM0_ADDR_raw at 0x502000d4; type SM0_INSTR_t { SM0_INSTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Read to see the instruction currently addressed by state machine 0's program counter Write to execute an instruction immediately (including jumps) and then resume execution. register SM0_INSTR_t PIO0_SM0_INSTR at 0x502000d8; + register uint32 PIO0_SM0_INSTR_raw at 0x502000d8; type SM0_PINCTRL_t { OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. @@ -9377,6 +13729,7 @@ // PIO0 State machine pin control register SM0_PINCTRL_t PIO0_SM0_PINCTRL at 0x502000dc; + register uint32 PIO0_SM0_PINCTRL_raw at 0x502000dc; type SM1_CLKDIV_t { _res1 = uint8(0); // Reserved, 8 bits @@ -9386,6 +13739,12 @@ // PIO0 Clock divisor register for state machine 1 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) register SM1_CLKDIV_t PIO0_SM1_CLKDIV at 0x502000e0; + register uint32 PIO0_SM1_CLKDIV_raw at 0x502000e0; + + enum SM1_EXECCTRL_STATUS_SEL { + TXLEVEL = 0, // All-ones if TX FIFO level < N, otherwise all-zeroes + RXLEVEL = 1 // All-ones if RX FIFO level < N, otherwise all-zeroes + } type SM1_EXECCTRL_t { STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction @@ -9404,6 +13763,7 @@ // PIO0 Execution/behavioural settings for state machine 1 register SM1_EXECCTRL_t PIO0_SM1_EXECCTRL at 0x502000e4; + register uint32 PIO0_SM1_EXECCTRL_raw at 0x502000e4; type SM1_SHIFTCTRL_t { _res1 = uint16(0); // Reserved, 16 bits @@ -9419,20 +13779,25 @@ // PIO0 Control behaviour of the input/output shift registers for state machine 1 register SM1_SHIFTCTRL_t PIO0_SM1_SHIFTCTRL at 0x502000e8; + register uint32 PIO0_SM1_SHIFTCTRL_raw at 0x502000e8; type SM1_ADDR_t { SM1_ADDR = uint5(0); // + _res1 = uint27(0); // Reserved, 27 bits } // PIO0 Current instruction address of state machine 1 register SM1_ADDR_t PIO0_SM1_ADDR at 0x502000ec; + register uint32 PIO0_SM1_ADDR_raw at 0x502000ec; type SM1_INSTR_t { SM1_INSTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Read to see the instruction currently addressed by state machine 1's program counter Write to execute an instruction immediately (including jumps) and then resume execution. register SM1_INSTR_t PIO0_SM1_INSTR at 0x502000f0; + register uint32 PIO0_SM1_INSTR_raw at 0x502000f0; type SM1_PINCTRL_t { OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. @@ -9446,6 +13811,7 @@ // PIO0 State machine pin control register SM1_PINCTRL_t PIO0_SM1_PINCTRL at 0x502000f4; + register uint32 PIO0_SM1_PINCTRL_raw at 0x502000f4; type SM2_CLKDIV_t { _res1 = uint8(0); // Reserved, 8 bits @@ -9455,6 +13821,12 @@ // PIO0 Clock divisor register for state machine 2 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) register SM2_CLKDIV_t PIO0_SM2_CLKDIV at 0x502000f8; + register uint32 PIO0_SM2_CLKDIV_raw at 0x502000f8; + + enum SM2_EXECCTRL_STATUS_SEL { + TXLEVEL = 0, // All-ones if TX FIFO level < N, otherwise all-zeroes + RXLEVEL = 1 // All-ones if RX FIFO level < N, otherwise all-zeroes + } type SM2_EXECCTRL_t { STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction @@ -9473,6 +13845,7 @@ // PIO0 Execution/behavioural settings for state machine 2 register SM2_EXECCTRL_t PIO0_SM2_EXECCTRL at 0x502000fc; + register uint32 PIO0_SM2_EXECCTRL_raw at 0x502000fc; type SM2_SHIFTCTRL_t { _res1 = uint16(0); // Reserved, 16 bits @@ -9488,20 +13861,25 @@ // PIO0 Control behaviour of the input/output shift registers for state machine 2 register SM2_SHIFTCTRL_t PIO0_SM2_SHIFTCTRL at 0x50200100; + register uint32 PIO0_SM2_SHIFTCTRL_raw at 0x50200100; type SM2_ADDR_t { SM2_ADDR = uint5(0); // + _res1 = uint27(0); // Reserved, 27 bits } // PIO0 Current instruction address of state machine 2 register SM2_ADDR_t PIO0_SM2_ADDR at 0x50200104; + register uint32 PIO0_SM2_ADDR_raw at 0x50200104; type SM2_INSTR_t { SM2_INSTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Read to see the instruction currently addressed by state machine 2's program counter Write to execute an instruction immediately (including jumps) and then resume execution. register SM2_INSTR_t PIO0_SM2_INSTR at 0x50200108; + register uint32 PIO0_SM2_INSTR_raw at 0x50200108; type SM2_PINCTRL_t { OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. @@ -9515,6 +13893,7 @@ // PIO0 State machine pin control register SM2_PINCTRL_t PIO0_SM2_PINCTRL at 0x5020010c; + register uint32 PIO0_SM2_PINCTRL_raw at 0x5020010c; type SM3_CLKDIV_t { _res1 = uint8(0); // Reserved, 8 bits @@ -9524,6 +13903,12 @@ // PIO0 Clock divisor register for state machine 3 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) register SM3_CLKDIV_t PIO0_SM3_CLKDIV at 0x50200110; + register uint32 PIO0_SM3_CLKDIV_raw at 0x50200110; + + enum SM3_EXECCTRL_STATUS_SEL { + TXLEVEL = 0, // All-ones if TX FIFO level < N, otherwise all-zeroes + RXLEVEL = 1 // All-ones if RX FIFO level < N, otherwise all-zeroes + } type SM3_EXECCTRL_t { STATUS_N = uint4(0); // Comparison level for the MOV x, STATUS instruction @@ -9542,6 +13927,7 @@ // PIO0 Execution/behavioural settings for state machine 3 register SM3_EXECCTRL_t PIO0_SM3_EXECCTRL at 0x50200114; + register uint32 PIO0_SM3_EXECCTRL_raw at 0x50200114; type SM3_SHIFTCTRL_t { _res1 = uint16(0); // Reserved, 16 bits @@ -9557,20 +13943,25 @@ // PIO0 Control behaviour of the input/output shift registers for state machine 3 register SM3_SHIFTCTRL_t PIO0_SM3_SHIFTCTRL at 0x50200118; + register uint32 PIO0_SM3_SHIFTCTRL_raw at 0x50200118; type SM3_ADDR_t { SM3_ADDR = uint5(0); // + _res1 = uint27(0); // Reserved, 27 bits } // PIO0 Current instruction address of state machine 3 register SM3_ADDR_t PIO0_SM3_ADDR at 0x5020011c; + register uint32 PIO0_SM3_ADDR_raw at 0x5020011c; type SM3_INSTR_t { SM3_INSTR = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // PIO0 Read to see the instruction currently addressed by state machine 3's program counter Write to execute an instruction immediately (including jumps) and then resume execution. register SM3_INSTR_t PIO0_SM3_INSTR at 0x50200120; + register uint32 PIO0_SM3_INSTR_raw at 0x50200120; type SM3_PINCTRL_t { OUT_BASE = uint5(0); // The lowest-numbered pin that will be affected by an OUT PINS, OUT PINDIRS or MOV PINS instruction. The data written to this pin will always be the least-significant bit of the OUT or MOV data. @@ -9584,6 +13975,7 @@ // PIO0 State machine pin control register SM3_PINCTRL_t PIO0_SM3_PINCTRL at 0x50200124; + register uint32 PIO0_SM3_PINCTRL_raw at 0x50200124; type PIO0_INTR_t { SM0_RXNEMPTY = false; // @@ -9598,10 +13990,12 @@ SM1 = false; // SM2 = false; // SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits } // PIO0 Raw Interrupts register PIO0_INTR_t PIO0_PIO0_INTR at 0x50200128; + register uint32 PIO0_PIO0_INTR_raw at 0x50200128; type IRQ0_INTE_t { SM0_RXNEMPTY = false; // @@ -9616,10 +14010,12 @@ SM1 = false; // SM2 = false; // SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits } // PIO0 Interrupt Enable for irq0 register IRQ0_INTE_t PIO0_IRQ0_INTE at 0x5020012c; + register uint32 PIO0_IRQ0_INTE_raw at 0x5020012c; type IRQ0_INTF_t { SM0_RXNEMPTY = false; // @@ -9634,10 +14030,12 @@ SM1 = false; // SM2 = false; // SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits } // PIO0 Interrupt Force for irq0 register IRQ0_INTF_t PIO0_IRQ0_INTF at 0x50200130; + register uint32 PIO0_IRQ0_INTF_raw at 0x50200130; type IRQ0_INTS_t { SM0_RXNEMPTY = false; // @@ -9652,10 +14050,12 @@ SM1 = false; // SM2 = false; // SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits } // PIO0 Interrupt status after masking & forcing for irq0 register IRQ0_INTS_t PIO0_IRQ0_INTS at 0x50200134; + register uint32 PIO0_IRQ0_INTS_raw at 0x50200134; type IRQ1_INTE_t { SM0_RXNEMPTY = false; // @@ -9670,10 +14070,12 @@ SM1 = false; // SM2 = false; // SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits } // PIO0 Interrupt Enable for irq1 register IRQ1_INTE_t PIO0_IRQ1_INTE at 0x50200138; + register uint32 PIO0_IRQ1_INTE_raw at 0x50200138; type IRQ1_INTF_t { SM0_RXNEMPTY = false; // @@ -9688,10 +14090,12 @@ SM1 = false; // SM2 = false; // SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits } // PIO0 Interrupt Force for irq1 register IRQ1_INTF_t PIO0_IRQ1_INTF at 0x5020013c; + register uint32 PIO0_IRQ1_INTF_raw at 0x5020013c; type IRQ1_INTS_t { SM0_RXNEMPTY = false; // @@ -9706,256 +14110,339 @@ SM1 = false; // SM2 = false; // SM3 = false; // + _res1 = uint20(0); // Reserved, 20 bits } // PIO0 Interrupt status after masking & forcing for irq1 register IRQ1_INTS_t PIO0_IRQ1_INTS at 0x50200140; + register uint32 PIO0_IRQ1_INTS_raw at 0x50200140; /* Types and registers for PIO1 */ // PIO1 PIO control register register PIO0_CTRL_t PIO1_CTRL at 0x50300000; + register uint32 PIO1_CTRL_raw at 0x50300000; // PIO1 FIFO status register register FSTAT_t PIO1_FSTAT at 0x50300004; + register uint32 PIO1_FSTAT_raw at 0x50300004; // PIO1 FIFO debug register register FDEBUG_t PIO1_FDEBUG at 0x50300008; + register uint32 PIO1_FDEBUG_raw at 0x50300008; // PIO1 FIFO levels register FLEVEL_t PIO1_FLEVEL at 0x5030000c; + register uint32 PIO1_FLEVEL_raw at 0x5030000c; // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. register TXF0_t PIO1_TXF0 at 0x50300010; + register uint32 PIO1_TXF0_raw at 0x50300010; // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. register TXF1_t PIO1_TXF1 at 0x50300014; + register uint32 PIO1_TXF1_raw at 0x50300014; // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. register TXF2_t PIO1_TXF2 at 0x50300018; + register uint32 PIO1_TXF2_raw at 0x50300018; // PIO1 Direct write access to the TX FIFO for this state machine. Each write pushes one word to the FIFO. Attempting to write to a full FIFO has no effect on the FIFO state or contents, and sets the sticky FDEBUG_TXOVER error flag for this FIFO. register TXF3_t PIO1_TXF3 at 0x5030001c; + register uint32 PIO1_TXF3_raw at 0x5030001c; // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. register RXF0_t PIO1_RXF0 at 0x50300020; + register uint32 PIO1_RXF0_raw at 0x50300020; // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. register RXF1_t PIO1_RXF1 at 0x50300024; + register uint32 PIO1_RXF1_raw at 0x50300024; // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. register RXF2_t PIO1_RXF2 at 0x50300028; + register uint32 PIO1_RXF2_raw at 0x50300028; // PIO1 Direct read access to the RX FIFO for this state machine. Each read pops one word from the FIFO. Attempting to read from an empty FIFO has no effect on the FIFO state, and sets the sticky FDEBUG_RXUNDER error flag for this FIFO. The data returned to the system on a read from an empty FIFO is undefined. register RXF3_t PIO1_RXF3 at 0x5030002c; + register uint32 PIO1_RXF3_raw at 0x5030002c; // PIO1 State machine IRQ flags register. Write 1 to clear. There are 8 state machine IRQ flags, which can be set, cleared, and waited on by the state machines. There's no fixed association between flags and state machines -- any state machine can use any flag. Any of the 8 flags can be used for timing synchronisation between state machines, using IRQ and WAIT instructions. The lower four of these flags are also routed out to system-level interrupt requests, alongside FIFO status interrupts -- see e.g. IRQ0_INTE. register IRQ_t PIO1_IRQ at 0x50300030; + register uint32 PIO1_IRQ_raw at 0x50300030; // PIO1 Writing a 1 to each of these bits will forcibly assert the corresponding IRQ. Note this is different to the INTF register: writing here affects PIO internal state. INTF just asserts the processor-facing IRQ signal for testing ISRs, and is not visible to the state machines. register IRQ_FORCE_t PIO1_IRQ_FORCE at 0x50300034; + register uint32 PIO1_IRQ_FORCE_raw at 0x50300034; // PIO1 There is a 2-flipflop synchronizer on each GPIO input, which protects PIO logic from metastabilities. This increases input delay, and for fast synchronous IO (e.g. SPI) these synchronizers may need to be bypassed. Each bit in this register corresponds to one GPIO. 0 -> input is synchronized (default) 1 -> synchronizer is bypassed If in doubt, leave this register as all zeroes. register INPUT_SYNC_BYPASS_t PIO1_INPUT_SYNC_BYPASS at 0x50300038; + register uint32 PIO1_INPUT_SYNC_BYPASS_raw at 0x50300038; // PIO1 Read to sample the pad output values PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. register DBG_PADOUT_t PIO1_DBG_PADOUT at 0x5030003c; + register uint32 PIO1_DBG_PADOUT_raw at 0x5030003c; // PIO1 Read to sample the pad output enables (direction) PIO is currently driving to the GPIOs. On RP2040 there are 30 GPIOs, so the two most significant bits are hardwired to 0. register DBG_PADOE_t PIO1_DBG_PADOE at 0x50300040; + register uint32 PIO1_DBG_PADOE_raw at 0x50300040; // PIO1 The PIO hardware has some free parameters that may vary between chip products. These should be provided in the chip datasheet, but are also exposed here. register DBG_CFGINFO_t PIO1_DBG_CFGINFO at 0x50300044; + register uint32 PIO1_DBG_CFGINFO_raw at 0x50300044; // PIO1 Write-only access to instruction memory location 0 register INSTR_MEM0_t PIO1_INSTR_MEM0 at 0x50300048; + register uint32 PIO1_INSTR_MEM0_raw at 0x50300048; // PIO1 Write-only access to instruction memory location 1 register INSTR_MEM1_t PIO1_INSTR_MEM1 at 0x5030004c; + register uint32 PIO1_INSTR_MEM1_raw at 0x5030004c; // PIO1 Write-only access to instruction memory location 2 register INSTR_MEM2_t PIO1_INSTR_MEM2 at 0x50300050; + register uint32 PIO1_INSTR_MEM2_raw at 0x50300050; // PIO1 Write-only access to instruction memory location 3 register INSTR_MEM3_t PIO1_INSTR_MEM3 at 0x50300054; + register uint32 PIO1_INSTR_MEM3_raw at 0x50300054; // PIO1 Write-only access to instruction memory location 4 register INSTR_MEM4_t PIO1_INSTR_MEM4 at 0x50300058; + register uint32 PIO1_INSTR_MEM4_raw at 0x50300058; // PIO1 Write-only access to instruction memory location 5 register INSTR_MEM5_t PIO1_INSTR_MEM5 at 0x5030005c; + register uint32 PIO1_INSTR_MEM5_raw at 0x5030005c; // PIO1 Write-only access to instruction memory location 6 register INSTR_MEM6_t PIO1_INSTR_MEM6 at 0x50300060; + register uint32 PIO1_INSTR_MEM6_raw at 0x50300060; // PIO1 Write-only access to instruction memory location 7 register INSTR_MEM7_t PIO1_INSTR_MEM7 at 0x50300064; + register uint32 PIO1_INSTR_MEM7_raw at 0x50300064; // PIO1 Write-only access to instruction memory location 8 register INSTR_MEM8_t PIO1_INSTR_MEM8 at 0x50300068; + register uint32 PIO1_INSTR_MEM8_raw at 0x50300068; // PIO1 Write-only access to instruction memory location 9 register INSTR_MEM9_t PIO1_INSTR_MEM9 at 0x5030006c; + register uint32 PIO1_INSTR_MEM9_raw at 0x5030006c; // PIO1 Write-only access to instruction memory location 10 register INSTR_MEM10_t PIO1_INSTR_MEM10 at 0x50300070; + register uint32 PIO1_INSTR_MEM10_raw at 0x50300070; // PIO1 Write-only access to instruction memory location 11 register INSTR_MEM11_t PIO1_INSTR_MEM11 at 0x50300074; + register uint32 PIO1_INSTR_MEM11_raw at 0x50300074; // PIO1 Write-only access to instruction memory location 12 register INSTR_MEM12_t PIO1_INSTR_MEM12 at 0x50300078; + register uint32 PIO1_INSTR_MEM12_raw at 0x50300078; // PIO1 Write-only access to instruction memory location 13 register INSTR_MEM13_t PIO1_INSTR_MEM13 at 0x5030007c; + register uint32 PIO1_INSTR_MEM13_raw at 0x5030007c; // PIO1 Write-only access to instruction memory location 14 register INSTR_MEM14_t PIO1_INSTR_MEM14 at 0x50300080; + register uint32 PIO1_INSTR_MEM14_raw at 0x50300080; // PIO1 Write-only access to instruction memory location 15 register INSTR_MEM15_t PIO1_INSTR_MEM15 at 0x50300084; + register uint32 PIO1_INSTR_MEM15_raw at 0x50300084; // PIO1 Write-only access to instruction memory location 16 register INSTR_MEM16_t PIO1_INSTR_MEM16 at 0x50300088; + register uint32 PIO1_INSTR_MEM16_raw at 0x50300088; // PIO1 Write-only access to instruction memory location 17 register INSTR_MEM17_t PIO1_INSTR_MEM17 at 0x5030008c; + register uint32 PIO1_INSTR_MEM17_raw at 0x5030008c; // PIO1 Write-only access to instruction memory location 18 register INSTR_MEM18_t PIO1_INSTR_MEM18 at 0x50300090; + register uint32 PIO1_INSTR_MEM18_raw at 0x50300090; // PIO1 Write-only access to instruction memory location 19 register INSTR_MEM19_t PIO1_INSTR_MEM19 at 0x50300094; + register uint32 PIO1_INSTR_MEM19_raw at 0x50300094; // PIO1 Write-only access to instruction memory location 20 register INSTR_MEM20_t PIO1_INSTR_MEM20 at 0x50300098; + register uint32 PIO1_INSTR_MEM20_raw at 0x50300098; // PIO1 Write-only access to instruction memory location 21 register INSTR_MEM21_t PIO1_INSTR_MEM21 at 0x5030009c; + register uint32 PIO1_INSTR_MEM21_raw at 0x5030009c; // PIO1 Write-only access to instruction memory location 22 register INSTR_MEM22_t PIO1_INSTR_MEM22 at 0x503000a0; + register uint32 PIO1_INSTR_MEM22_raw at 0x503000a0; // PIO1 Write-only access to instruction memory location 23 register INSTR_MEM23_t PIO1_INSTR_MEM23 at 0x503000a4; + register uint32 PIO1_INSTR_MEM23_raw at 0x503000a4; // PIO1 Write-only access to instruction memory location 24 register INSTR_MEM24_t PIO1_INSTR_MEM24 at 0x503000a8; + register uint32 PIO1_INSTR_MEM24_raw at 0x503000a8; // PIO1 Write-only access to instruction memory location 25 register INSTR_MEM25_t PIO1_INSTR_MEM25 at 0x503000ac; + register uint32 PIO1_INSTR_MEM25_raw at 0x503000ac; // PIO1 Write-only access to instruction memory location 26 register INSTR_MEM26_t PIO1_INSTR_MEM26 at 0x503000b0; + register uint32 PIO1_INSTR_MEM26_raw at 0x503000b0; // PIO1 Write-only access to instruction memory location 27 register INSTR_MEM27_t PIO1_INSTR_MEM27 at 0x503000b4; + register uint32 PIO1_INSTR_MEM27_raw at 0x503000b4; // PIO1 Write-only access to instruction memory location 28 register INSTR_MEM28_t PIO1_INSTR_MEM28 at 0x503000b8; + register uint32 PIO1_INSTR_MEM28_raw at 0x503000b8; // PIO1 Write-only access to instruction memory location 29 register INSTR_MEM29_t PIO1_INSTR_MEM29 at 0x503000bc; + register uint32 PIO1_INSTR_MEM29_raw at 0x503000bc; // PIO1 Write-only access to instruction memory location 30 register INSTR_MEM30_t PIO1_INSTR_MEM30 at 0x503000c0; + register uint32 PIO1_INSTR_MEM30_raw at 0x503000c0; // PIO1 Write-only access to instruction memory location 31 register INSTR_MEM31_t PIO1_INSTR_MEM31 at 0x503000c4; + register uint32 PIO1_INSTR_MEM31_raw at 0x503000c4; // PIO1 Clock divisor register for state machine 0 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) register SM0_CLKDIV_t PIO1_SM0_CLKDIV at 0x503000c8; + register uint32 PIO1_SM0_CLKDIV_raw at 0x503000c8; // PIO1 Execution/behavioural settings for state machine 0 register SM0_EXECCTRL_t PIO1_SM0_EXECCTRL at 0x503000cc; + register uint32 PIO1_SM0_EXECCTRL_raw at 0x503000cc; // PIO1 Control behaviour of the input/output shift registers for state machine 0 register SM0_SHIFTCTRL_t PIO1_SM0_SHIFTCTRL at 0x503000d0; + register uint32 PIO1_SM0_SHIFTCTRL_raw at 0x503000d0; // PIO1 Current instruction address of state machine 0 register SM0_ADDR_t PIO1_SM0_ADDR at 0x503000d4; + register uint32 PIO1_SM0_ADDR_raw at 0x503000d4; // PIO1 Read to see the instruction currently addressed by state machine 0's program counter Write to execute an instruction immediately (including jumps) and then resume execution. register SM0_INSTR_t PIO1_SM0_INSTR at 0x503000d8; + register uint32 PIO1_SM0_INSTR_raw at 0x503000d8; // PIO1 State machine pin control register SM0_PINCTRL_t PIO1_SM0_PINCTRL at 0x503000dc; + register uint32 PIO1_SM0_PINCTRL_raw at 0x503000dc; // PIO1 Clock divisor register for state machine 1 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) register SM1_CLKDIV_t PIO1_SM1_CLKDIV at 0x503000e0; + register uint32 PIO1_SM1_CLKDIV_raw at 0x503000e0; // PIO1 Execution/behavioural settings for state machine 1 register SM1_EXECCTRL_t PIO1_SM1_EXECCTRL at 0x503000e4; + register uint32 PIO1_SM1_EXECCTRL_raw at 0x503000e4; // PIO1 Control behaviour of the input/output shift registers for state machine 1 register SM1_SHIFTCTRL_t PIO1_SM1_SHIFTCTRL at 0x503000e8; + register uint32 PIO1_SM1_SHIFTCTRL_raw at 0x503000e8; // PIO1 Current instruction address of state machine 1 register SM1_ADDR_t PIO1_SM1_ADDR at 0x503000ec; + register uint32 PIO1_SM1_ADDR_raw at 0x503000ec; // PIO1 Read to see the instruction currently addressed by state machine 1's program counter Write to execute an instruction immediately (including jumps) and then resume execution. register SM1_INSTR_t PIO1_SM1_INSTR at 0x503000f0; + register uint32 PIO1_SM1_INSTR_raw at 0x503000f0; // PIO1 State machine pin control register SM1_PINCTRL_t PIO1_SM1_PINCTRL at 0x503000f4; + register uint32 PIO1_SM1_PINCTRL_raw at 0x503000f4; // PIO1 Clock divisor register for state machine 2 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) register SM2_CLKDIV_t PIO1_SM2_CLKDIV at 0x503000f8; + register uint32 PIO1_SM2_CLKDIV_raw at 0x503000f8; // PIO1 Execution/behavioural settings for state machine 2 register SM2_EXECCTRL_t PIO1_SM2_EXECCTRL at 0x503000fc; + register uint32 PIO1_SM2_EXECCTRL_raw at 0x503000fc; // PIO1 Control behaviour of the input/output shift registers for state machine 2 register SM2_SHIFTCTRL_t PIO1_SM2_SHIFTCTRL at 0x50300100; + register uint32 PIO1_SM2_SHIFTCTRL_raw at 0x50300100; // PIO1 Current instruction address of state machine 2 register SM2_ADDR_t PIO1_SM2_ADDR at 0x50300104; + register uint32 PIO1_SM2_ADDR_raw at 0x50300104; // PIO1 Read to see the instruction currently addressed by state machine 2's program counter Write to execute an instruction immediately (including jumps) and then resume execution. register SM2_INSTR_t PIO1_SM2_INSTR at 0x50300108; + register uint32 PIO1_SM2_INSTR_raw at 0x50300108; // PIO1 State machine pin control register SM2_PINCTRL_t PIO1_SM2_PINCTRL at 0x5030010c; + register uint32 PIO1_SM2_PINCTRL_raw at 0x5030010c; // PIO1 Clock divisor register for state machine 3 Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) register SM3_CLKDIV_t PIO1_SM3_CLKDIV at 0x50300110; + register uint32 PIO1_SM3_CLKDIV_raw at 0x50300110; // PIO1 Execution/behavioural settings for state machine 3 register SM3_EXECCTRL_t PIO1_SM3_EXECCTRL at 0x50300114; + register uint32 PIO1_SM3_EXECCTRL_raw at 0x50300114; // PIO1 Control behaviour of the input/output shift registers for state machine 3 register SM3_SHIFTCTRL_t PIO1_SM3_SHIFTCTRL at 0x50300118; + register uint32 PIO1_SM3_SHIFTCTRL_raw at 0x50300118; // PIO1 Current instruction address of state machine 3 register SM3_ADDR_t PIO1_SM3_ADDR at 0x5030011c; + register uint32 PIO1_SM3_ADDR_raw at 0x5030011c; // PIO1 Read to see the instruction currently addressed by state machine 3's program counter Write to execute an instruction immediately (including jumps) and then resume execution. register SM3_INSTR_t PIO1_SM3_INSTR at 0x50300120; + register uint32 PIO1_SM3_INSTR_raw at 0x50300120; // PIO1 State machine pin control register SM3_PINCTRL_t PIO1_SM3_PINCTRL at 0x50300124; + register uint32 PIO1_SM3_PINCTRL_raw at 0x50300124; // PIO1 Raw Interrupts register PIO0_INTR_t PIO1_INTR at 0x50300128; + register uint32 PIO1_INTR_raw at 0x50300128; // PIO1 Interrupt Enable for irq0 register IRQ0_INTE_t PIO1_IRQ0_INTE at 0x5030012c; + register uint32 PIO1_IRQ0_INTE_raw at 0x5030012c; // PIO1 Interrupt Force for irq0 register IRQ0_INTF_t PIO1_IRQ0_INTF at 0x50300130; + register uint32 PIO1_IRQ0_INTF_raw at 0x50300130; // PIO1 Interrupt status after masking & forcing for irq0 register IRQ0_INTS_t PIO1_IRQ0_INTS at 0x50300134; + register uint32 PIO1_IRQ0_INTS_raw at 0x50300134; // PIO1 Interrupt Enable for irq1 register IRQ1_INTE_t PIO1_IRQ1_INTE at 0x50300138; + register uint32 PIO1_IRQ1_INTE_raw at 0x50300138; // PIO1 Interrupt Force for irq1 register IRQ1_INTF_t PIO1_IRQ1_INTF at 0x5030013c; + register uint32 PIO1_IRQ1_INTF_raw at 0x5030013c; // PIO1 Interrupt status after masking & forcing for irq1 register IRQ1_INTS_t PIO1_IRQ1_INTS at 0x50300140; + register uint32 PIO1_IRQ1_INTS_raw at 0x50300140; /* Types and registers for BUSCTRL @@ -9970,73 +14457,185 @@ DMA_R = false; // 0 - low priority, 1 - high priority _res3 = uint3(0); // Reserved, 3 bits DMA_W = false; // 0 - low priority, 1 - high priority + _res4 = uint19(0); // Reserved, 19 bits } // Set the priority of each master for bus arbitration. register BUS_PRIORITY_t BUS_PRIORITY at 0x40030000; + register uint32 BUS_PRIORITY_raw at 0x40030000; type BUS_PRIORITY_ACK_t { BUS_PRIORITY_ACK = false; // Goes to 1 once all arbiters have registered the new global priority levels. Arbiters update their local priority when servicing a new nonsequential access. In normal circumstances this will happen almost immediately. + _res1 = uint31(0); // Reserved, 31 bits } // Bus priority acknowledge register BUS_PRIORITY_ACK_t BUS_PRIORITY_ACK at 0x40030004; + register uint32 BUS_PRIORITY_ACK_raw at 0x40030004; type PERFCTR0_t { PERFCTR0 = uint24(0); // Busfabric saturating performance counter 0 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL0 + _res1 = uint8(0); // Reserved, 8 bits } // Bus fabric performance counter 0 register PERFCTR0_t PERFCTR0 at 0x40030008; + register uint32 PERFCTR0_raw at 0x40030008; + + enum PERFSEL0_PERFSEL0 { + apb_contested = 0, // + apb = 1, // + fastperi_contested = 2, // + fastperi = 3, // + sram5_contested = 4, // + sram5 = 5, // + sram4_contested = 6, // + sram4 = 7, // + sram3_contested = 8, // + sram3 = 9, // + sram2_contested = 10, // + sram2 = 11, // + sram1_contested = 12, // + sram1 = 13, // + sram0_contested = 14, // + sram0 = 15, // + xip_main_contested = 16, // + xip_main = 17, // + rom_contested = 18, // + rom = 19 // + } type PERFSEL0_t { PERFSEL0 = uint5(0); // Select an event for PERFCTR0. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + _res1 = uint27(0); // Reserved, 27 bits } // Bus fabric performance event select for PERFCTR0 register PERFSEL0_t PERFSEL0 at 0x4003000c; + register uint32 PERFSEL0_raw at 0x4003000c; type PERFCTR1_t { PERFCTR1 = uint24(0); // Busfabric saturating performance counter 1 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL1 + _res1 = uint8(0); // Reserved, 8 bits } // Bus fabric performance counter 1 register PERFCTR1_t PERFCTR1 at 0x40030010; + register uint32 PERFCTR1_raw at 0x40030010; + + enum PERFSEL1_PERFSEL1 { + apb_contested = 0, // + apb = 1, // + fastperi_contested = 2, // + fastperi = 3, // + sram5_contested = 4, // + sram5 = 5, // + sram4_contested = 6, // + sram4 = 7, // + sram3_contested = 8, // + sram3 = 9, // + sram2_contested = 10, // + sram2 = 11, // + sram1_contested = 12, // + sram1 = 13, // + sram0_contested = 14, // + sram0 = 15, // + xip_main_contested = 16, // + xip_main = 17, // + rom_contested = 18, // + rom = 19 // + } type PERFSEL1_t { PERFSEL1 = uint5(0); // Select an event for PERFCTR1. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + _res1 = uint27(0); // Reserved, 27 bits } // Bus fabric performance event select for PERFCTR1 register PERFSEL1_t PERFSEL1 at 0x40030014; + register uint32 PERFSEL1_raw at 0x40030014; type PERFCTR2_t { PERFCTR2 = uint24(0); // Busfabric saturating performance counter 2 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL2 + _res1 = uint8(0); // Reserved, 8 bits } // Bus fabric performance counter 2 register PERFCTR2_t PERFCTR2 at 0x40030018; + register uint32 PERFCTR2_raw at 0x40030018; + + enum PERFSEL2_PERFSEL2 { + apb_contested = 0, // + apb = 1, // + fastperi_contested = 2, // + fastperi = 3, // + sram5_contested = 4, // + sram5 = 5, // + sram4_contested = 6, // + sram4 = 7, // + sram3_contested = 8, // + sram3 = 9, // + sram2_contested = 10, // + sram2 = 11, // + sram1_contested = 12, // + sram1 = 13, // + sram0_contested = 14, // + sram0 = 15, // + xip_main_contested = 16, // + xip_main = 17, // + rom_contested = 18, // + rom = 19 // + } type PERFSEL2_t { PERFSEL2 = uint5(0); // Select an event for PERFCTR2. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + _res1 = uint27(0); // Reserved, 27 bits } // Bus fabric performance event select for PERFCTR2 register PERFSEL2_t PERFSEL2 at 0x4003001c; + register uint32 PERFSEL2_raw at 0x4003001c; type PERFCTR3_t { PERFCTR3 = uint24(0); // Busfabric saturating performance counter 3 Count some event signal from the busfabric arbiters. Write any value to clear. Select an event to count using PERFSEL3 + _res1 = uint8(0); // Reserved, 8 bits } // Bus fabric performance counter 3 register PERFCTR3_t PERFCTR3 at 0x40030020; + register uint32 PERFCTR3_raw at 0x40030020; + + enum PERFSEL3_PERFSEL3 { + apb_contested = 0, // + apb = 1, // + fastperi_contested = 2, // + fastperi = 3, // + sram5_contested = 4, // + sram5 = 5, // + sram4_contested = 6, // + sram4 = 7, // + sram3_contested = 8, // + sram3 = 9, // + sram2_contested = 10, // + sram2 = 11, // + sram1_contested = 12, // + sram1 = 13, // + sram0_contested = 14, // + sram0 = 15, // + xip_main_contested = 16, // + xip_main = 17, // + rom_contested = 18, // + rom = 19 // + } type PERFSEL3_t { PERFSEL3 = uint5(0); // Select an event for PERFCTR3. Count either contested accesses, or all accesses, on a downstream port of the main crossbar. + _res1 = uint27(0); // Reserved, 27 bits } // Bus fabric performance event select for PERFCTR3 register PERFSEL3_t PERFSEL3 at 0x40030024; + register uint32 PERFSEL3_raw at 0x40030024; /* Types and registers for SIO @@ -10049,6 +14648,7 @@ // Processor core identifier register SIO_CPUID_t SIO_CPUID at 0xd0000000; + register uint32 SIO_CPUID_raw at 0xd0000000; type GPIO_IN_t { IO0 = false; // @@ -10086,13 +14686,16 @@ // Input value for GPIO pins register GPIO_IN_t GPIO_IN at 0xd0000004; + register uint32 GPIO_IN_raw at 0xd0000004; type GPIO_HI_IN_t { GPIO_HI_IN = uint6(0); // Input value on QSPI IO in order 0..5: SCLK, SSn, SD0, SD1, SD2, SD3 + _res1 = uint26(0); // Reserved, 26 bits } // Input value for QSPI pins register GPIO_HI_IN_t GPIO_HI_IN at 0xd0000008; + register uint32 GPIO_HI_IN_raw at 0xd0000008; type GPIO_OUT_t { IO0 = false; // @@ -10130,6 +14733,7 @@ // GPIO output value: Set output level (1/0 -> high/low) for GPIO0...29. Reading back gives the last value written, NOT the input value from the pins. If core 0 and core 1 both write to GPIO_OUT simultaneously (or to a SET/CLR/XOR alias), the result is as though the write from core 0 took place first, and the write from core 1 was then applied to that intermediate result. register GPIO_OUT_t GPIO_OUT at 0xd0000010; + register uint32 GPIO_OUT_raw at 0xd0000010; type GPIO_OUT_SET_t { IO0 = false; // @@ -10167,6 +14771,7 @@ // GPIO output value set: Perform an atomic bit-set on GPIO_OUT, i.e. `GPIO_OUT |= wdata` register GPIO_OUT_SET_t GPIO_OUT_SET at 0xd0000014; + register uint32 GPIO_OUT_SET_raw at 0xd0000014; type GPIO_OUT_CLR_t { IO0 = false; // @@ -10204,6 +14809,7 @@ // GPIO output value clear register GPIO_OUT_CLR_t GPIO_OUT_CLR at 0xd0000018; + register uint32 GPIO_OUT_CLR_raw at 0xd0000018; type GPIO_OUT_XOR_t { IO0 = false; // @@ -10241,6 +14847,7 @@ // GPIO output value XOR register GPIO_OUT_XOR_t GPIO_OUT_XOR at 0xd000001c; + register uint32 GPIO_OUT_XOR_raw at 0xd000001c; type GPIO_OE_t { IO0 = false; // @@ -10278,6 +14885,7 @@ // GPIO output enable: Set output enable (1/0 -> output/input) for GPIO0...29. register GPIO_OE_t GPIO_OE at 0xd0000020; + register uint32 GPIO_OE_raw at 0xd0000020; type GPIO_OE_SET_t { IO0 = false; // @@ -10315,6 +14923,7 @@ // GPIO output enable set: Perform an atomic bit-set on GPIO_OE, i.e. `GPIO_OE |= wdata` register GPIO_OE_SET_t GPIO_OE_SET at 0xd0000024; + register uint32 GPIO_OE_SET_raw at 0xd0000024; type GPIO_OE_CLR_t { IO0 = false; // @@ -10352,6 +14961,7 @@ // GPIO output enable clear: Perform an atomic bit-clear on GPIO_OE, i.e. `GPIO_OE &= ~wdata` register GPIO_OE_CLR_t GPIO_OE_CLR at 0xd0000028; + register uint32 GPIO_OE_CLR_raw at 0xd0000028; type GPIO_OE_XOR_t { IO0 = false; // @@ -10389,72 +14999,91 @@ // GPIO output enable XOR: Perform an atomic bitwise XOR on GPIO_OE, i.e. `GPIO_OE ^= wdata` register GPIO_OE_XOR_t GPIO_OE_XOR at 0xd000002c; + register uint32 GPIO_OE_XOR_raw at 0xd000002c; type GPIO_HI_OUT_t { GPIO_HI_OUT = uint6(0); // Set output level (1/0 -> high/low) for QSPI IO0...5. Reading back gives the last value written, NOT the input value from the pins. If core 0 and core 1 both write to GPIO_HI_OUT simultaneously (or to a SET/CLR/XOR alias), the result is as though the write from core 0 took place first, and the write from core 1 was then applied to that intermediate result. + _res1 = uint26(0); // Reserved, 26 bits } // QSPI output value register GPIO_HI_OUT_t GPIO_HI_OUT at 0xd0000030; + register uint32 GPIO_HI_OUT_raw at 0xd0000030; type GPIO_HI_OUT_SET_t { GPIO_HI_OUT_SET = uint6(0); // Perform an atomic bit-set on GPIO_HI_OUT, i.e. `GPIO_HI_OUT |= wdata` + _res1 = uint26(0); // Reserved, 26 bits } // QSPI output value set register GPIO_HI_OUT_SET_t GPIO_HI_OUT_SET at 0xd0000034; + register uint32 GPIO_HI_OUT_SET_raw at 0xd0000034; type GPIO_HI_OUT_CLR_t { GPIO_HI_OUT_CLR = uint6(0); // Perform an atomic bit-clear on GPIO_HI_OUT, i.e. `GPIO_HI_OUT &= ~wdata` + _res1 = uint26(0); // Reserved, 26 bits } // QSPI output value clear register GPIO_HI_OUT_CLR_t GPIO_HI_OUT_CLR at 0xd0000038; + register uint32 GPIO_HI_OUT_CLR_raw at 0xd0000038; type GPIO_HI_OUT_XOR_t { GPIO_HI_OUT_XOR = uint6(0); // Perform an atomic bitwise XOR on GPIO_HI_OUT, i.e. `GPIO_HI_OUT ^= wdata` + _res1 = uint26(0); // Reserved, 26 bits } // QSPI output value XOR register GPIO_HI_OUT_XOR_t GPIO_HI_OUT_XOR at 0xd000003c; + register uint32 GPIO_HI_OUT_XOR_raw at 0xd000003c; type GPIO_HI_OE_t { GPIO_HI_OE = uint6(0); // Set output enable (1/0 -> output/input) for QSPI IO0...5. Reading back gives the last value written. If core 0 and core 1 both write to GPIO_HI_OE simultaneously (or to a SET/CLR/XOR alias), the result is as though the write from core 0 took place first, and the write from core 1 was then applied to that intermediate result. + _res1 = uint26(0); // Reserved, 26 bits } // QSPI output enable register GPIO_HI_OE_t GPIO_HI_OE at 0xd0000040; + register uint32 GPIO_HI_OE_raw at 0xd0000040; type GPIO_HI_OE_SET_t { GPIO_HI_OE_SET = uint6(0); // Perform an atomic bit-set on GPIO_HI_OE, i.e. `GPIO_HI_OE |= wdata` + _res1 = uint26(0); // Reserved, 26 bits } // QSPI output enable set register GPIO_HI_OE_SET_t GPIO_HI_OE_SET at 0xd0000044; + register uint32 GPIO_HI_OE_SET_raw at 0xd0000044; type GPIO_HI_OE_CLR_t { GPIO_HI_OE_CLR = uint6(0); // Perform an atomic bit-clear on GPIO_HI_OE, i.e. `GPIO_HI_OE &= ~wdata` + _res1 = uint26(0); // Reserved, 26 bits } // QSPI output enable clear register GPIO_HI_OE_CLR_t GPIO_HI_OE_CLR at 0xd0000048; + register uint32 GPIO_HI_OE_CLR_raw at 0xd0000048; type GPIO_HI_OE_XOR_t { GPIO_HI_OE_XOR = uint6(0); // Perform an atomic bitwise XOR on GPIO_HI_OE, i.e. `GPIO_HI_OE ^= wdata` + _res1 = uint26(0); // Reserved, 26 bits } // QSPI output enable XOR register GPIO_HI_OE_XOR_t GPIO_HI_OE_XOR at 0xd000004c; + register uint32 GPIO_HI_OE_XOR_raw at 0xd000004c; type FIFO_ST_t { - VLD = false; // Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid) - RDY = false; // Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more data) - WOF = false; // Sticky flag indicating the TX FIFO was written when full. This write was ignored by the FIFO. - ROE = false; // Sticky flag indicating the RX FIFO was read when empty. This read was ignored by the FIFO. + VLD = false; // Value is 1 if this core's RX FIFO is not empty (i.e. if FIFO_RD is valid) + RDY = false; // Value is 1 if this core's TX FIFO is not full (i.e. if FIFO_WR is ready for more data) + WOF = false; // Sticky flag indicating the TX FIFO was written when full. This write was ignored by the FIFO. + ROE = false; // Sticky flag indicating the RX FIFO was read when empty. This read was ignored by the FIFO. + _res1 = uint28(0); // Reserved, 28 bits } // Status register for inter-core FIFOs (mailboxes). There is one FIFO in the core 0 -> core 1 direction, and one core 1 -> core 0. Both are 32 bits wide and 8 words deep. Core 0 can see the read side of the 1->0 FIFO (RX), and the write side of 0->1 FIFO (TX). Core 1 can see the read side of the 0->1 FIFO (RX), and the write side of 1->0 FIFO (TX). The SIO IRQ for each core is the logical OR of the VLD, WOF and ROE fields of its FIFO_ST register. register FIFO_ST_t FIFO_ST at 0xd0000050; + register uint32 FIFO_ST_raw at 0xd0000050; type FIFO_WR_t { FIFO_WR = uint32(0); // @@ -10462,6 +15091,7 @@ // Write access to this core's TX FIFO register FIFO_WR_t FIFO_WR at 0xd0000054; + register uint32 FIFO_WR_raw at 0xd0000054; type FIFO_RD_t { FIFO_RD = uint32(0); // @@ -10469,6 +15099,7 @@ // Read access to this core's RX FIFO register FIFO_RD_t FIFO_RD at 0xd0000058; + register uint32 FIFO_RD_raw at 0xd0000058; type SPINLOCK_ST_t { SPINLOCK_ST = uint32(0); // @@ -10476,6 +15107,7 @@ // Spinlock state A bitmap containing the state of all 32 spinlocks (1=locked). Mainly intended for debugging. register SPINLOCK_ST_t SPINLOCK_ST at 0xd000005c; + register uint32 SPINLOCK_ST_raw at 0xd000005c; type DIV_UDIVIDEND_t { DIV_UDIVIDEND = uint32(0); // @@ -10483,6 +15115,7 @@ // Divider unsigned dividend Write to the DIVIDEND operand of the divider, i.e. the p in `p / q`. Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. UDIVIDEND/SDIVIDEND are aliases of the same internal register. The U alias starts an unsigned calculation, and the S alias starts a signed calculation. register DIV_UDIVIDEND_t DIV_UDIVIDEND at 0xd0000060; + register uint32 DIV_UDIVIDEND_raw at 0xd0000060; type DIV_UDIVISOR_t { DIV_UDIVISOR = uint32(0); // @@ -10490,6 +15123,7 @@ // Divider unsigned divisor Write to the DIVISOR operand of the divider, i.e. the q in `p / q`. Any operand write starts a new calculation. The results appear in QUOTIENT, REMAINDER. UDIVISOR/SDIVISOR are aliases of the same internal register. The U alias starts an unsigned calculation, and the S alias starts a signed calculation. register DIV_UDIVISOR_t DIV_UDIVISOR at 0xd0000064; + register uint32 DIV_UDIVISOR_raw at 0xd0000064; type DIV_SDIVIDEND_t { DIV_SDIVIDEND = uint32(0); // @@ -10497,6 +15131,7 @@ // Divider signed dividend The same as UDIVIDEND, but starts a signed calculation, rather than unsigned. register DIV_SDIVIDEND_t DIV_SDIVIDEND at 0xd0000068; + register uint32 DIV_SDIVIDEND_raw at 0xd0000068; type DIV_SDIVISOR_t { DIV_SDIVISOR = uint32(0); // @@ -10504,6 +15139,7 @@ // Divider signed divisor The same as UDIVISOR, but starts a signed calculation, rather than unsigned. register DIV_SDIVISOR_t DIV_SDIVISOR at 0xd000006c; + register uint32 DIV_SDIVISOR_raw at 0xd000006c; type DIV_QUOTIENT_t { DIV_QUOTIENT = uint32(0); // @@ -10511,6 +15147,7 @@ // Divider result quotient The result of `DIVIDEND / DIVISOR` (division). Contents undefined while CSR_READY is low. For signed calculations, QUOTIENT is negative when the signs of DIVIDEND and DIVISOR differ. This register can be written to directly, for context save/restore purposes. This halts any in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. Reading from QUOTIENT clears the CSR_DIRTY flag, so should read results in the order REMAINDER, QUOTIENT if CSR_DIRTY is used. register DIV_QUOTIENT_t DIV_QUOTIENT at 0xd0000070; + register uint32 DIV_QUOTIENT_raw at 0xd0000070; type DIV_REMAINDER_t { DIV_REMAINDER = uint32(0); // @@ -10518,14 +15155,17 @@ // Divider result remainder The result of `DIVIDEND % DIVISOR` (modulo). Contents undefined while CSR_READY is low. For signed calculations, REMAINDER is negative only when DIVIDEND is negative. This register can be written to directly, for context save/restore purposes. This halts any in-progress calculation and sets the CSR_READY and CSR_DIRTY flags. register DIV_REMAINDER_t DIV_REMAINDER at 0xd0000074; + register uint32 DIV_REMAINDER_raw at 0xd0000074; type DIV_CSR_t { READY = false; // Reads as 0 when a calculation is in progress, 1 otherwise. Writing an operand (xDIVIDEND, xDIVISOR) will immediately start a new calculation, no matter if one is already in progress. Writing to a result register will immediately terminate any in-progress calculation and set the READY and DIRTY flags. DIRTY = false; // Changes to 1 when any register is written, and back to 0 when QUOTIENT is read. Software can use this flag to make save/restore more efficient (skip if not DIRTY). If the flag is used in this way, it's recommended to either read QUOTIENT only, or REMAINDER and then QUOTIENT, to prevent data loss on context switch. + _res1 = uint30(0); // Reserved, 30 bits } // Control and status register for divider. register DIV_CSR_t DIV_CSR at 0xd0000078; + register uint32 DIV_CSR_raw at 0xd0000078; type INTERP0_ACCUM0_t { INTERP0_ACCUM0 = uint32(0); // @@ -10533,6 +15173,7 @@ // Read/write access to accumulator 0 register INTERP0_ACCUM0_t INTERP0_ACCUM0 at 0xd0000080; + register uint32 INTERP0_ACCUM0_raw at 0xd0000080; type INTERP0_ACCUM1_t { INTERP0_ACCUM1 = uint32(0); // @@ -10540,6 +15181,7 @@ // Read/write access to accumulator 1 register INTERP0_ACCUM1_t INTERP0_ACCUM1 at 0xd0000084; + register uint32 INTERP0_ACCUM1_raw at 0xd0000084; type INTERP0_BASE0_t { INTERP0_BASE0 = uint32(0); // @@ -10547,6 +15189,7 @@ // Read/write access to BASE0 register. register INTERP0_BASE0_t INTERP0_BASE0 at 0xd0000088; + register uint32 INTERP0_BASE0_raw at 0xd0000088; type INTERP0_BASE1_t { INTERP0_BASE1 = uint32(0); // @@ -10554,6 +15197,7 @@ // Read/write access to BASE1 register. register INTERP0_BASE1_t INTERP0_BASE1 at 0xd000008c; + register uint32 INTERP0_BASE1_raw at 0xd000008c; type INTERP0_BASE2_t { INTERP0_BASE2 = uint32(0); // @@ -10561,6 +15205,7 @@ // Read/write access to BASE2 register. register INTERP0_BASE2_t INTERP0_BASE2 at 0xd0000090; + register uint32 INTERP0_BASE2_raw at 0xd0000090; type INTERP0_POP_LANE0_t { INTERP0_POP_LANE0 = uint32(0); // @@ -10568,6 +15213,7 @@ // Read LANE0 result, and simultaneously write lane results to both accumulators (POP). register INTERP0_POP_LANE0_t INTERP0_POP_LANE0 at 0xd0000094; + register uint32 INTERP0_POP_LANE0_raw at 0xd0000094; type INTERP0_POP_LANE1_t { INTERP0_POP_LANE1 = uint32(0); // @@ -10575,6 +15221,7 @@ // Read LANE1 result, and simultaneously write lane results to both accumulators (POP). register INTERP0_POP_LANE1_t INTERP0_POP_LANE1 at 0xd0000098; + register uint32 INTERP0_POP_LANE1_raw at 0xd0000098; type INTERP0_POP_FULL_t { INTERP0_POP_FULL = uint32(0); // @@ -10582,6 +15229,7 @@ // Read FULL result, and simultaneously write lane results to both accumulators (POP). register INTERP0_POP_FULL_t INTERP0_POP_FULL at 0xd000009c; + register uint32 INTERP0_POP_FULL_raw at 0xd000009c; type INTERP0_PEEK_LANE0_t { INTERP0_PEEK_LANE0 = uint32(0); // @@ -10589,6 +15237,7 @@ // Read LANE0 result, without altering any internal state (PEEK). register INTERP0_PEEK_LANE0_t INTERP0_PEEK_LANE0 at 0xd00000a0; + register uint32 INTERP0_PEEK_LANE0_raw at 0xd00000a0; type INTERP0_PEEK_LANE1_t { INTERP0_PEEK_LANE1 = uint32(0); // @@ -10596,6 +15245,7 @@ // Read LANE1 result, without altering any internal state (PEEK). register INTERP0_PEEK_LANE1_t INTERP0_PEEK_LANE1 at 0xd00000a4; + register uint32 INTERP0_PEEK_LANE1_raw at 0xd00000a4; type INTERP0_PEEK_FULL_t { INTERP0_PEEK_FULL = uint32(0); // @@ -10603,6 +15253,7 @@ // Read FULL result, without altering any internal state (PEEK). register INTERP0_PEEK_FULL_t INTERP0_PEEK_FULL at 0xd00000a8; + register uint32 INTERP0_PEEK_FULL_raw at 0xd00000a8; type INTERP0_CTRL_LANE0_t { SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking @@ -10618,10 +15269,12 @@ OVERF0 = false; // Indicates if any masked-off MSBs in ACCUM0 are set. OVERF1 = false; // Indicates if any masked-off MSBs in ACCUM1 are set. OVERF = false; // Set if either OVERF0 or OVERF1 is set. + _res2 = uint6(0); // Reserved, 6 bits } // Control register for lane 0 register INTERP0_CTRL_LANE0_t INTERP0_CTRL_LANE0 at 0xd00000ac; + register uint32 INTERP0_CTRL_LANE0_raw at 0xd00000ac; type INTERP0_CTRL_LANE1_t { SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking @@ -10632,24 +15285,30 @@ CROSS_RESULT = false; // If 1, feed the opposite lane's result into this lane's accumulator on POP. ADD_RAW = false; // If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. FORCE_MSB = uint2(0); // ORed into bits 29:28 of the lane result presented to the processor on the bus. No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence of pointers into flash or SRAM. + _res1 = uint11(0); // Reserved, 11 bits } // Control register for lane 1 register INTERP0_CTRL_LANE1_t INTERP0_CTRL_LANE1 at 0xd00000b0; + register uint32 INTERP0_CTRL_LANE1_raw at 0xd00000b0; type INTERP0_ACCUM0_ADD_t { INTERP0_ACCUM0_ADD = uint24(0); // + _res1 = uint8(0); // Reserved, 8 bits } // Values written here are atomically added to ACCUM0 Reading yields lane 0's raw shift and mask value (BASE0 not added). register INTERP0_ACCUM0_ADD_t INTERP0_ACCUM0_ADD at 0xd00000b4; + register uint32 INTERP0_ACCUM0_ADD_raw at 0xd00000b4; type INTERP0_ACCUM1_ADD_t { INTERP0_ACCUM1_ADD = uint24(0); // + _res1 = uint8(0); // Reserved, 8 bits } // Values written here are atomically added to ACCUM1 Reading yields lane 1's raw shift and mask value (BASE1 not added). register INTERP0_ACCUM1_ADD_t INTERP0_ACCUM1_ADD at 0xd00000b8; + register uint32 INTERP0_ACCUM1_ADD_raw at 0xd00000b8; type INTERP0_BASE_1AND0_t { INTERP0_BASE_1AND0 = uint32(0); // @@ -10657,6 +15316,7 @@ // On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. register INTERP0_BASE_1AND0_t INTERP0_BASE_1AND0 at 0xd00000bc; + register uint32 INTERP0_BASE_1AND0_raw at 0xd00000bc; type INTERP1_ACCUM0_t { INTERP1_ACCUM0 = uint32(0); // @@ -10664,6 +15324,7 @@ // Read/write access to accumulator 0 register INTERP1_ACCUM0_t INTERP1_ACCUM0 at 0xd00000c0; + register uint32 INTERP1_ACCUM0_raw at 0xd00000c0; type INTERP1_ACCUM1_t { INTERP1_ACCUM1 = uint32(0); // @@ -10671,6 +15332,7 @@ // Read/write access to accumulator 1 register INTERP1_ACCUM1_t INTERP1_ACCUM1 at 0xd00000c4; + register uint32 INTERP1_ACCUM1_raw at 0xd00000c4; type INTERP1_BASE0_t { INTERP1_BASE0 = uint32(0); // @@ -10678,6 +15340,7 @@ // Read/write access to BASE0 register. register INTERP1_BASE0_t INTERP1_BASE0 at 0xd00000c8; + register uint32 INTERP1_BASE0_raw at 0xd00000c8; type INTERP1_BASE1_t { INTERP1_BASE1 = uint32(0); // @@ -10685,6 +15348,7 @@ // Read/write access to BASE1 register. register INTERP1_BASE1_t INTERP1_BASE1 at 0xd00000cc; + register uint32 INTERP1_BASE1_raw at 0xd00000cc; type INTERP1_BASE2_t { INTERP1_BASE2 = uint32(0); // @@ -10692,6 +15356,7 @@ // Read/write access to BASE2 register. register INTERP1_BASE2_t INTERP1_BASE2 at 0xd00000d0; + register uint32 INTERP1_BASE2_raw at 0xd00000d0; type INTERP1_POP_LANE0_t { INTERP1_POP_LANE0 = uint32(0); // @@ -10699,6 +15364,7 @@ // Read LANE0 result, and simultaneously write lane results to both accumulators (POP). register INTERP1_POP_LANE0_t INTERP1_POP_LANE0 at 0xd00000d4; + register uint32 INTERP1_POP_LANE0_raw at 0xd00000d4; type INTERP1_POP_LANE1_t { INTERP1_POP_LANE1 = uint32(0); // @@ -10706,6 +15372,7 @@ // Read LANE1 result, and simultaneously write lane results to both accumulators (POP). register INTERP1_POP_LANE1_t INTERP1_POP_LANE1 at 0xd00000d8; + register uint32 INTERP1_POP_LANE1_raw at 0xd00000d8; type INTERP1_POP_FULL_t { INTERP1_POP_FULL = uint32(0); // @@ -10713,6 +15380,7 @@ // Read FULL result, and simultaneously write lane results to both accumulators (POP). register INTERP1_POP_FULL_t INTERP1_POP_FULL at 0xd00000dc; + register uint32 INTERP1_POP_FULL_raw at 0xd00000dc; type INTERP1_PEEK_LANE0_t { INTERP1_PEEK_LANE0 = uint32(0); // @@ -10720,6 +15388,7 @@ // Read LANE0 result, without altering any internal state (PEEK). register INTERP1_PEEK_LANE0_t INTERP1_PEEK_LANE0 at 0xd00000e0; + register uint32 INTERP1_PEEK_LANE0_raw at 0xd00000e0; type INTERP1_PEEK_LANE1_t { INTERP1_PEEK_LANE1 = uint32(0); // @@ -10727,6 +15396,7 @@ // Read LANE1 result, without altering any internal state (PEEK). register INTERP1_PEEK_LANE1_t INTERP1_PEEK_LANE1 at 0xd00000e4; + register uint32 INTERP1_PEEK_LANE1_raw at 0xd00000e4; type INTERP1_PEEK_FULL_t { INTERP1_PEEK_FULL = uint32(0); // @@ -10734,6 +15404,7 @@ // Read FULL result, without altering any internal state (PEEK). register INTERP1_PEEK_FULL_t INTERP1_PEEK_FULL at 0xd00000e8; + register uint32 INTERP1_PEEK_FULL_raw at 0xd00000e8; type INTERP1_CTRL_LANE0_t { SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking @@ -10749,10 +15420,12 @@ OVERF0 = false; // Indicates if any masked-off MSBs in ACCUM0 are set. OVERF1 = false; // Indicates if any masked-off MSBs in ACCUM1 are set. OVERF = false; // Set if either OVERF0 or OVERF1 is set. + _res2 = uint6(0); // Reserved, 6 bits } // Control register for lane 0 register INTERP1_CTRL_LANE0_t INTERP1_CTRL_LANE0 at 0xd00000ec; + register uint32 INTERP1_CTRL_LANE0_raw at 0xd00000ec; type INTERP1_CTRL_LANE1_t { SHIFT = uint5(0); // Logical right-shift applied to accumulator before masking @@ -10763,24 +15436,30 @@ CROSS_RESULT = false; // If 1, feed the opposite lane's result into this lane's accumulator on POP. ADD_RAW = false; // If 1, mask + shift is bypassed for LANE1 result. This does not affect FULL result. FORCE_MSB = uint2(0); // ORed into bits 29:28 of the lane result presented to the processor on the bus. No effect on the internal 32-bit datapath. Handy for using a lane to generate sequence of pointers into flash or SRAM. + _res1 = uint11(0); // Reserved, 11 bits } // Control register for lane 1 register INTERP1_CTRL_LANE1_t INTERP1_CTRL_LANE1 at 0xd00000f0; + register uint32 INTERP1_CTRL_LANE1_raw at 0xd00000f0; type INTERP1_ACCUM0_ADD_t { INTERP1_ACCUM0_ADD = uint24(0); // + _res1 = uint8(0); // Reserved, 8 bits } // Values written here are atomically added to ACCUM0 Reading yields lane 0's raw shift and mask value (BASE0 not added). register INTERP1_ACCUM0_ADD_t INTERP1_ACCUM0_ADD at 0xd00000f4; + register uint32 INTERP1_ACCUM0_ADD_raw at 0xd00000f4; type INTERP1_ACCUM1_ADD_t { INTERP1_ACCUM1_ADD = uint24(0); // + _res1 = uint8(0); // Reserved, 8 bits } // Values written here are atomically added to ACCUM1 Reading yields lane 1's raw shift and mask value (BASE1 not added). register INTERP1_ACCUM1_ADD_t INTERP1_ACCUM1_ADD at 0xd00000f8; + register uint32 INTERP1_ACCUM1_ADD_raw at 0xd00000f8; type INTERP1_BASE_1AND0_t { INTERP1_BASE_1AND0 = uint32(0); // @@ -10788,6 +15467,7 @@ // On write, the lower 16 bits go to BASE0, upper bits to BASE1 simultaneously. Each half is sign-extended to 32 bits if that lane's SIGNED flag is set. register INTERP1_BASE_1AND0_t INTERP1_BASE_1AND0 at 0xd00000fc; + register uint32 INTERP1_BASE_1AND0_raw at 0xd00000fc; type SPINLOCK0_t { SPINLOCK0 = uint32(0); // @@ -10795,6 +15475,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK0_t SPINLOCK0 at 0xd0000100; + register uint32 SPINLOCK0_raw at 0xd0000100; type SPINLOCK1_t { SPINLOCK1 = uint32(0); // @@ -10802,6 +15483,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK1_t SPINLOCK1 at 0xd0000104; + register uint32 SPINLOCK1_raw at 0xd0000104; type SPINLOCK2_t { SPINLOCK2 = uint32(0); // @@ -10809,6 +15491,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK2_t SPINLOCK2 at 0xd0000108; + register uint32 SPINLOCK2_raw at 0xd0000108; type SPINLOCK3_t { SPINLOCK3 = uint32(0); // @@ -10816,6 +15499,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK3_t SPINLOCK3 at 0xd000010c; + register uint32 SPINLOCK3_raw at 0xd000010c; type SPINLOCK4_t { SPINLOCK4 = uint32(0); // @@ -10823,6 +15507,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK4_t SPINLOCK4 at 0xd0000110; + register uint32 SPINLOCK4_raw at 0xd0000110; type SPINLOCK5_t { SPINLOCK5 = uint32(0); // @@ -10830,6 +15515,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK5_t SPINLOCK5 at 0xd0000114; + register uint32 SPINLOCK5_raw at 0xd0000114; type SPINLOCK6_t { SPINLOCK6 = uint32(0); // @@ -10837,6 +15523,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK6_t SPINLOCK6 at 0xd0000118; + register uint32 SPINLOCK6_raw at 0xd0000118; type SPINLOCK7_t { SPINLOCK7 = uint32(0); // @@ -10844,6 +15531,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK7_t SPINLOCK7 at 0xd000011c; + register uint32 SPINLOCK7_raw at 0xd000011c; type SPINLOCK8_t { SPINLOCK8 = uint32(0); // @@ -10851,6 +15539,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK8_t SPINLOCK8 at 0xd0000120; + register uint32 SPINLOCK8_raw at 0xd0000120; type SPINLOCK9_t { SPINLOCK9 = uint32(0); // @@ -10858,6 +15547,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK9_t SPINLOCK9 at 0xd0000124; + register uint32 SPINLOCK9_raw at 0xd0000124; type SPINLOCK10_t { SPINLOCK10 = uint32(0); // @@ -10865,6 +15555,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK10_t SPINLOCK10 at 0xd0000128; + register uint32 SPINLOCK10_raw at 0xd0000128; type SPINLOCK11_t { SPINLOCK11 = uint32(0); // @@ -10872,6 +15563,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK11_t SPINLOCK11 at 0xd000012c; + register uint32 SPINLOCK11_raw at 0xd000012c; type SPINLOCK12_t { SPINLOCK12 = uint32(0); // @@ -10879,6 +15571,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK12_t SPINLOCK12 at 0xd0000130; + register uint32 SPINLOCK12_raw at 0xd0000130; type SPINLOCK13_t { SPINLOCK13 = uint32(0); // @@ -10886,6 +15579,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK13_t SPINLOCK13 at 0xd0000134; + register uint32 SPINLOCK13_raw at 0xd0000134; type SPINLOCK14_t { SPINLOCK14 = uint32(0); // @@ -10893,6 +15587,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK14_t SPINLOCK14 at 0xd0000138; + register uint32 SPINLOCK14_raw at 0xd0000138; type SPINLOCK15_t { SPINLOCK15 = uint32(0); // @@ -10900,6 +15595,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK15_t SPINLOCK15 at 0xd000013c; + register uint32 SPINLOCK15_raw at 0xd000013c; type SPINLOCK16_t { SPINLOCK16 = uint32(0); // @@ -10907,6 +15603,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK16_t SPINLOCK16 at 0xd0000140; + register uint32 SPINLOCK16_raw at 0xd0000140; type SPINLOCK17_t { SPINLOCK17 = uint32(0); // @@ -10914,6 +15611,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK17_t SPINLOCK17 at 0xd0000144; + register uint32 SPINLOCK17_raw at 0xd0000144; type SPINLOCK18_t { SPINLOCK18 = uint32(0); // @@ -10921,6 +15619,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK18_t SPINLOCK18 at 0xd0000148; + register uint32 SPINLOCK18_raw at 0xd0000148; type SPINLOCK19_t { SPINLOCK19 = uint32(0); // @@ -10928,6 +15627,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK19_t SPINLOCK19 at 0xd000014c; + register uint32 SPINLOCK19_raw at 0xd000014c; type SPINLOCK20_t { SPINLOCK20 = uint32(0); // @@ -10935,6 +15635,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK20_t SPINLOCK20 at 0xd0000150; + register uint32 SPINLOCK20_raw at 0xd0000150; type SPINLOCK21_t { SPINLOCK21 = uint32(0); // @@ -10942,6 +15643,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK21_t SPINLOCK21 at 0xd0000154; + register uint32 SPINLOCK21_raw at 0xd0000154; type SPINLOCK22_t { SPINLOCK22 = uint32(0); // @@ -10949,6 +15651,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK22_t SPINLOCK22 at 0xd0000158; + register uint32 SPINLOCK22_raw at 0xd0000158; type SPINLOCK23_t { SPINLOCK23 = uint32(0); // @@ -10956,6 +15659,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK23_t SPINLOCK23 at 0xd000015c; + register uint32 SPINLOCK23_raw at 0xd000015c; type SPINLOCK24_t { SPINLOCK24 = uint32(0); // @@ -10963,6 +15667,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK24_t SPINLOCK24 at 0xd0000160; + register uint32 SPINLOCK24_raw at 0xd0000160; type SPINLOCK25_t { SPINLOCK25 = uint32(0); // @@ -10970,6 +15675,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK25_t SPINLOCK25 at 0xd0000164; + register uint32 SPINLOCK25_raw at 0xd0000164; type SPINLOCK26_t { SPINLOCK26 = uint32(0); // @@ -10977,6 +15683,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK26_t SPINLOCK26 at 0xd0000168; + register uint32 SPINLOCK26_raw at 0xd0000168; type SPINLOCK27_t { SPINLOCK27 = uint32(0); // @@ -10984,6 +15691,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK27_t SPINLOCK27 at 0xd000016c; + register uint32 SPINLOCK27_raw at 0xd000016c; type SPINLOCK28_t { SPINLOCK28 = uint32(0); // @@ -10991,6 +15699,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK28_t SPINLOCK28 at 0xd0000170; + register uint32 SPINLOCK28_raw at 0xd0000170; type SPINLOCK29_t { SPINLOCK29 = uint32(0); // @@ -10998,6 +15707,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK29_t SPINLOCK29 at 0xd0000174; + register uint32 SPINLOCK29_raw at 0xd0000174; type SPINLOCK30_t { SPINLOCK30 = uint32(0); // @@ -11005,6 +15715,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK30_t SPINLOCK30 at 0xd0000178; + register uint32 SPINLOCK30_raw at 0xd0000178; type SPINLOCK31_t { SPINLOCK31 = uint32(0); // @@ -11012,6 +15723,7 @@ // Reading from a spinlock address will: - Return 0 if lock is already locked - Otherwise return nonzero, and simultaneously claim the lock Writing (any value) releases the lock. If core 0 and core 1 attempt to claim the same lock simultaneously, core 0 wins. The value returned on success is 0x1 << lock number. register SPINLOCK31_t SPINLOCK31 at 0xd000017c; + register uint32 SPINLOCK31_raw at 0xd000017c; /* Types and registers for USB @@ -11020,234 +15732,253 @@ type ADDR_ENDP_t { ADDRESS = uint7(0); // In device mode, the address that the device should respond to. Set in response to a SET_ADDR setup packet from the host. In host mode set to the address of the device to communicate with. - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Device endpoint to send data to. Only valid for HOST mode. + _res2 = uint12(0); // Reserved, 12 bits } // Device address and endpoint control register ADDR_ENDP_t ADDR_ENDP at 0x50110000; + register uint32 ADDR_ENDP_raw at 0x50110000; type ADDR_ENDP1_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 1. Only valid for HOST mode. register ADDR_ENDP1_t ADDR_ENDP1 at 0x50110004; + register uint32 ADDR_ENDP1_raw at 0x50110004; type ADDR_ENDP2_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 2. Only valid for HOST mode. register ADDR_ENDP2_t ADDR_ENDP2 at 0x50110008; + register uint32 ADDR_ENDP2_raw at 0x50110008; type ADDR_ENDP3_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 3. Only valid for HOST mode. register ADDR_ENDP3_t ADDR_ENDP3 at 0x5011000c; + register uint32 ADDR_ENDP3_raw at 0x5011000c; type ADDR_ENDP4_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 4. Only valid for HOST mode. register ADDR_ENDP4_t ADDR_ENDP4 at 0x50110010; + register uint32 ADDR_ENDP4_raw at 0x50110010; type ADDR_ENDP5_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 5. Only valid for HOST mode. register ADDR_ENDP5_t ADDR_ENDP5 at 0x50110014; + register uint32 ADDR_ENDP5_raw at 0x50110014; type ADDR_ENDP6_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 6. Only valid for HOST mode. register ADDR_ENDP6_t ADDR_ENDP6 at 0x50110018; + register uint32 ADDR_ENDP6_raw at 0x50110018; type ADDR_ENDP7_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 7. Only valid for HOST mode. register ADDR_ENDP7_t ADDR_ENDP7 at 0x5011001c; + register uint32 ADDR_ENDP7_raw at 0x5011001c; type ADDR_ENDP8_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 8. Only valid for HOST mode. register ADDR_ENDP8_t ADDR_ENDP8 at 0x50110020; + register uint32 ADDR_ENDP8_raw at 0x50110020; type ADDR_ENDP9_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 9. Only valid for HOST mode. register ADDR_ENDP9_t ADDR_ENDP9 at 0x50110024; + register uint32 ADDR_ENDP9_raw at 0x50110024; type ADDR_ENDP10_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 10. Only valid for HOST mode. register ADDR_ENDP10_t ADDR_ENDP10 at 0x50110028; + register uint32 ADDR_ENDP10_raw at 0x50110028; type ADDR_ENDP11_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 11. Only valid for HOST mode. register ADDR_ENDP11_t ADDR_ENDP11 at 0x5011002c; + register uint32 ADDR_ENDP11_raw at 0x5011002c; type ADDR_ENDP12_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 12. Only valid for HOST mode. register ADDR_ENDP12_t ADDR_ENDP12 at 0x50110030; + register uint32 ADDR_ENDP12_raw at 0x50110030; type ADDR_ENDP13_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 13. Only valid for HOST mode. register ADDR_ENDP13_t ADDR_ENDP13 at 0x50110034; + register uint32 ADDR_ENDP13_raw at 0x50110034; type ADDR_ENDP14_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 14. Only valid for HOST mode. register ADDR_ENDP14_t ADDR_ENDP14 at 0x50110038; + register uint32 ADDR_ENDP14_raw at 0x50110038; type ADDR_ENDP15_t { ADDRESS = uint7(0); // Device address - _res1 = uint8(0); // Reserved, 9 bits - _res2 = false; // + _res1 = uint9(0); // Reserved, 9 bits ENDPOINT = uint4(0); // Endpoint number of the interrupt endpoint - _res3 = uint5(0); // Reserved, 5 bits + _res2 = uint5(0); // Reserved, 5 bits INTEP_DIR = false; // Direction of the interrupt endpoint. In=0, Out=1 INTEP_PREAMBLE = false; // Interrupt EP requires preamble (is a low speed device on a full speed hub) + _res3 = uint5(0); // Reserved, 5 bits } // Interrupt endpoint 15. Only valid for HOST mode. register ADDR_ENDP15_t ADDR_ENDP15 at 0x5011003c; + register uint32 ADDR_ENDP15_raw at 0x5011003c; type MAIN_CTRL_t { CONTROLLER_EN = false; // Enable controller HOST_NDEVICE = false; // Device mode = 0, Host mode = 1 - _res1 = uint16(0); // Reserved, 29 bits - _res2 = uint8(0); // - _res3 = uint5(0); // + _res1 = uint29(0); // Reserved, 29 bits SIM_TIMING = false; // Reduced timings for simulation } // Main control register register MAIN_CTRL_t MAIN_CTRL at 0x50110040; + register uint32 MAIN_CTRL_raw at 0x50110040; type SOF_WR_t { COUNT = uint11(0); // + _res1 = uint21(0); // Reserved, 21 bits } // Set the SOF (Start of Frame) frame number in the host controller. The SOF packet is sent every 1ms and the host will increment the frame number by 1 each time. register SOF_WR_t SOF_WR at 0x50110044; + register uint32 SOF_WR_raw at 0x50110044; type SOF_RD_t { COUNT = uint11(0); // + _res1 = uint21(0); // Reserved, 21 bits } // Read the last SOF (Start of Frame) frame number seen. In device mode the last SOF received from the host. In host mode the last SOF sent by the host. register SOF_RD_t SOF_RD at 0x50110048; + register uint32 SOF_RD_raw at 0x50110048; type SIE_CTRL_t { START_TRANS = false; // Host: Start transaction @@ -11282,6 +16013,7 @@ // SIE control register register SIE_CTRL_t SIE_CTRL at 0x5011004c; + register uint32 SIE_CTRL_raw at 0x5011004c; type SIE_STATUS_t { VBUS_DETECTED = false; // Device: VBUS Detected @@ -11310,14 +16042,17 @@ // SIE status register register SIE_STATUS_t SIE_STATUS at 0x50110050; + register uint32 SIE_STATUS_raw at 0x50110050; type INT_EP_CTRL_t { _res1 = false; // Reserved, 1 bits INT_EP_ACTIVE = uint15(0); // Host: Enable interrupt endpoint 1 => 15 + _res2 = uint16(0); // Reserved, 16 bits } // interrupt endpoint control register register INT_EP_CTRL_t INT_EP_CTRL at 0x50110054; + register uint32 INT_EP_CTRL_raw at 0x50110054; type BUFF_STATUS_t { EP0_IN = false; // @@ -11356,6 +16091,7 @@ // Buffer status register. A bit set here indicates that a buffer has completed on the endpoint (if the buffer interrupt is enabled). It is possible for 2 buffers to be completed, so clearing the buffer status bit may instantly re set it on the next clock cycle. register BUFF_STATUS_t BUFF_STATUS at 0x50110058; + register uint32 BUFF_STATUS_raw at 0x50110058; type BUFF_CPU_SHOULD_HANDLE_t { EP0_IN = false; // @@ -11394,6 +16130,7 @@ // Which of the double buffers should be handled. Only valid if using an interrupt per buffer (i.e. not per 2 buffers). Not valid for host interrupt endpoint polling because they are only single buffered. register BUFF_CPU_SHOULD_HANDLE_t BUFF_CPU_SHOULD_HANDLE at 0x5011005c; + register uint32 BUFF_CPU_SHOULD_HANDLE_raw at 0x5011005c; type EP_ABORT_t { EP0_IN = false; // @@ -11432,6 +16169,7 @@ // Device only: Can be set to ignore the buffer control register for this endpoint in case you would like to revoke a buffer. A NAK will be sent for every access to the endpoint until this bit is cleared. A corresponding bit in `EP_ABORT_DONE` is set when it is safe to modify the buffer control register. register EP_ABORT_t EP_ABORT at 0x50110060; + register uint32 EP_ABORT_raw at 0x50110060; type EP_ABORT_DONE_t { EP0_IN = false; // @@ -11470,23 +16208,28 @@ // Device only: Used in conjunction with `EP_ABORT`. Set once an endpoint is idle so the programmer knows it is safe to modify the buffer control register. register EP_ABORT_DONE_t EP_ABORT_DONE at 0x50110064; + register uint32 EP_ABORT_DONE_raw at 0x50110064; type EP_STALL_ARM_t { EP0_IN = false; // EP0_OUT = false; // + _res1 = uint30(0); // Reserved, 30 bits } // Device: this bit must be set in conjunction with the `STALL` bit in the buffer control register to send a STALL on EP0. The device controller clears these bits when a SETUP packet is received because the USB spec requires that a STALL condition is cleared when a SETUP packet is received. register EP_STALL_ARM_t EP_STALL_ARM at 0x50110068; + register uint32 EP_STALL_ARM_raw at 0x50110068; type NAK_POLL_t { DELAY_LS = uint10(0); // NAK polling interval for a low speed device _res1 = uint6(0); // Reserved, 6 bits DELAY_FS = uint10(0); // NAK polling interval for a full speed device + _res2 = uint6(0); // Reserved, 6 bits } // Used by the host controller. Sets the wait time in microseconds before trying again if the device replies with a NAK. register NAK_POLL_t NAK_POLL at 0x5011006c; + register uint32 NAK_POLL_raw at 0x5011006c; type EP_STATUS_STALL_NAK_t { EP0_IN = false; // @@ -11525,16 +16268,19 @@ // Device: bits are set when the `IRQ_ON_NAK` or `IRQ_ON_STALL` bits are set. For EP0 this comes from `SIE_CTRL`. For all other endpoints it comes from the endpoint control register. register EP_STATUS_STALL_NAK_t EP_STATUS_STALL_NAK at 0x50110070; + register uint32 EP_STATUS_STALL_NAK_raw at 0x50110070; type USB_MUXING_t { TO_PHY = false; // TO_EXTPHY = false; // TO_DIGITAL_PAD = false; // SOFTCON = false; // + _res1 = uint28(0); // Reserved, 28 bits } // Where to connect the USB controller. Should be to_phy by default. register USB_MUXING_t USB_MUXING at 0x50110074; + register uint32 USB_MUXING_raw at 0x50110074; type USB_PWR_t { VBUS_EN = false; // @@ -11543,10 +16289,12 @@ VBUS_DETECT_OVERRIDE_EN = false; // OVERCURR_DETECT = false; // OVERCURR_DETECT_EN = false; // + _res1 = uint26(0); // Reserved, 26 bits } // Overrides for the power signals in the event that the VBUS signals are not hooked up to GPIO. Set the value of the override and then the override enable so switch over to the override value. register USB_PWR_t USB_PWR at 0x50110078; + register uint32 USB_PWR_raw at 0x50110078; type USBPHY_DIRECT_t { DP_PULLUP_HISEL = false; // when dp_pullup_en is set high, this enables second resistor. 0 - Pull = Rpu2; 1 - Pull = Rpu1 + Rpu2 @@ -11572,10 +16320,12 @@ DM_OVCN = false; // Status bit from USB PHY DP_OVV = false; // Status bit from USB PHY DM_OVV = false; // Status bit from USB PHY + _res3 = uint9(0); // Reserved, 9 bits } // Note that most functions are driven directly from usb_fsls controller. This register allows more detailed control/status from the USB PHY. Useful for debug but not expected to be used in normal operation Use in conjunction with usbphy_direct_override register register USBPHY_DIRECT_t USBPHY_DIRECT at 0x5011007c; + register uint32 USBPHY_DIRECT_raw at 0x5011007c; type USBPHY_DIRECT_OVERRIDE_t { DP_PULLUP_HISEL_OVERRIDE_EN = false; // @@ -11593,19 +16343,23 @@ DM_PULLUP_OVERRIDE_EN = false; // _res1 = uint2(0); // Reserved, 2 bits TX_DIFFMODE_OVERRIDE_EN = false; // + _res2 = uint16(0); // Reserved, 16 bits } // register USBPHY_DIRECT_OVERRIDE_t USBPHY_DIRECT_OVERRIDE at 0x50110080; + register uint32 USBPHY_DIRECT_OVERRIDE_raw at 0x50110080; type USBPHY_TRIM_t { DP_PULLDN_TRIM = uint5(0); // Value to drive to USB PHY DP pulldown resistor trim control Experimental data suggests that the reset value will work, but this register allows adjustment if required _res1 = uint3(0); // Reserved, 3 bits DM_PULLDN_TRIM = uint5(0); // Value to drive to USB PHY DM pulldown resistor trim control Experimental data suggests that the reset value will work, but this register allows adjustment if required + _res2 = uint19(0); // Reserved, 19 bits } // Note that most functions are driven directly from usb_fsls controller. This register allows more detailed control/status from the USB PHY. Useful for debug but not expected to be used in normal operation register USBPHY_TRIM_t USBPHY_TRIM at 0x50110084; + register uint32 USBPHY_TRIM_raw at 0x50110084; type USB_INTR_t { HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED @@ -11628,10 +16382,12 @@ DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + _res1 = uint12(0); // Reserved, 12 bits } // Raw Interrupts register USB_INTR_t USB_INTR at 0x5011008c; + register uint32 USB_INTR_raw at 0x5011008c; type USB_INTE_t { HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED @@ -11654,10 +16410,12 @@ DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + _res1 = uint12(0); // Reserved, 12 bits } // Interrupt Enable register USB_INTE_t USB_INTE at 0x50110090; + register uint32 USB_INTE_raw at 0x50110090; type USB_INTF_t { HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED @@ -11680,10 +16438,12 @@ DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + _res1 = uint12(0); // Reserved, 12 bits } // Interrupt Force register USB_INTF_t USB_INTF at 0x50110094; + register uint32 USB_INTF_raw at 0x50110094; type USB_INTS_t { HOST_CONN_DIS = false; // Host: raised when a device is connected or disconnected (i.e. when SIE_STATUS.SPEED changes). Cleared by writing to SIE_STATUS.SPEED @@ -11706,10 +16466,12 @@ DEV_SOF = false; // Set every time the device receives a SOF (Start of Frame) packet. Cleared by reading SOF_RD ABORT_DONE = false; // Raised when any bit in ABORT_DONE is set. Clear by clearing all bits in ABORT_DONE. EP_STALL_NAK = false; // Raised when any bit in EP_STATUS_STALL_NAK is set. Clear by clearing all bits in EP_STATUS_STALL_NAK. + _res1 = uint12(0); // Reserved, 12 bits } // Interrupt status after masking & forcing register USB_INTS_t USB_INTS at 0x50110098; + register uint32 USB_INTS_raw at 0x50110098; /* Types and registers for USB_DPRAM @@ -11724,6 +16486,7 @@ // Bytes 0-3 of the SETUP packet from the host. register SETUP_PACKET_LOW_t SETUP_PACKET_LOW at 0x50100000; + register uint32 SETUP_PACKET_LOW_raw at 0x50100000; type SETUP_PACKET_HIGH_t { WINDEX = uint16(0); // @@ -11732,6 +16495,14 @@ // Bytes 4-7 of the setup packet from the host. register SETUP_PACKET_HIGH_t SETUP_PACKET_HIGH at 0x50100004; + register uint32 SETUP_PACKET_HIGH_raw at 0x50100004; + + enum EP1_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP1_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11747,6 +16518,14 @@ // register EP1_IN_CONTROL_t EP1_IN_CONTROL at 0x50100008; + register uint32 EP1_IN_CONTROL_raw at 0x50100008; + + enum EP1_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP1_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11762,6 +16541,14 @@ // register EP1_OUT_CONTROL_t EP1_OUT_CONTROL at 0x5010000c; + register uint32 EP1_OUT_CONTROL_raw at 0x5010000c; + + enum EP2_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP2_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11777,6 +16564,14 @@ // register EP2_IN_CONTROL_t EP2_IN_CONTROL at 0x50100010; + register uint32 EP2_IN_CONTROL_raw at 0x50100010; + + enum EP2_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP2_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11792,6 +16587,14 @@ // register EP2_OUT_CONTROL_t EP2_OUT_CONTROL at 0x50100014; + register uint32 EP2_OUT_CONTROL_raw at 0x50100014; + + enum EP3_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP3_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11807,6 +16610,14 @@ // register EP3_IN_CONTROL_t EP3_IN_CONTROL at 0x50100018; + register uint32 EP3_IN_CONTROL_raw at 0x50100018; + + enum EP3_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP3_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11822,6 +16633,14 @@ // register EP3_OUT_CONTROL_t EP3_OUT_CONTROL at 0x5010001c; + register uint32 EP3_OUT_CONTROL_raw at 0x5010001c; + + enum EP4_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP4_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11837,6 +16656,14 @@ // register EP4_IN_CONTROL_t EP4_IN_CONTROL at 0x50100020; + register uint32 EP4_IN_CONTROL_raw at 0x50100020; + + enum EP4_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP4_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11852,6 +16679,14 @@ // register EP4_OUT_CONTROL_t EP4_OUT_CONTROL at 0x50100024; + register uint32 EP4_OUT_CONTROL_raw at 0x50100024; + + enum EP5_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP5_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11867,6 +16702,14 @@ // register EP5_IN_CONTROL_t EP5_IN_CONTROL at 0x50100028; + register uint32 EP5_IN_CONTROL_raw at 0x50100028; + + enum EP5_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP5_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11882,6 +16725,14 @@ // register EP5_OUT_CONTROL_t EP5_OUT_CONTROL at 0x5010002c; + register uint32 EP5_OUT_CONTROL_raw at 0x5010002c; + + enum EP6_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP6_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11897,6 +16748,14 @@ // register EP6_IN_CONTROL_t EP6_IN_CONTROL at 0x50100030; + register uint32 EP6_IN_CONTROL_raw at 0x50100030; + + enum EP6_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP6_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11912,6 +16771,14 @@ // register EP6_OUT_CONTROL_t EP6_OUT_CONTROL at 0x50100034; + register uint32 EP6_OUT_CONTROL_raw at 0x50100034; + + enum EP7_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP7_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11927,6 +16794,14 @@ // register EP7_IN_CONTROL_t EP7_IN_CONTROL at 0x50100038; + register uint32 EP7_IN_CONTROL_raw at 0x50100038; + + enum EP7_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP7_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11942,6 +16817,14 @@ // register EP7_OUT_CONTROL_t EP7_OUT_CONTROL at 0x5010003c; + register uint32 EP7_OUT_CONTROL_raw at 0x5010003c; + + enum EP8_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP8_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11957,6 +16840,14 @@ // register EP8_IN_CONTROL_t EP8_IN_CONTROL at 0x50100040; + register uint32 EP8_IN_CONTROL_raw at 0x50100040; + + enum EP8_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP8_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11972,6 +16863,14 @@ // register EP8_OUT_CONTROL_t EP8_OUT_CONTROL at 0x50100044; + register uint32 EP8_OUT_CONTROL_raw at 0x50100044; + + enum EP9_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP9_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -11987,6 +16886,14 @@ // register EP9_IN_CONTROL_t EP9_IN_CONTROL at 0x50100048; + register uint32 EP9_IN_CONTROL_raw at 0x50100048; + + enum EP9_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP9_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12002,6 +16909,14 @@ // register EP9_OUT_CONTROL_t EP9_OUT_CONTROL at 0x5010004c; + register uint32 EP9_OUT_CONTROL_raw at 0x5010004c; + + enum EP10_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP10_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12017,6 +16932,14 @@ // register EP10_IN_CONTROL_t EP10_IN_CONTROL at 0x50100050; + register uint32 EP10_IN_CONTROL_raw at 0x50100050; + + enum EP10_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP10_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12032,6 +16955,14 @@ // register EP10_OUT_CONTROL_t EP10_OUT_CONTROL at 0x50100054; + register uint32 EP10_OUT_CONTROL_raw at 0x50100054; + + enum EP11_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP11_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12047,6 +16978,14 @@ // register EP11_IN_CONTROL_t EP11_IN_CONTROL at 0x50100058; + register uint32 EP11_IN_CONTROL_raw at 0x50100058; + + enum EP11_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP11_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12062,6 +17001,14 @@ // register EP11_OUT_CONTROL_t EP11_OUT_CONTROL at 0x5010005c; + register uint32 EP11_OUT_CONTROL_raw at 0x5010005c; + + enum EP12_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP12_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12077,6 +17024,14 @@ // register EP12_IN_CONTROL_t EP12_IN_CONTROL at 0x50100060; + register uint32 EP12_IN_CONTROL_raw at 0x50100060; + + enum EP12_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP12_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12092,6 +17047,14 @@ // register EP12_OUT_CONTROL_t EP12_OUT_CONTROL at 0x50100064; + register uint32 EP12_OUT_CONTROL_raw at 0x50100064; + + enum EP13_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP13_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12107,6 +17070,14 @@ // register EP13_IN_CONTROL_t EP13_IN_CONTROL at 0x50100068; + register uint32 EP13_IN_CONTROL_raw at 0x50100068; + + enum EP13_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP13_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12122,6 +17093,14 @@ // register EP13_OUT_CONTROL_t EP13_OUT_CONTROL at 0x5010006c; + register uint32 EP13_OUT_CONTROL_raw at 0x5010006c; + + enum EP14_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP14_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12137,6 +17116,14 @@ // register EP14_IN_CONTROL_t EP14_IN_CONTROL at 0x50100070; + register uint32 EP14_IN_CONTROL_raw at 0x50100070; + + enum EP14_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP14_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12152,6 +17139,14 @@ // register EP14_OUT_CONTROL_t EP14_OUT_CONTROL at 0x50100074; + register uint32 EP14_OUT_CONTROL_raw at 0x50100074; + + enum EP15_IN_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP15_IN_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12167,6 +17162,14 @@ // register EP15_IN_CONTROL_t EP15_IN_CONTROL at 0x50100078; + register uint32 EP15_IN_CONTROL_raw at 0x50100078; + + enum EP15_OUT_CONTROL_ENDPOINT_TYPE { + Control = 0, // + Isochronous = 1, // + Bulk = 2, // + Interrupt = 3 // + } type EP15_OUT_CONTROL_t { BUFFER_ADDRESS = uint16(0); // 64 byte aligned buffer address for this EP (bits 0-5 are ignored). Relative to the start of the DPRAM. @@ -12182,6 +17185,14 @@ // register EP15_OUT_CONTROL_t EP15_OUT_CONTROL at 0x5010007c; + register uint32 EP15_OUT_CONTROL_raw at 0x5010007c; + + enum EP0_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP0_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12201,6 +17212,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP0_IN_BUFFER_CONTROL_t EP0_IN_BUFFER_CONTROL at 0x50100080; + register uint32 EP0_IN_BUFFER_CONTROL_raw at 0x50100080; + + enum EP0_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP0_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12220,6 +17239,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP0_OUT_BUFFER_CONTROL_t EP0_OUT_BUFFER_CONTROL at 0x50100084; + register uint32 EP0_OUT_BUFFER_CONTROL_raw at 0x50100084; + + enum EP1_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP1_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12239,6 +17266,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP1_IN_BUFFER_CONTROL_t EP1_IN_BUFFER_CONTROL at 0x50100088; + register uint32 EP1_IN_BUFFER_CONTROL_raw at 0x50100088; + + enum EP1_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP1_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12258,6 +17293,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP1_OUT_BUFFER_CONTROL_t EP1_OUT_BUFFER_CONTROL at 0x5010008c; + register uint32 EP1_OUT_BUFFER_CONTROL_raw at 0x5010008c; + + enum EP2_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP2_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12277,6 +17320,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP2_IN_BUFFER_CONTROL_t EP2_IN_BUFFER_CONTROL at 0x50100090; + register uint32 EP2_IN_BUFFER_CONTROL_raw at 0x50100090; + + enum EP2_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP2_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12296,6 +17347,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP2_OUT_BUFFER_CONTROL_t EP2_OUT_BUFFER_CONTROL at 0x50100094; + register uint32 EP2_OUT_BUFFER_CONTROL_raw at 0x50100094; + + enum EP3_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP3_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12315,6 +17374,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP3_IN_BUFFER_CONTROL_t EP3_IN_BUFFER_CONTROL at 0x50100098; + register uint32 EP3_IN_BUFFER_CONTROL_raw at 0x50100098; + + enum EP3_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP3_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12334,6 +17401,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP3_OUT_BUFFER_CONTROL_t EP3_OUT_BUFFER_CONTROL at 0x5010009c; + register uint32 EP3_OUT_BUFFER_CONTROL_raw at 0x5010009c; + + enum EP4_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP4_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12353,6 +17428,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP4_IN_BUFFER_CONTROL_t EP4_IN_BUFFER_CONTROL at 0x501000a0; + register uint32 EP4_IN_BUFFER_CONTROL_raw at 0x501000a0; + + enum EP4_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP4_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12372,6 +17455,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP4_OUT_BUFFER_CONTROL_t EP4_OUT_BUFFER_CONTROL at 0x501000a4; + register uint32 EP4_OUT_BUFFER_CONTROL_raw at 0x501000a4; + + enum EP5_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP5_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12391,6 +17482,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP5_IN_BUFFER_CONTROL_t EP5_IN_BUFFER_CONTROL at 0x501000a8; + register uint32 EP5_IN_BUFFER_CONTROL_raw at 0x501000a8; + + enum EP5_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP5_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12410,6 +17509,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP5_OUT_BUFFER_CONTROL_t EP5_OUT_BUFFER_CONTROL at 0x501000ac; + register uint32 EP5_OUT_BUFFER_CONTROL_raw at 0x501000ac; + + enum EP6_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP6_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12429,6 +17536,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP6_IN_BUFFER_CONTROL_t EP6_IN_BUFFER_CONTROL at 0x501000b0; + register uint32 EP6_IN_BUFFER_CONTROL_raw at 0x501000b0; + + enum EP6_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP6_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12448,6 +17563,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP6_OUT_BUFFER_CONTROL_t EP6_OUT_BUFFER_CONTROL at 0x501000b4; + register uint32 EP6_OUT_BUFFER_CONTROL_raw at 0x501000b4; + + enum EP7_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP7_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12467,6 +17590,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP7_IN_BUFFER_CONTROL_t EP7_IN_BUFFER_CONTROL at 0x501000b8; + register uint32 EP7_IN_BUFFER_CONTROL_raw at 0x501000b8; + + enum EP7_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP7_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12486,6 +17617,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP7_OUT_BUFFER_CONTROL_t EP7_OUT_BUFFER_CONTROL at 0x501000bc; + register uint32 EP7_OUT_BUFFER_CONTROL_raw at 0x501000bc; + + enum EP8_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP8_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12505,6 +17644,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP8_IN_BUFFER_CONTROL_t EP8_IN_BUFFER_CONTROL at 0x501000c0; + register uint32 EP8_IN_BUFFER_CONTROL_raw at 0x501000c0; + + enum EP8_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP8_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12524,6 +17671,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP8_OUT_BUFFER_CONTROL_t EP8_OUT_BUFFER_CONTROL at 0x501000c4; + register uint32 EP8_OUT_BUFFER_CONTROL_raw at 0x501000c4; + + enum EP9_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP9_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12543,6 +17698,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP9_IN_BUFFER_CONTROL_t EP9_IN_BUFFER_CONTROL at 0x501000c8; + register uint32 EP9_IN_BUFFER_CONTROL_raw at 0x501000c8; + + enum EP9_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP9_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12562,6 +17725,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP9_OUT_BUFFER_CONTROL_t EP9_OUT_BUFFER_CONTROL at 0x501000cc; + register uint32 EP9_OUT_BUFFER_CONTROL_raw at 0x501000cc; + + enum EP10_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP10_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12581,6 +17752,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP10_IN_BUFFER_CONTROL_t EP10_IN_BUFFER_CONTROL at 0x501000d0; + register uint32 EP10_IN_BUFFER_CONTROL_raw at 0x501000d0; + + enum EP10_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP10_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12600,6 +17779,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP10_OUT_BUFFER_CONTROL_t EP10_OUT_BUFFER_CONTROL at 0x501000d4; + register uint32 EP10_OUT_BUFFER_CONTROL_raw at 0x501000d4; + + enum EP11_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP11_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12619,6 +17806,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP11_IN_BUFFER_CONTROL_t EP11_IN_BUFFER_CONTROL at 0x501000d8; + register uint32 EP11_IN_BUFFER_CONTROL_raw at 0x501000d8; + + enum EP11_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP11_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12638,6 +17833,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP11_OUT_BUFFER_CONTROL_t EP11_OUT_BUFFER_CONTROL at 0x501000dc; + register uint32 EP11_OUT_BUFFER_CONTROL_raw at 0x501000dc; + + enum EP12_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP12_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12657,6 +17860,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP12_IN_BUFFER_CONTROL_t EP12_IN_BUFFER_CONTROL at 0x501000e0; + register uint32 EP12_IN_BUFFER_CONTROL_raw at 0x501000e0; + + enum EP12_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP12_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12676,6 +17887,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP12_OUT_BUFFER_CONTROL_t EP12_OUT_BUFFER_CONTROL at 0x501000e4; + register uint32 EP12_OUT_BUFFER_CONTROL_raw at 0x501000e4; + + enum EP13_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP13_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12695,6 +17914,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP13_IN_BUFFER_CONTROL_t EP13_IN_BUFFER_CONTROL at 0x501000e8; + register uint32 EP13_IN_BUFFER_CONTROL_raw at 0x501000e8; + + enum EP13_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP13_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12714,6 +17941,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP13_OUT_BUFFER_CONTROL_t EP13_OUT_BUFFER_CONTROL at 0x501000ec; + register uint32 EP13_OUT_BUFFER_CONTROL_raw at 0x501000ec; + + enum EP14_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP14_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12733,6 +17968,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP14_IN_BUFFER_CONTROL_t EP14_IN_BUFFER_CONTROL at 0x501000f0; + register uint32 EP14_IN_BUFFER_CONTROL_raw at 0x501000f0; + + enum EP14_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP14_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12752,6 +17995,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP14_OUT_BUFFER_CONTROL_t EP14_OUT_BUFFER_CONTROL at 0x501000f4; + register uint32 EP14_OUT_BUFFER_CONTROL_raw at 0x501000f4; + + enum EP15_IN_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP15_IN_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12771,6 +18022,14 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP15_IN_BUFFER_CONTROL_t EP15_IN_BUFFER_CONTROL at 0x501000f8; + register uint32 EP15_IN_BUFFER_CONTROL_raw at 0x501000f8; + + enum EP15_OUT_BUFFER_CONTROL_DOUBLE_BUFFER_ISO_OFFSET { + _128 = 0, // + _256 = 1, // + _512 = 2, // + _1024 = 3 // + } type EP15_OUT_BUFFER_CONTROL_t { LENGTH_0 = uint10(0); // The length of the data in buffer 0. @@ -12790,6 +18049,7 @@ // Buffer control for both buffers of an endpoint. Fields ending in a _1 are for buffer 1. Fields ending in a _0 are for buffer 0. Buffer 1 controls are only valid if the endpoint is in double buffered mode. register EP15_OUT_BUFFER_CONTROL_t EP15_OUT_BUFFER_CONTROL at 0x501000fc; + register uint32 EP15_OUT_BUFFER_CONTROL_raw at 0x501000fc; /* Types and registers for TBMAN @@ -12797,12 +18057,14 @@ */ type TBMAN_PLATFORM_t { - ASIC = false; // Indicates the platform is an ASIC - FPGA = false; // Indicates the platform is an FPGA + ASIC = false; // Indicates the platform is an ASIC + FPGA = false; // Indicates the platform is an FPGA + _res1 = uint30(0); // Reserved, 30 bits } // Indicates the type of platform in use register TBMAN_PLATFORM_t TBMAN_PLATFORM at 0x4006c000; + register uint32 TBMAN_PLATFORM_raw at 0x4006c000; /* Types and registers for VREG_AND_CHIP_RESET @@ -12816,19 +18078,23 @@ VSEL = uint4(0); // output voltage select 0000 to 0101 - 0.80V 0110 - 0.85V 0111 - 0.90V 1000 - 0.95V 1001 - 1.00V 1010 - 1.05V 1011 - 1.10V (default) 1100 - 1.15V 1101 - 1.20V 1110 - 1.25V 1111 - 1.30V _res2 = uint4(0); // Reserved, 4 bits ROK = false; // regulation status 0=not in regulation, 1=in regulation + _res3 = uint19(0); // Reserved, 19 bits } // Voltage regulator control and status register VREG_t VREG at 0x40064000; + register uint32 VREG_raw at 0x40064000; type BOD_t { EN = false; // enable 0=not enabled, 1=enabled _res1 = uint3(0); // Reserved, 3 bits VSEL = uint4(0); // threshold select 0000 - 0.473V 0001 - 0.516V 0010 - 0.559V 0011 - 0.602V 0100 - 0.645V 0101 - 0.688V 0110 - 0.731V 0111 - 0.774V 1000 - 0.817V 1001 - 0.860V (default) 1010 - 0.903V 1011 - 0.946V 1100 - 0.989V 1101 - 1.032V 1110 - 1.075V 1111 - 1.118V + _res2 = uint24(0); // Reserved, 24 bits } // brown-out detection control register BOD_t BOD at 0x40064004; + register uint32 BOD_raw at 0x40064004; type CHIP_RESET_t { _res1 = uint8(0); // Reserved, 8 bits @@ -12839,10 +18105,12 @@ HAD_PSM_RESTART = false; // Last reset was from the debug port _res4 = uint3(0); // Reserved, 3 bits PSM_RESTART_FLAG = false; // This is set by psm_restart from the debugger. Its purpose is to branch bootcode to a safe mode when the debugger has issued a psm_restart in order to recover from a boot lock-up. In the safe mode the debugger can repair the boot code, clear this flag then reboot the processor. + _res5 = uint7(0); // Reserved, 7 bits } // Chip reset control and status register CHIP_RESET_t CHIP_RESET at 0x40064008; + register uint32 CHIP_RESET_raw at 0x40064008; /* Types and registers for RTC @@ -12851,20 +18119,24 @@ type CLKDIV_M1_t { CLKDIV_M1 = uint16(0); // + _res1 = uint16(0); // Reserved, 16 bits } // Divider minus 1 for the 1 second counter. Safe to change the value when RTC is not enabled. register CLKDIV_M1_t CLKDIV_M1 at 0x4005c000; + register uint32 CLKDIV_M1_raw at 0x4005c000; type SETUP_0_t { DAY = uint5(0); // Day of the month (1..31) _res1 = uint3(0); // Reserved, 3 bits MONTH = uint4(0); // Month (1..12) YEAR = uint12(0); // Year + _res2 = uint8(0); // Reserved, 8 bits } // RTC setup register 0 register SETUP_0_t SETUP_0 at 0x4005c004; + register uint32 SETUP_0_raw at 0x4005c004; type SETUP_1_t { SEC = uint6(0); // Seconds @@ -12874,10 +18146,12 @@ HOUR = uint5(0); // Hours _res3 = uint3(0); // Reserved, 3 bits DOTW = uint3(0); // Day of the week: 1-Monday...0-Sunday ISO 8601 mod 7 + _res4 = uint5(0); // Reserved, 5 bits } // RTC setup register 1 register SETUP_1_t SETUP_1 at 0x4005c008; + register uint32 SETUP_1_raw at 0x4005c008; type RTC_CTRL_t { RTC_ENABLE = false; // Enable RTC @@ -12886,10 +18160,12 @@ LOAD = false; // Load RTC _res2 = uint3(0); // Reserved, 3 bits FORCE_NOTLEAPYEAR = false; // If set, leapyear is forced off. Useful for years divisible by 100 but not by 400 + _res3 = uint23(0); // Reserved, 23 bits } // RTC Control and status register RTC_CTRL_t RTC_CTRL at 0x4005c00c; + register uint32 RTC_CTRL_raw at 0x4005c00c; type IRQ_SETUP_0_t { DAY = uint5(0); // Day of the month (1..31) @@ -12902,10 +18178,12 @@ _res2 = false; // Reserved, 1 bits MATCH_ENA = false; // Global match enable. Don't change any other value while this one is enabled MATCH_ACTIVE = false; // + _res3 = uint2(0); // Reserved, 2 bits } // Interrupt setup register 0 register IRQ_SETUP_0_t IRQ_SETUP_0 at 0x4005c010; + register uint32 IRQ_SETUP_0_raw at 0x4005c010; type IRQ_SETUP_1_t { SEC = uint6(0); // Seconds @@ -12924,16 +18202,19 @@ // Interrupt setup register 1 register IRQ_SETUP_1_t IRQ_SETUP_1 at 0x4005c014; + register uint32 IRQ_SETUP_1_raw at 0x4005c014; type RTC_1_t { DAY = uint5(0); // Day of the month (1..31) _res1 = uint3(0); // Reserved, 3 bits MONTH = uint4(0); // Month (1..12) YEAR = uint12(0); // Year + _res2 = uint8(0); // Reserved, 8 bits } // RTC register 1. register RTC_1_t RTC_1 at 0x4005c018; + register uint32 RTC_1_raw at 0x4005c018; type RTC_0_t { SEC = uint6(0); // Seconds @@ -12943,36 +18224,46 @@ HOUR = uint5(0); // Hours _res3 = uint3(0); // Reserved, 3 bits DOTW = uint3(0); // Day of the week + _res4 = uint5(0); // Reserved, 5 bits } // RTC register 0 Read this before RTC 1! register RTC_0_t RTC_0 at 0x4005c01c; + register uint32 RTC_0_raw at 0x4005c01c; type RTC_INTR_t { - RTC = false; // + RTC = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Raw Interrupts register RTC_INTR_t RTC_INTR at 0x4005c020; + register uint32 RTC_INTR_raw at 0x4005c020; type RTC_INTE_t { - RTC = false; // + RTC = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Interrupt Enable register RTC_INTE_t RTC_INTE at 0x4005c024; + register uint32 RTC_INTE_raw at 0x4005c024; type RTC_INTF_t { - RTC = false; // + RTC = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Interrupt Force register RTC_INTF_t RTC_INTF at 0x4005c028; + register uint32 RTC_INTF_raw at 0x4005c028; type RTC_INTS_t { - RTC = false; // + RTC = false; // + _res1 = uint31(0); // Reserved, 31 bits } // Interrupt status after masking & forcing register RTC_INTS_t RTC_INTS at 0x4005c02c; + register uint32 RTC_INTS_raw at 0x4005c02c; diff --git a/lib/arch/rp/rp2040/rp2040.ld b/lib/arch/rp/rp2040/rp2040.ld index f0e1dea..9a30194 100644 --- a/lib/arch/rp/rp2040/rp2040.ld +++ b/lib/arch/rp/rp2040/rp2040.ld @@ -2,10 +2,6 @@ MEMORY { FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 2M RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 264K - /*qemu - FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 2M - RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 2K - */ } __reset_stack_pointer = ORIGIN(RAM) + LENGTH(RAM); @@ -52,17 +48,6 @@ SECTIONS . = ALIGN(4); } > FLASH - /* Machine inspectable binary information */ - . = ALIGN(4); - __binary_info_start = .; - .binary_info : - { - KEEP(*(.binary_info.keep.*)) - *(.binary_info.*) - } > RAM - __binary_info_end = .; - . = ALIGN(4); - __data_init = LOADADDR(.data); .data : { diff --git a/lib/arch/svd2rob.py b/lib/arch/svd2rob.py index 851aced..807b4bd 100644 --- a/lib/arch/svd2rob.py +++ b/lib/arch/svd2rob.py @@ -36,14 +36,18 @@ template_register = """\ // {prefix_desc}{description} - register {type}_t {prefix_name}{name} at {addr}; + register {type} {prefix_name}{name} at {addr}; """ -template_field = "\t{name: 0: - fsize = 0 - if size == 1: - ftype = "false;" - fsize = 1 - elif size in [2,3,4,5,6,7,8]: - ftype = "uint%d(0);" % size - fsize = size - elif size >= 32: - ftype = "uint32(0);" - fsize = 32 - elif size >= 16: - ftype = "uint16(0);" - fsize = 16 - elif size > 8: - ftype = "uint8(0);" - fsize = 8 - fres = {} - fres['name'] = '_res%d' % resnum - if first: - fres['description'] = 'Reserved, %d bits' % (orig_size,) - first = False - else: - fres['description'] = '' - fres['type'] = ftype - fres['start'] = start - start = start + fsize - size = size - fsize - resnum = resnum + 1; - reservedfields.append(fres) - return resnum - - -def get_fields_str(fields_node, size): + fres = {} + fres['name'] = f'_res{resnum}' + fres['description'] = f'Reserved, {size} bits' + if size == 1: + fres['type'] = "false;" + else: + fres['type'] = f"uint{size}(0);" + fres['start'] = start + reservedfields.append(fres) + + +def print_field_enumeration(register_name, field, enum_node): + enum_values = list(enum_node.iter('enumeratedValue')) + last = len(enum_values)-1 + maxlen = max([len(f.find('name').text) + len(f.find('value').text) for f in enum_values]) + + print(f" enum {register_name}_{field['name']} {{") + for i, enum_value in enumerate(enum_values): + name = enum_value.find('name').text + if name[0] >= '0' and name[0] <= '9': + name = "_" + name + value = enum_value.find('value').text + desc = enum_value.find('description') + desc = '' if desc is None else desc.text + comma = '' if i == last else ',' + leftstr = f"\t{name} = {value}{comma}" + print(f"{leftstr:<{maxlen+6}} // {desc}") + print(" }\n") + + +def get_fields_str(register_name, fields_node, size): if fields_node == None: return "" @@ -125,6 +124,10 @@ def get_fields_str(fields_node, size): if description_node is not None: field['description'] = clear_description(description_node.text) + enum_node = field_node.find('enumeratedValues') + if enum_node is not None: + print_field_enumeration(register_name, field, enum_node) + fields.append(field) fields = sorted(fields, key=lambda field: field['start']) @@ -136,7 +139,8 @@ def get_fields_str(fields_node, size): for f in fields: if f['start'] > i: #print("start: %d, i: %d\n" % (f['start'], i)) - resnum = add_reserved(reservedfields, i, f['start']-i, resnum) + add_reserved(reservedfields, i, f['start']-i, resnum) + resnum = resnum + 1 i = f['end'] + 1 # missing bits at end @@ -145,9 +149,8 @@ def get_fields_str(fields_node, size): fields = fields + reservedfields maxlen = max([len(f['name']) for f in fields]) - custom_template_field = template_field.replace('xxlenxx', str(maxlen)) fields = sorted(fields, key=lambda field: field['start']) - return "\n".join([custom_template_field.format(**f) for f in fields]) + return "\n".join([template_field.format(**f, maxlen=maxlen) for f in fields]) # map dependencies to generate peripherals prefixes @@ -178,9 +181,11 @@ def print_tags(tags): print("\t%s: %s" % (t, node.text)) print("/*") -print_tags(['vendor', 'name', 'series', 'version', 'description']) +print_tags(['vendor', 'name', 'series', 'version', 'description', 'width', 'size']) print("*/") +default_size = int(root.find('width').text) + for peripheral in root.iter('peripheral'): # peripheral name pname = peripheral.find('name').text @@ -250,6 +255,9 @@ def print_tags(tags): size_node = register.find('size') if size_node is not None: size = int(size_node.text, 0) + else: + size = default_size + regdata['type_raw'] = get_type_for_size(size) fields = register.find('fields') if fields == None: @@ -257,7 +265,9 @@ def print_tags(tags): print(template_register.format(**regdata)) else: if not isDerived: - regdata['fields'] = get_fields_str(fields, size) + regdata['fields'] = get_fields_str(regdata['name'], fields, size) print(template_type.format(**regdata)) - print(template_register.format(**regdata)) + regdata['type'] = regdata['type'] + "_t" + print(template_register.format(**regdata), end="") + print(template_register_raw.format(**regdata)) diff --git a/lib/atmega328p.rob b/lib/atmega328p.rob index eb3cc60..13e4edf 100644 --- a/lib/atmega328p.rob +++ b/lib/atmega328p.rob @@ -2,7 +2,7 @@ * Robcmp interruptions vector for atmega328p */ -int8 main(); +int16 main(); void __do_copy_data() naked { asm " @@ -37,16 +37,6 @@ asm " ret"; } -void __delay_us() naked { -asm " - ldi r18, 5 - __delay_ms_loop: - dec r18 - brne __delay_ms_loop - nop - ret"; -} - /* Weak definitions for supported interruptions */ void irq_usart_rx() naked, weak, section __irqs { } @@ -62,7 +52,7 @@ asm " timer0_millis = uint32(0); timer0_fract = uint16(0); - void irq_timer0_ovf() signal, weak, section __irqs { +void irq_timer0_ovf() signal, weak, section __irqs { timer0_millis += millis_per_ovf; timer0_fract += millis_frac_per_ovf; if (timer0_fract > 1000) { diff --git a/lib/avr5.S b/lib/avr5.S index 34c4cd6..fa07704 100644 --- a/lib/avr5.S +++ b/lib/avr5.S @@ -157,6 +157,34 @@ ENDF __mulsi3 #define r_cnt __zero_reg__ /* loop count (0 after the loop!) */ + +/******************************************************* + Division 8 / 8 => (result + remainder) +*******************************************************/ +#define r_rem r25 /* remainder */ +#define r_arg1 r24 /* dividend, quotient */ +#define r_arg2 r22 /* divisor */ +#define r_ucnt r23 /* loop count */ + +DEFUN __udivmodqi4 + sub r_rem,r_rem ; clear remainder and carry + ldi r_ucnt,9 ; init loop counter + rjmp __udivmodqi4_ep ; jump to entry point +__udivmodqi4_loop: + rol r_rem ; shift dividend into remainder + cp r_rem,r_arg2 ; compare remainder & divisor + brcs __udivmodqi4_ep ; remainder <= divisor + sub r_rem,r_arg2 ; restore remainder +__udivmodqi4_ep: + rol r_arg1 ; shift dividend (with CARRY) + dec r_ucnt ; decrement loop counter + brne __udivmodqi4_loop + com r_arg1 ; complement result + ; because C flag was complemented in loop + ret +ENDF __udivmodqi4 + + DEFUN __udivmodsi4 ldi r_remL, 33 ; init loop counter mov r_cnt, r_remL diff --git a/test/atmega328p/bitstruct-field-i5.rob b/test/atmega328p/bitstruct-field-i5.rob index 025393b..bf4e1d0 100644 --- a/test/atmega328p/bitstruct-field-i5.rob +++ b/test/atmega328p/bitstruct-field-i5.rob @@ -7,7 +7,7 @@ use arch.avr.avr5regs; int8 main() { TWCR = ETWCR.TWSTA | ETWCR.TWEN | ETWCR.TWINT; - while TWCR & ETWCR.TWINT == 0; + while (TWCR & ETWCR.TWINT) == 0; if TWSR.TWS != (0x8 >> 3) { return 1; diff --git a/test/debug/platformio.ini b/test/debug/platformio.ini index f39b390..c0546d1 100644 --- a/test/debug/platformio.ini +++ b/test/debug/platformio.ini @@ -3,6 +3,7 @@ platform = robcmp board = atmega328p upload_protocol = serial +upload_speed = 115200 [env:release] build_type = release diff --git a/test/rp2040/Makefile b/test/rp2040/Makefile index b9d2d99..3e48dda 100644 --- a/test/rp2040/Makefile +++ b/test/rp2040/Makefile @@ -18,7 +18,8 @@ LD_FLAGS+=--gc-sections LD_FLAGS+=--lto=thin DEPENDS=${ROBCMP} Makefile -LINK_DEPENDS=out/init.o ../../lib/arch/rp/rp2040/boot2.o +LINK_DEPENDS=out/init.o ../../lib/arch/rp/rp2040/boot2.o ../../lib/arm-none-eabi-thumb-v6m-libgcc.a ../../lib/cortex-m0plus-arm-missing.o +#../../lib/libclang_rt.builtins-armv6.a all: out test @@ -41,13 +42,14 @@ out/%.ll : %.rob ${DEPENDS} @-./runtest.sh $< $(patsubst %.rob,out/%,$<) out/%.uf2 : out/% + llvm-size $< ./elf2uf2/elf2uf2 -v $< $@ out/% : out/%.o ${LINK_DEPENDS} ld.lld ${LD_FLAGS} $^ -o $@ %.up : out/%.uf2 - cp out/blink.uf2 /Volumes/RPI-RP2 + cp $< /Volumes/RPI-RP2 test: ${ALL_TT} From fa1700d06ef74085d1143f6f1369a15000b1266c Mon Sep 17 00:00:00 2001 From: RayssaIssa Date: Thu, 28 Aug 2025 21:45:01 -0300 Subject: [PATCH 115/117] =?UTF-8?q?Altera=C3=A7=C3=B5es=20nos=20arquivos?= =?UTF-8?q?=20de=20conf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- butbuil | 6 ++++++ lib/lib | 1 + platformio/integrate2vc | 8 ++++---- .../__pycache__/platform.cpython-312.pyc | Bin 0 -> 3901 bytes platformio/toolchain-robcmp/Makefile | 10 +++++----- platformio/toolchain-robcmp/package.json | 8 ++++++++ platformio/toolchain-robcmp/stdlib | 2 +- platformio/toolchain-robcmp/toolchain-robcmp | 1 + 8 files changed, 26 insertions(+), 10 deletions(-) create mode 100755 butbuil create mode 120000 lib/lib create mode 100644 platformio/platform/__pycache__/platform.cpython-312.pyc create mode 100644 platformio/toolchain-robcmp/package.json create mode 120000 platformio/toolchain-robcmp/toolchain-robcmp diff --git a/butbuil b/butbuil new file mode 100755 index 0000000..a8cef49 --- /dev/null +++ b/butbuil @@ -0,0 +1,6 @@ +CXX=clang++ +CC=clang +export CXX +export CC +cmake -DCMAKE_BUILD_TYPE="Debug" .. +#cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_BUILD_TYPE="Debug" .. diff --git a/lib/lib b/lib/lib new file mode 120000 index 0000000..692df8b --- /dev/null +++ b/lib/lib @@ -0,0 +1 @@ +/home/rayssa/robcmp/lib \ No newline at end of file diff --git a/platformio/integrate2vc b/platformio/integrate2vc index 9f2044d..e387cef 100755 --- a/platformio/integrate2vc +++ b/platformio/integrate2vc @@ -5,8 +5,8 @@ cd ../lib && make cd .. mkdir -p ~/.platformio/platforms mkdir -p ~/.platformio/packages -ln -sf `realpath ../lib` toolchain-robcmp/stdlib -ln -sf `realpath platform` ~/.platformio/platforms/robcmp -ln -sf `realpath toolchain-robcmp` ~/.platformio/packages/toolchain-robcmp -code --install-extension vscode-syntax/robcmpsyntax-0.0.1.vsix +ln -sf `realpath lib` platformio/toolchain-robcmp/stdlib +ln -sf `realpath platformio/platform` ~/.platformio/platforms/robcmp +ln -sf `realpath platformio/toolchain-robcmp` ~/.platformio/packages/toolchain-robcmp +code --install-extension platformio/vscode-syntax/robcmpsyntax-0.0.1.vsix echo "Open the examples folder and try to build and upload!" diff --git a/platformio/platform/__pycache__/platform.cpython-312.pyc b/platformio/platform/__pycache__/platform.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e1a3f67b8fd5b6815c25aa333c50da2ff0e9e3d6 GIT binary patch literal 3901 zcmbtXTWk~A89p=i_Pi>M-2qlwSNG5EGK<3LWc?Q&FrX^QnfFA%Wl|e#Z&(?<4GWL*oPh| zXU^sS|MUC*zjOXCfAxA@2-=tQA0~T!2>pvp%*NCQ8v`(Sf-u5V8jX=Jou)GM7)>D> zjUsG$h_F?lUsw$JG0QX+W&T4ZSEH2Xxt8YTiJX`@$4f%O5Hb3?JlYt9`LEyv0gX`@ zjnQQ^L1F5lW6XlB`j~#`9J7*h#+WjCK#kdMpeUpHuII)RnY?K~VcH|st?)+`UP#Q&RBMkvAn2j&R8*;VM^fDy?%tm;ga?4yJyyoW5$%10y{|9 zObO9~?K4dFzz%YbO}Q|3f?NpBcIjsae^7(QZt#^6o3N*Z?vi+HYbB-~R#| zoVAtE7XbwEDs4svqV2n?`3w1Uj>lYH%*nY#F0CPr8PD+|)@+g>ruejGKy?m0TadO`*LuZ2J@MoOeE1WA~LAHMFbjU2}KLPri2VQ~k}W{w~GewcuFsM;C9c z#!e}*Q_GVpu~9WLFy~bRt*e1r%*PZ@|6+&Y8Tz-sdG@~IKe!ZKzFqTQs5&lefTJi;zeQw>$jhPMzCXc$ z+&-DC>TQ+*e8GN+GO;~FmuLz8Zorxt0IZttj;R7)z+(Llf)st1WMo@=QJal7-xYN1ax%egi$Hu12k5GpuMXKnbU#T+%`ukMSnFurOXo z>R15~req-_MQvg$(Xpg3r`be70u*YNd&0EFO!4W0Aa=m6L~fb^CNT^{u?xCl`!;B7 zow}RoOh5-v_d=3Es^<(Asnv)Xw=={&J~@zvo!U#@k2T(MQ8U%S^WL}tz3Quc}v zy!UhIfdxI6W6s7-(bFZPc|2=J=uJ^7s`$6r%d)n-FZKx&N zg9P)2zqn~DP7U{i$*nkAa5EtMZ-8!V$y%~ZQIZ|LTQQ;@`Ed(wP15l8H;!+ciF&E| zCkThY&jz)j2q-mg)Gw(L)9A)QHrh*8B8fY2xMan<^vXoz-B}8E>gzV#^+R3|x#VU& zq)_9tcCZrJij4WID1<$@8~2nLyyv%;6jU(-KP9V?4|wRPw4c#sj8w+Z0sT{;L|JzbP6+3Xr6^j2gvd5(Uu#c8V^eu*A{=F4D1y zqHFK9>pvakuARO4G0ZbXOKkGKW-)e?dQqN&%IJhjSI7uiSt|PK1|$g|JUn<*v)2ck z8|Tw8q>e^;!hFh~QkQ*u3}J*^$d8l3`i z1jh?mTrUnf*AV;2CcBMKNt%_!RdWNIg2d?#Z&izkQ7s~%S?t?ZEq1C)KvI#!K`8_l z!L~f{&G}Z@9);~$IJS7M#>Rm>xSQsC6?d1qyQ_Sm(l>i`&CNa@o*k~-Sva&p=tOwF zuyFh7XNo_z)*PBYphDNX;88kaYIFPi5tyz!nNg~#!c>xTzWI{E9$5Uj!X91vg~E=k z`w$yhII`IGyVF1y8t4xj`j<`pYFAug2bV$$`=jL(3OoA$8(`6{?q{c;o?Z>dlyGcu za+$7$PppQ|DB&}&+<&=V3ty``LTYp0wl$Q$2w_kpy#4o69 zXf51T?LJoRI9|T2218GV=Z34hV=KXdb*QapDU}^sDtz_etFXEZ^$q;UwAhCbh;WnwJg@U&aHSx)@>-zu6D)Lp19h5;2XO&+_Y}7 z?e!VCoF7s=k#!cu4=)K{rCz39`Kv#>Q9F9GI&kwHfrWO(vtJ!J^kJFTp8e|wNsQKq z(4PJ>^Vm1*tK3%{T|gVl9-TCZoq#sr+76D(@)?2SG#AHZa=4HtV-LrDTHw>hj!uVl z;v*6~Yu-B7P6+8V$3-cFC=tT_x(fkh7K?nsqgkVnb!Zdo?u!G zFNhReL^>yF0h5xaas&Cocsi933E|KUJx7K(plj6~RPKBS|D#gIS^ooBw8&Qg literal 0 HcmV?d00001 diff --git a/platformio/toolchain-robcmp/Makefile b/platformio/toolchain-robcmp/Makefile index fec367d..193a4e3 100644 --- a/platformio/toolchain-robcmp/Makefile +++ b/platformio/toolchain-robcmp/Makefile @@ -1,14 +1,14 @@ -LLVM_OBJCOPY=$(shell which llvm-objcopy-18) +LLVM_OBJCOPY=$(shell which llvm-objcopy-20) ifeq ($(LLVM_OBJCOPY),) LLVM_OBJCOPY=$(shell which llvm-objcopy) endif -LLVM_LD=$(shell which ld.lld-18) +LLVM_LD=$(shell which ld.lld-20) ifeq ($(LLVM_LD),) LLVM_LD=$(shell which ld.lld) endif -LLVM_SIZE=$(shell which llvm-size-18) +LLVM_SIZE=$(shell which llvm-size-20) ifeq ($(LLVM_SIZE),) LLVM_SIZE=$(shell which llvm-size) endif @@ -79,8 +79,8 @@ package.json: package-orig.json ../toolchain-robcmp-${suffix}-${version}.tar.gz: package.json ln -sf $(TOOLS) bin ln -sf $(LIBS) lib - if [ -f bin/ld.lld-18 ]; then cd bin && ln -s ld.lld-18 ld.lld; fi - if [ -f bin/llvm-objcopy-18 ]; then cd bin && ln -s llvm-objcopy-18 llvm-objcopy; fi + if [ -f bin/ld.lld-20 ]; then cd bin && ln -s ld.lld-20 ld.lld; fi + if [ -f bin/llvm-objcopy-20 ]; then cd bin && ln -s llvm-objcopy-20 llvm-objcopy; fi tar chfz $@ $^ bin lib clean: diff --git a/platformio/toolchain-robcmp/package.json b/platformio/toolchain-robcmp/package.json new file mode 100644 index 0000000..a1b4da2 --- /dev/null +++ b/platformio/toolchain-robcmp/package.json @@ -0,0 +1,8 @@ +{ + "name": "toolchain-robcmp", + "version": "0.1", + "description": "Robcmp Toolchain", + "keywords": ["toolchain", "build tools", "compiler", "assembler", "linker", "preprocessor", "avr", "stm32"], + "homepage": "https://thborges.github.io/robcmp", "license": "GPL-2.0", + "system": ["linux_x86_64"] +} diff --git a/platformio/toolchain-robcmp/stdlib b/platformio/toolchain-robcmp/stdlib index a3fadee..692df8b 120000 --- a/platformio/toolchain-robcmp/stdlib +++ b/platformio/toolchain-robcmp/stdlib @@ -1 +1 @@ -/Users/thborges/projects/robcmp/lib \ No newline at end of file +/home/rayssa/robcmp/lib \ No newline at end of file diff --git a/platformio/toolchain-robcmp/toolchain-robcmp b/platformio/toolchain-robcmp/toolchain-robcmp new file mode 120000 index 0000000..9355f65 --- /dev/null +++ b/platformio/toolchain-robcmp/toolchain-robcmp @@ -0,0 +1 @@ +/home/rayssa/robcmp/platformio/toolchain-robcmp \ No newline at end of file From 3c4f8fd267b5caebbb7d76320e93af516660c0b1 Mon Sep 17 00:00:00 2001 From: RayssaIssa Date: Thu, 28 Aug 2025 21:57:39 -0300 Subject: [PATCH 116/117] =?UTF-8?q?Cria=C3=A7=C3=A3o=20da=20fun=C3=A7?= =?UTF-8?q?=C3=A3o=20Atoi=20e=20seu=20arquivo=20de=20teste,=20cria=C3=A7?= =?UTF-8?q?=C3=A3o=20da=20interface=20para=20motor=20stepper=20e=20o=20tip?= =?UTF-8?q?o=20ULN2003?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/convert/atoi.rob | 23 ++++++ lib/intfs/stepper.rob | 15 ++++ lib/motor/stepper/uln2003.rob | 117 +++++++++++++++++++++++++++ test/atmega328p/stepper_uln2003.rob | 18 +++++ test/atmega328p/stepper_uln2003.spec | 9 +++ test/general/atoi.rob | 53 ++++++++++++ 6 files changed, 235 insertions(+) create mode 100644 lib/convert/atoi.rob create mode 100644 lib/intfs/stepper.rob create mode 100644 lib/motor/stepper/uln2003.rob create mode 100644 test/atmega328p/stepper_uln2003.rob create mode 100644 test/atmega328p/stepper_uln2003.spec create mode 100644 test/general/atoi.rob diff --git a/lib/convert/atoi.rob b/lib/convert/atoi.rob new file mode 100644 index 0000000..62eadd7 --- /dev/null +++ b/lib/convert/atoi.rob @@ -0,0 +1,23 @@ + +int16 atoi(char[] str, int8 base) { + result = int16(0); + i = 0; + negativo = 0; + + while i < str.size and str[i] != 0 { + if str[i] == '-'{ + negativo = 1; + }else if str[i] >= '0' and str[i] <= '9' { + result = result * base + (str[i] - '0'); + } else { + return i; + } + i++; + } + + if negativo == 1{ + result = result * -1; + } + + return result; +} \ No newline at end of file diff --git a/lib/intfs/stepper.rob b/lib/intfs/stepper.rob new file mode 100644 index 0000000..1b6cdb3 --- /dev/null +++ b/lib/intfs/stepper.rob @@ -0,0 +1,15 @@ + +enum stepper_mode {wave, fullstep, halfstep} +enum stepper_direction {clockwise, counterclockwise} + +interface stepper{ + void setup(stepper_mode mode); + + void enable(); + void disable(); + + void set_mode(stepper_mode mode); + void set_direction(stepper_direction direction); + + void step(); +} diff --git a/lib/motor/stepper/uln2003.rob b/lib/motor/stepper/uln2003.rob new file mode 100644 index 0000000..9163717 --- /dev/null +++ b/lib/motor/stepper/uln2003.rob @@ -0,0 +1,117 @@ +use intfs.ports; +use intfs.stepper; + +type uln2003 implements stepper{ + current_step = 0u; + incrementer = 0; + mode = stepper_mode.wave; + + dp1 = digitalport(); + dp2 = digitalport(); + dp3 = digitalport(); + dp4 = digitalport(); + + void setup(stepper_mode selected_mode){ + mode = selected_mode; + + dp1.mode(port_mode.output); + dp2.mode(port_mode.output); + dp3.mode(port_mode.output); + dp4.mode(port_mode.output); + } + + void set_mode(stepper_mode mode){ + if mode == stepper_mode.wave{ + if current_step % 2 == 0{ //Tem que ser indice impar + current_step++; + } + incrementer = 2; + + }else if mode == stepper_mode.halfstep{ + incrementer = 1; + + }else if mode == stepper_mode.fullstep{ + if current_step % 2 != 0{ //Tem que ser indice par + current_step++; + } + incrementer = 2; + } + } + + void set_direction(stepper_direction direction){ + set_mode(mode); + + if direction == stepper_direction.counterclockwise{ + incrementer *= -1; + } + } + + void enable(){ + dp1.set(true); + dp2.set(true); + dp3.set(true); + dp4.set(true); + } + + void disable(){ + dp1.set(false); + dp2.set(false); + dp3.set(false); + dp4.set(false); + } + + void step(){ + if current_step == 0 { //1000 + dp1.set(true); + dp2.set(false); + dp3.set(false); + dp4.set(false); + }else if current_step == 1{ //1100 + dp1.set(true); + dp2.set(true); + dp3.set(false); + dp4.set(false); + }else if current_step == 2{ //0100 + dp1.set(false); + dp2.set(true); + dp3.set(false); + dp4.set(false); + }else if current_step == 3{ //0110 + dp1.set(false); + dp2.set(true); + dp3.set(true); + dp4.set(false); + }else if current_step == 4{ //0010 + dp1.set(false); + dp2.set(false); + dp3.set(true); + dp4.set(false); + }else if current_step == 5{ //0011 + dp1.set(false); + dp2.set(false); + dp3.set(true); + dp4.set(true); + }else if current_step == 6{ //0001 + dp1.set(false); + dp2.set(false); + dp3.set(false); + dp4.set(true); + }else if current_step == 7{ //1001 + dp1.set(true); + dp2.set(false); + dp3.set(false); + dp4.set(true); + } + + current_step = (current_step + incrementer + 8) % 8; + + /*current_step += incrementer; + + if current_step > 7{ + current_step = 0; + }else if current_step < 0{ + current_step = 7; + }*/ + } +} + diff --git a/test/atmega328p/stepper_uln2003.rob b/test/atmega328p/stepper_uln2003.rob new file mode 100644 index 0000000..20790d7 --- /dev/null +++ b/test/atmega328p/stepper_uln2003.rob @@ -0,0 +1,18 @@ +use intfs.mcu; +use motor.stepper.uln2003; + +mmcu = mcu(); + +int16 main(){ + stepper_base = uln2003(); + + stepper_base.setup(stepper_mode.fullstep); + stepper_base.set_direction(stepper_direction.counterclockwise); + + loop{ + stepper_base.step(); + mmcu.wait_ms(2); + } + + return 0; +} diff --git a/test/atmega328p/stepper_uln2003.spec b/test/atmega328p/stepper_uln2003.spec new file mode 100644 index 0000000..842f07f --- /dev/null +++ b/test/atmega328p/stepper_uln2003.spec @@ -0,0 +1,9 @@ +use arch.avr.avr5mcu; + +bind avr5mcu to mmcu singleton; + +bind avr5mcu.b0 to uln2003.dp1 singleton; +bind avr5mcu.b1 to uln2003.dp2 singleton; +bind avr5mcu.b2 to uln2003.dp3 singleton; +bind avr5mcu.b3 to uln2003.dp4 singleton; + diff --git a/test/general/atoi.rob b/test/general/atoi.rob new file mode 100644 index 0000000..4c2dbfd --- /dev/null +++ b/test/general/atoi.rob @@ -0,0 +1,53 @@ + +use convert.atoi; + +strings = { + {'-', '3', '2', '1', '2', '3', 0, 0, 0, 0}, + {'-', '1', '5', '6', '7', '8', 0, 0, 0, 0}, + {'-', '4', '3', '6', '4', 0 , 0, 0, 0, 0}, + {'-', '5', '0', '1', 0 , 0 , 0, 0, 0, 0}, + {'-', '2', '5', 0 , 0 , 0 , 0, 0, 0, 0}, + {'0', 0 , 0 , 0 , 0 , 0 , 0, 0, 0, 0}, + {'2', '5', 0 , 0 , 0 , 0 , 0, 0, 0, 0}, + {'5', '1', '2', 0 , 0 , 0 , 0, 0, 0, 0}, + {'4', '3', '6', '4', 0 , 0 , 0, 0, 0, 0}, + {'1', '5', '6', '7', '8', 0 , 0, 0, 0, 0}, + {'3', '2', '7', '6', '7', 0 , 0, 0, 0, 0} +}; + +results = {-32123, -15678, -4364, -501, -25, 0, 25, 512, 4364, 15678, 32767}; + +bool check(int16 result, int16 expected){ + if result == expected{ + return true; + } + return false; +} + +int16 main() { + ok = true; + + string = {'0':10}; + + i = 0; + while i < strings.rows and ok{ + j = 0; + while j < strings.cols{ + string[j] = strings[i][j]; + j++; + } + r = atoi(string, 10); + if !check(r, results[i]){ + ok = false; + } + i++; + } + + if ok{ + return 0; + } else { + return i; + } +} + + From 29703f582e216d67d333281a46b19106ea29cd26 Mon Sep 17 00:00:00 2001 From: Rayssa Date: Tue, 2 Dec 2025 16:04:26 -0300 Subject: [PATCH 117/117] =?UTF-8?q?Altera=C3=A7=C3=B5es=20em=20toolchain-r?= =?UTF-8?q?obcmp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simavr | 1 + 1 file changed, 1 insertion(+) create mode 160000 simavr diff --git a/simavr b/simavr new file mode 160000 index 0000000..bf8937e --- /dev/null +++ b/simavr @@ -0,0 +1 @@ +Subproject commit bf8937edb1022bd3e0602e1da9ede3af549ff5a2