Implement a new DTS Source Language
Subsystems (2)
v3 cover Implement a new DTS Source Language
This series of patches enhances the DTS source language to support a fullly interpreted language for generating nodes and properties. It is backward compatible with V1 sources.
The main features implemented by this patch set support function definitions, 'if', 'for', 'return' and assignment statements. Local variables, global constants and almost complete C-like expressions are also supported.
Enhancements to the source position and error/warning reporting now support source column positions too.
Version 1 was the original posting.
Version 2 only fixed one patch in the series
This is Version 3 and it includes fixes and suggestions due to community review and feedback, and includes a new patch that provides some testing. Git bisectability has been ensured as well.
Jon Loeliger (9):
Remove support for the legacy DTS source file format. Add conditionalized debug() print macro. Enhance source position implementation.
Add header files for new Internal Representation form. Add most of the new IR implementation files. Add the main IR evaluation implementation Introduce new DTS language.
Add documentation for the new DTS language. Test constant expressions in cell contexts.
Documentation/manual.txt | 500 ++++++++++++++-- Makefile | 2 +- Makefile.dtc | 18 +- dtc-lexer.l | 311 +++++++--- dtc-parser.y | 721 ++++++++++++++++------ dtc.c | 7 +- dtc.h | 9 + ir.c | 190 ++++++ ir.h | 175 ++++++ ir_builtin.c | 180 ++++++ ir_builtin.h | 31 + ir_dump.c | 211 +++++++ ir_emit.c | 490 +++++++++++++++ ir_eval.c | 1502 +++++++++++++++++++++++++++++++++++++++++++++ ir_scope.c | 318 ++++++++++ ir_scope.h | 114 ++++ livetree.c | 16 + nv.c | 108 ++++ nv.h | 34 + srcpos.c | 142 ++++- srcpos.h | 23 +- tests/Makefile.tests | 1 + tests/base01.dts | 24 +- tests/cell-expressions.c | 116 ++++ tests/empty.dts | 2 + tests/escapes.dts | 2 + tests/label01.dts | 38 +- tests/references_dts0.dts | 12 +- tests/run_tests.sh | 32 +- tests/test01.dts | 38 +- tests/test_tree1_dts0.dts | 18 +- treesource.c | 3 + 32 files changed, 4987 insertions(+), 401 deletions(-) create mode 100644 ir.c create mode 100644 ir.h create mode 100644 ir_builtin.c create mode 100644 ir_builtin.h create mode 100644 ir_dump.c create mode 100644 ir_emit.c create mode 100644 ir_eval.c create mode 100644 ir_scope.c create mode 100644 ir_scope.h create mode 100644 nv.c create mode 100644 nv.h create mode 100644 tests/cell-expressions.c
A message that is not in the archive (sent off-list or not yet received): 1222460748-20127-1-git-send-email-jdl-CYoMK+44s/[email protected]
PATCH v3 1/9 Remove support for the legacy DTS source file format.
Now that all in-kernel-tree DTS files are properly /dts-v1/, remove direct support for the older, un-numbered DTS source file format.
Convert existing tests to /dts-v1/ and remove support for the conversion tests themselves.
For now, though, the conversion tool still exists.
--- dtc-lexer.l | 40 +------------------------------------- dtc-parser.y | 46 --------------------------------------------- tests/base01.dts | 24 ++++++++++++---------- tests/empty.dts | 2 + tests/escapes.dts | 2 + tests/label01.dts | 38 +++++++++++++++++++----------------- tests/references_dts0.dts | 12 ++++++---- tests/run_tests.sh | 27 +------------------------- tests/test01.dts | 38 +++++++++++++++++++----------------- tests/test_tree1_dts0.dts | 18 +++++++++------- 10 files changed, 77 insertions(+), 170 deletions(-)
dtc-lexer.l +2 -38
@@ -47,15 +47,10 @@ LINECOMMENT "//".*\n #define DPRINT(fmt, ...) do { } while (0) #endif -static int dts_version; /* = 0 */ +static int dts_version = 1; -#define BEGIN_DEFAULT() if (dts_version == 0) { \ - DPRINT("<INITIAL>\n"); \ - BEGIN(INITIAL); \ - } else { \ - DPRINT("<V1>\n"); \ +#define BEGIN_DEFAULT() DPRINT("<V1>\n"); \ BEGIN(V1); \ - } static void push_input_file(const char *filename); static int pop_input_file(void);
@@ -110,29 +105,6 @@ static int pop_input_file(void); return DT_LABEL; } -<INITIAL>[bodh]# { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; - if (*yytext == 'b') - yylval.cbase = 2; - else if (*yytext == 'o') - yylval.cbase = 8; - else if (*yytext == 'd') - yylval.cbase = 10; - else - yylval.cbase = 16; - DPRINT("Base: %d\n", yylval.cbase); - return DT_BASE; - } - -<INITIAL>[0-9a-fA-F]+ { - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; - yylval.literal = strdup(yytext); - DPRINT("Literal: '%s'\n", yylval.literal); - return DT_LEGACYLITERAL; - } - <V1>[0-9]+|0[xX][0-9a-fA-F]+ { yylloc.file = srcpos_file; yylloc.first_line = yylineno;
@@ -158,14 +130,6 @@ static int pop_input_file(void); return DT_REF; } -<INITIAL>"&/"{PATHCHAR}+ { /* old-style path reference */ - yylloc.file = srcpos_file; - yylloc.first_line = yylineno; - DPRINT("Ref: %s\n", yytext+1); - yylval.labelref = strdup(yytext+1); - return DT_REF; - } - <BYTESTRING>[0-9a-fA-F]{2} { yylloc.file = srcpos_file; yylloc.first_line = yylineno;
dtc-parser.y +0 -46
88 lines not on this page · raw message
tests/base01.dts +13 -11
@@ -1,3 +1,5 @@ +/dts-v1/; + / { model = "SomeModel"; compatible = "Nothing";
@@ -6,26 +8,26 @@ memory@0 { device_type = "memory"; - reg = <00000000 00000000 00000000 20000000>; + reg = <0x00000000 0x00000000 0x00000000 0x20000000>; }; cpus { #address-cells = <1>; #size-cells = <0>; - d10 = <d# 10>; // hex: 0xa - d23 = <d# 23>; // hex: 0x17 - b101 = <b# 101>; // hex: 0x5 - o17 = <o# 17>; // hex: 0xf - hd00d = <h# d00d>; // hex: 0xd00d + d10 = < 10>; // hex: 0xa + d23 = < 23>; // hex: 0x17 + b101 = < 0x5>; // hex: 0x5 + o17 = < 017>; // hex: 0xf + hd00d = < 0xd00d>; // hex: 0xd00d // hex: 0x4d2 0x163e 0x2334 0xd80 - stuff = <d# 1234 d# 5678 d# 9012 d# 3456>; + stuff = < 1234 5678 9012 3456>; - bad-d-1 = <d# abc123>; // Hrm. 0 - bad-d-2 = <d# 123456789012345>; - bad-o-1 = <o# 891>; - bad-o-2 = <o# 123456123456>; + bad-d-1 = < 0>; // Hrm. 0 + bad-d-2 = < 123456789012345>; + bad-o-1 = < 00>; + bad-o-2 = < 0123456123456>; }; };
tests/empty.dts +2 -0
@@ -1,2 +1,4 @@ +/dts-v1/; + / { };
tests/escapes.dts +2 -0
@@ -1,3 +1,5 @@ +/dts-v1/; + / { compatible = "test_string_escapes"; escape-str = "nastystring: \a\b\t\n\v\f\r\\\"";
tests/label01.dts +20 -18
@@ -1,6 +1,8 @@ -/memreserve/ 1000000000000000 0000000002000000; -memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff; -/memreserve/ 0-13; +/dts-v1/; + +/memreserve/ 0x1000000000000000 0x0000000002000000; +memrsv2: /memreserve/ 0x2000000000000000 0x0100000000000000; +/memreserve/ 0x0000000000000000 0x0000000000000014; / { model = "MyBoardName";
@@ -9,28 +11,28 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff; #size-cells = <2>; cpus { - linux,phandle = <1>; + linux,phandle = <0x1>; #address-cells = <1>; #size-cells = <0>; PowerPC,970@0 { name = "PowerPC,970"; device_type = "cpu"; - reg = <0>; - clock-frequency = <5f5e1000>; - timebase-frequency = <1FCA055>; + reg = <0x00000000>; + clock-frequency = <1600000000>; + timebase-frequency = <33333333>; linux,boot-cpu; - i-cache-size = <10000>; - d-cache-size = <8000>; + i-cache-size = <65536>; + d-cache-size = <32768>; }; PowerPC,970@1 { name = "PowerPC,970"; device_type = "cpu"; - reg = <1>; - clock-frequency = <5f5e1000>; - timebase-frequency = <1FCA055>; - i-cache-size = <10000>; - d-cache-size = <8000>; + reg = <0x00000001>; + clock-frequency = <1600000000>; + timebase-frequency = <33333333>; + i-cache-size = <65536>; + d-cache-size = <32768>; }; };
@@ -38,8 +40,8 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff; node: randomnode { prop: string = str: "foo", str_mid: "stuffstuff\t\t\t\n\n\n" str_end: ; blob = [byte: 0a 0b 0c 0d byte_mid: de ea ad be ef byte_end: ]; - ref = < cell: &/memory@0 0 cell_mid: ffffffff cell_end: >; - mixed = "abc", pre: [1234] post: , gap: < aligned: a b c>; + ref = < cell: &{/memory@0} 0x0 cell_mid: 0xffffffff cell_end: >; + mixed = "abc", pre: [1234] post: , gap: < aligned: 0xa 0xb 0xc>; tricky1 = [61 lt1: 62 63 00]; subnode: child { };
@@ -49,12 +51,12 @@ memrsv2: /memreserve/ 2000000000000000-20ffffffffffffff; memory@0 { device_type = "memory"; - memreg: reg = <00000000 00000000 00000000 20000000>; + memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>; }; chosen { bootargs = "root=/dev/sda2"; - linux,platform = <00000600>; + linux,platform = <0x600>; }; };
tests/references_dts0.dts +7 -5
@@ -1,19 +1,21 @@ +/dts-v1/; + / { /* Explicit phandles */ n1: node1 { - linux,phandle = <2000>; - ref = <&/node2>; /* reference precedes target */ + linux,phandle = <0x2000>; + ref = <&{/node2}>; /* reference precedes target */ lref = <&n2>; }; n2: node2 { - linux,phandle = <1>; - ref = <&/node1>; /* reference after target */ + linux,phandle = <0x1>; + ref = <&{/node1}>; /* reference after target */ lref = <&n1>; }; /* Implicit phandles */ n3: node3 { - ref = <&/node4>; + ref = <&{/node4}>; lref = <&n4>; }; n4: node4 {
tests/run_tests.sh +1 -26
@@ -71,13 +71,6 @@ run_dtc_test () { base_run_test wrap_test $VALGRIND $DTC "$@" } -CONVERT=../convert-dtsv0 - -run_convert_test () { - echo -n "convert-dtsv0 $@: " - base_run_test wrap_test $VALGRIND $CONVERT "$@" -} - tree1_tests () { TREE=$1
@@ -287,21 +280,6 @@ dtc_tests () { run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile } -convert_tests () { - V0_DTS="test_tree1_dts0.dts references_dts0.dts empty.dts escapes.dts \ - test01.dts label01.dts" - for dts in $V0_DTS; do - run_dtc_test -I dts -O dtb -o cvtraw_$dts.test.dtb $dts - run_dtc_test -I dts -O dts -o cvtdtc_$dts.test.dts $dts - run_dtc_test -I dts -O dtb -o cvtdtc_$dts.test.dtb cvtdtc_$dts.test.dts - run_convert_test $dts - run_dtc_test -I dts -O dtb -o cvtcvt_$dts.test.dtb ${dts}v1 - - run_wrap_test cmp cvtraw_$dts.test.dtb cvtdtc_$dts.test.dtb - run_wrap_test cmp cvtraw_$dts.test.dtb cvtcvt_$dts.test.dtb - done -} - while getopts "vt:m" ARG ; do case $ARG in "v")
@@ -317,7 +295,7 @@ while getopts "vt:m" ARG ; do done if [ -z "$TESTSETS" ]; then - TESTSETS="libfdt dtc convert" + TESTSETS="libfdt dtc" fi # Make sure we don't have stale blobs lying around
@@ -331,9 +309,6 @@ for set in $TESTSETS; do "dtc") dtc_tests ;; - "convert") - convert_tests - ;; esac done
tests/test01.dts +20 -18
@@ -1,6 +1,8 @@ -/memreserve/ 1000000000000000 0000000002000000; -/memreserve/ 2000000000000000-20ffffffffffffff; -/memreserve/ 0-13; +/dts-v1/; + +/memreserve/ 0x1000000000000000 0x0000000002000000; +/memreserve/ 0x2000000000000000 0x0100000000000000; +/memreserve/ 0x0000000000000000 0x0000000000000014; / { model = "MyBoardName";
@@ -9,28 +11,28 @@ #size-cells = <2>; cpus { - linux,phandle = <1>; + linux,phandle = <0x1>; #address-cells = <1>; #size-cells = <0>; PowerPC,970@0 { name = "PowerPC,970"; device_type = "cpu"; - reg = <0>; - clock-frequency = <5f5e1000>; - timebase-frequency = <1FCA055>; + reg = <0x00000000>; + clock-frequency = <1600000000>; + timebase-frequency = <33333333>; linux,boot-cpu; - i-cache-size = <10000>; - d-cache-size = <8000>; + i-cache-size = <65536>; + d-cache-size = <32768>; }; PowerPC,970@1 { name = "PowerPC,970"; device_type = "cpu"; - reg = <1>; - clock-frequency = <5f5e1000>; - timebase-frequency = <1FCA055>; - i-cache-size = <10000>; - d-cache-size = <8000>; + reg = <0x00000001>; + clock-frequency = <1600000000>; + timebase-frequency = <33333333>; + i-cache-size = <65536>; + d-cache-size = <32768>; }; };
@@ -38,18 +40,18 @@ randomnode { string = "\xff\0stuffstuff\t\t\t\n\n\n"; blob = [0a 0b 0c 0d de ea ad be ef]; - ref = < &/memory@0 >; - mixed = "abc", [1234], <a b c>; + ref = < &{/memory@0} >; + mixed = "abc", [1234], <0xa 0xb 0xc>; }; memory@0 { device_type = "memory"; - memreg: reg = <00000000 00000000 00000000 20000000>; + memreg: reg = <0x00000000 0x00000000 0x00000000 0x20000000>; }; chosen { bootargs = "root=/dev/sda2"; - linux,platform = <00000600>; + linux,platform = <0x600>; }; };
tests/test_tree1_dts0.dts +10 -8
@@ -1,9 +1,11 @@ -/memreserve/ deadbeef00000000-deadbeef000fffff; -/memreserve/ 75bcd15 1000; +/dts-v1/; + +/memreserve/ 0xdeadbeef00000000 0x0000000000100000; +/memreserve/ 0x00000000075bcd15 0x0000000000001000; / { compatible = "test_tree1"; - prop-int = <deadbeef>; + prop-int = <0xdeadbeef>; prop-str = "hello world"; subnode@1 {
@@ -12,18 +14,18 @@ subsubnode { compatible = "subsubnode1", "subsubnode"; - prop-int = <h# deadbeef>; + prop-int = < 0xdeadbeef>; }; }; subnode@2 { - linux,phandle = <2000>; - prop-int = <d# 123456789>; + linux,phandle = <0x2000>; + prop-int = < 123456789>; subsubnode@0 { - linux,phandle = <2001>; + linux,phandle = <0x2001>; compatible = "subsubnode2", "subsubnode"; - prop-int = <o# 0726746425>; + prop-int = < 0726746425>; }; }; };
Signature · 1 line
1.6.0.90.g436ed
A message that is not in the archive (sent off-list or not yet received): 1222460748-20127-2-git-send-email-jdl-CYoMK+44s/[email protected]
PATCH v3 2/9 Add conditionalized debug() print macro.
From: Jon Loeliger <[email protected]>
--- dtc.h | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
dtc.h +8 -0
@@ -34,7 +34,15 @@#include <libfdt_env.h> #include <fdt.h> +#ifdef DEBUG +#define debug(fmt,args...) printf(fmt, ##args) +#else +#define debug(fmt,args...) +#endif + +#define DEFAULT_FDT_VERSION 17 +/* * Command line options */
Signature · 1 line
1.6.0.90.g436ed
A message that is not in the archive (sent off-list or not yet received): 1222460748-20127-3-git-send-email-jdl-CYoMK+44s/[email protected]
PATCH v3 3/9 Enhance source position implementation.
Implemented some print and copy routines. Made empty srcpos objects that will be used later. Protected .h file from multiple #include's.
--- srcpos.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- srcpos.h | 19 ++++++++++++ 2 files changed, 107 insertions(+), 7 deletions(-)
srcpos.c +88 -7
@@ -23,12 +23,29 @@/* * Like yylineno, this is the current open file pos. */ -struct dtc_file *srcpos_file; -static int dtc_open_one (struct dtc_file *file, -const char *search, -const char *fname) +/* +* The empty source position. +*/ + +struct dtc_file dtc_empty_file = { + .dir =NULL , + .name ="<no file>" , + .file =NULL +}; + +srcpos srcpos_empty = { + .first_line =0 , + .first_column =0 , + .last_line =0 , + .last_column =0 , + .file = &dtc_empty_file +}; + + +static int +dtc_open_one (struct dtc_file *file,const char *search,const char *fname) {char *fullname;
@@ -53,8 +70,8 @@ static int dtc_open_one(struct dtc_file *file, } -struct dtc_file *dtc_open_file (const char *fname, -const struct search_path *search) +struct dtc_file * +dtc_open_file (const char *fname,const struct search_path *search) {static const struct search_path default_search = {NULL ,NULL ,NULL };
@@ -106,7 +123,9 @@ fail:die ("Couldn't open \"%s\": %s\n" , fname,strerror (errno)); } -void dtc_close_file (struct dtc_file *file) + +void +dtc_close_file (struct dtc_file *file) {if (fclose (file->file))die ("Error closing \"%s\": %s\n" , file->name,strerror (errno));
@@ -114,3 +133,65 @@ void dtc_close_file(struct dtc_file *file)free (file->dir);free (file); } + + +srcpos * +srcpos_copy (srcpos *pos) +{ +srcpos *pos_new; + + pos_new =xmalloc (sizeof (srcpos)); +memcpy (pos_new, pos,sizeof (srcpos)); + +return pos_new; +} + + + +void +srcpos_dump (srcpos *pos) +{ +printf ("file : \"%s\"\n" , + pos->file ? (char *) pos->file :"<no file>" ); +printf ("first_line : %d\n" , pos->first_line); +printf ("first_column: %d\n" , pos->first_column); +printf ("last_line : %d\n" , pos->last_line); +printf ("last_column : %d\n" , pos->last_column); +printf ("file : %s\n" , pos->file->name); +} + + +char * +srcpos_string (srcpos *pos) +{ +# define POS_BUF_SIZE (100) + +const char *fname; +char buf[POS_BUF_SIZE ]; + +if (pos->file && pos->file->name) + fname = pos->file->name; +else + fname ="<no-file>" ; + +if (pos->first_line == pos->last_line) { +if (pos->first_column == pos->last_column) { +snprintf (buf,POS_BUF_SIZE ,"%s %d:%d" , + fname, pos->first_line, pos->first_column); + }else { +snprintf (buf,POS_BUF_SIZE ,"%s %d:%d-%d" , + fname, pos->first_line, + pos->first_column, pos->last_column); + } + + }else { +snprintf (buf,POS_BUF_SIZE ,"%s %d:%d - %d:%d" , + fname, + pos->first_line, pos->first_column, + pos->last_line, pos->last_column); + } + +return strdup (buf); + +# undef POS_BUF_SIZE +}
srcpos.h +19 -0
@@ -17,6 +17,9 @@* USA */ +#ifndef _SRCPOS_H_ +#define _SRCPOS_H_ +/* * Augment the standard YYLTYPE with a filenum index into an * array of all opened filenames.
@@ -69,6 +72,16 @@ typedef struct YYLTYPE {while (YYID (0 )) +typedef YYLTYPE srcpos; + +/* +* Fictional source position used for IR nodes that are +* created without otherwise knowing a true source position. +* For example,constant definitions from the command line. +*/ +extern srcpos srcpos_empty; + +extern void yyerror (char const *);extern void yyerrorf (char const *, ...) __attribute__((format (printf,1 ,2 )));
@@ -83,3 +96,9 @@ struct search_path {extern struct dtc_file *dtc_open_file (const char *fname,const struct search_path *search);extern void dtc_close_file (struct dtc_file *file); + +extern srcpos *srcpos_copy (srcpos *pos); +extern char *srcpos_string (srcpos *pos); +extern void srcpos_dump (srcpos *pos); + +#endif /* _SRCPOS_H_ */
Signature · 1 line
1.6.0.90.g436ed
A message that is not in the archive (sent off-list or not yet received): 1222460748-20127-4-git-send-email-jdl-CYoMK+44s/[email protected]
PATCH v3 4/9 Add header files for new Internal Representation form.
--- ir.h | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ir_builtin.h | 31 ++++++++++ ir_scope.h | 114 +++++++++++++++++++++++++++++++++++++ 3 files changed, 321 insertions(+), 0 deletions(-) create mode 100644 ir.h create mode 100644 ir_builtin.h create mode 100644 ir_scope.h
ir.h new file +176 -0
@@ -0,0 +1,176 @@ +/* +* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of the +* License, or (at your option) any later version. +* +* This program 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 +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +* USA +*/ + +#ifndef _IR_H_ +#define _IR_H_ + +#include "srcpos.h" +#include "ir_builtin.h" + + +#define IR_UNDEF 0 +#define IR_ROOT 1 +#define IR_MEM_RESERVE 2 +#define IR_ASSIGN 3 +#define IR_PROP_DEF 4 +#define IR_REF_PHANDLE 5 +#define IR_REF_PATH 6 +#define IR_CELL 7 +#define IR_LITERAL 8 +#define IR_LIT_STR 9 +#define IR_LIT_BYTE 10 +#define IR_LABEL 11 +#define IR_LIST 12 +#define IR_INCBIN 13 +#define IR_BUILTIN 14 +#define IR_SELECT 15 +#define IR_OR 16 +#define IR_AND 17 +#define IR_BIT_OR 18 +#define IR_BIT_XOR 19 +#define IR_BIT_AND 20 +#define IR_EQ 21 +#define IR_LT 22 +#define IR_LE 23 +#define IR_GT 24 +#define IR_GE 25 +#define IR_NE 26 +#define IR_LSHIFT 27 +#define IR_RSHIFT 28 +#define IR_ADD 29 +#define IR_MINUS 30 +#define IR_MULT 31 +#define IR_DIV 32 +#define IR_MOD 33 +#define IR_UMINUS 34 +#define IR_BIT_COMPL 35 +#define IR_NOT 36 +#define IR_FUNC_DEF 37 +#define IR_FOR 38 +#define IR_RETURN 39 +#define IR_RANGE 40 +#define IR_ID 41 +#define IR_IF 42 +#define IR_PARAMDECL 43 +#define IR_FUNC_CALL 44 +#define IR_NODE 45 +#define IR_PROPNODENAME 46 +#define IR_LIT_CELL 47 +#define IR_LIT_ADDR 48 +#define IR_CVT_PROPNODENAME 49 +#define IR_CVT_STRING 50 +#define IR_CONST_DEF 51 + +#define IR_NUM_TYPES 52 + + +typedef unsigned int ir_type ; + +extern char const *ir_type_string (ir_type ir_type); + + +struct ir { +ir_type ir_type; +srcpos *ir_srcpos; + +long long ir_literal; +char *ir_lit_str; +char *ir_label_name; +irb_id ir_builtin_id; + +struct ir *ir_name; +struct ir *ir_label; +struct ir *ir_expr1; +struct ir *ir_expr2; +struct ir *ir_expr3; + +struct ir *ir_mem_reserves; +struct ir *ir_statements; +struct ir *ir_statements2; +struct ir *ir_declarations; + +struct ir *ir_first; +struct ir *ir_last; +struct ir *ir_prev; +struct ir *ir_next; +}; + + +extern struct ir *the_ir_tree; + +extern struct ir *ir_alloc (ir_type ir_type,srcpos *); +extern struct ir *ir_copy (struct ir *ir);/* shallow copy */ +extern void ir_free (struct ir *ir); +extern void ir_free_all (struct ir *ir); + +extern struct ir *ir_alloc_unop (ir_type ir_type, +struct ir *ir1, +srcpos *pos); +extern struct ir *ir_alloc_binop (ir_type ir_type, +struct ir *ir1, +struct ir *ir2, +srcpos *pos); +extern struct ir *ir_alloc_triop (ir_type ir_type, +struct ir *ir1, +struct ir *ir2, +struct ir *ir3, +srcpos *pos); +extern struct ir *ir_list_append (struct ir *ir_list,struct ir *ir_node); +extern void ir_dump (struct ir *ir); +extern struct ir *ir_eval (struct ir *ir); +extern struct ir_scope *ir_eval_func_body (struct ir *ir_func); + +extern void ir_process (void ); +extern struct ir *ir_simplify (struct ir *ir,unsigned int ctxt); +extern void ir_emit (struct ir *ir); +extern void ir_emit_statement_list (struct ir *ir_list); + + +#define IR_EVAL_CTXT_ANY 0 +#define IR_EVAL_CTXT_CELL 1 + +extern int ir_is_constant (struct ir *ir); +extern int ir_is_string (struct ir *ir); +extern char *ir_eval_for_label (struct ir *ir); +extern char *ir_eval_for_name (struct ir *ir); +extern uint64_t ir_eval_for_addr (struct ir *ir); +extern void ir_eval_for_data (struct ir *ir,struct data *d); +extern char *ir_eval_for_c_string (struct ir *ir); + + +/* +* IR Messaging. +*/ + +#define IR_SEV_INFO 0 +#define IR_SEV_WARN 1 +#define IR_SEV_ERROR 2 + +typedef unsigned int ir_severity_t ; + +#define ir_info(ir, fmt...) ir_msg(IR_SEV_INFO, ir, ##fmt) +#define ir_warn(ir, fmt...) ir_msg(IR_SEV_WARN, ir, ##fmt) +#define ir_error(ir, fmt...) ir_msg(IR_SEV_ERROR, ir, ##fmt) + +extern void ir_msg (ir_severity_t severity, +struct ir *ir, +char const *fmt, ...) + __attribute__((format (printf,3 ,4 ))); + +#endif /* _IR_H_ */
ir_builtin.h new file +31 -0
@@ -0,0 +1,31 @@ +/* +* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of the +* License, or (at your option) any later version. +* +* This program 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 +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +* USA +*/ + +#ifndef _IR_BUILTIN_H_ +#define _IR_BUILTIN_H_ + + +typedef int irb_id ; + +#define IRB_UNDEF (-1) + +extern irb_id ir_lookup_builtin_by_name (char *str_name); +extern struct ir *ir_eval_builtin (struct ir *ir); + +#endif /* _IR_BUILTIN_H_ */
ir_scope.h new file +114 -0
114 lines not on this page · raw message
Signature · 1 line
1.6.0.90.g436ed
A message that is not in the archive (sent off-list or not yet received): 1222460748-20127-5-git-send-email-jdl-CYoMK+44s/[email protected]
PATCH v3 5/9 Add most of the new IR implementation files.
--- ir.c | 190 ++++++++++++++++++++++ ir_builtin.c | 180 +++++++++++++++++++++ ir_dump.c | 220 ++++++++++++++++++++++++++ ir_emit.c | 491 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ir_scope.c | 319 +++++++++++++++++++++++++++++++++++++ 5 files changed, 1400 insertions(+), 0 deletions(-) create mode 100644 ir.c create mode 100644 ir_builtin.c create mode 100644 ir_dump.c create mode 100644 ir_emit.c create mode 100644 ir_scope.c
ir.c new file +190 -0
@@ -0,0 +1,190 @@ +/* +* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of the +* License, or (at your option) any later version. +* +* This program 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 +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +* USA +*/ + +#include "dtc.h" +#include "ir.h" + +extern int treesource_error; + + +struct ir *the_ir_tree; + + +extern struct ir * +ir_alloc (ir_type ir_type,srcpos *pos) +{ +struct ir *ir; + + ir =xmalloc (sizeof (struct ir )); +memset (ir,0 ,sizeof (struct ir )); + + ir->ir_type = ir_type; + ir->ir_srcpos =srcpos_copy (pos); + +return ir; +} + + +/* +* Shallow copy, mostly. +* +* Note that things like the immediate strings and source position +* are copied, but the sub-IR-expressions are not. +*/ +extern struct ir * +ir_copy (struct ir *ir) +{ +struct ir *ir_new; + +if (!ir) +return NULL ; + + ir_new =ir_alloc (ir->ir_type, ir->ir_srcpos); + ir_new->ir_literal = ir->ir_literal; +if (ir->ir_lit_str) + ir_new->ir_lit_str =strdup (ir->ir_lit_str); +if (ir->ir_label_name) + ir_new->ir_label_name =strdup (ir->ir_label_name); + +return ir_new; +} + + +void +ir_free (struct ir *ir) +{ +} + + +void +ir_free_all (struct ir *ir) +{ +} + + +extern struct ir * +ir_alloc_unop (ir_type ir_type,struct ir *ir1,srcpos *pos) +{ +struct ir *ir; + + ir =ir_alloc (ir_type, pos); + ir->ir_expr1 = ir1; + +return ir; +} + + +extern struct ir * +ir_alloc_binop (ir_type ir_type, +struct ir *ir1,struct ir *ir2, +srcpos *pos) +{ +struct ir *ir; + + ir =ir_alloc (ir_type, pos); + ir->ir_expr1 = ir1; + ir->ir_expr2 = ir2; + +return ir; +} + + +extern struct ir * +ir_alloc_triop (ir_type ir_type, +struct ir *ir1,struct ir *ir2,struct ir *ir3, +srcpos *pos) +{ +struct ir *ir; + + ir =ir_alloc (ir_type, pos); + ir->ir_expr1 = ir1; + ir->ir_expr2 = ir2; + ir->ir_expr3 = ir3; + +return ir; +} + + +extern struct ir * +ir_list_append (struct ir *ir_list,struct ir *ir_node) +{ +if (ir_node ==NULL ) { +return ir_list; + } + +if (ir_list ==NULL ) { + ir_list =ir_alloc (IR_LIST , ir_node->ir_srcpos); + } + + ir_node->ir_prev = ir_list->ir_last; + +if (ir_list->ir_last) { + ir_list->ir_last->ir_next = ir_node; + }else { + ir_list->ir_first = ir_node; + } + + ir_list->ir_last = ir_node; + +return ir_list; +} + + +void +ir_process (void ) +{ +/* +* FIXME: Fix leaking the whole orginal IR tree here. +*/ + the_ir_tree =ir_simplify (the_ir_tree,IR_EVAL_CTXT_ANY ); + +ir_emit (the_ir_tree); +} + + +static const char *ir_severity_str[] = { +"Info" , +"Warning" , +"Error" , +}; + +#define IR_NUM_SEV ARRAY_SIZE(ir_severity_str) + + +void +ir_msg (ir_severity_t severity,struct ir *ir,char const *fmt, ...) +{ +srcpos *pos; +const char *srcstr; +va_list va; +va_start (va, fmt); + + pos = ir ? ir->ir_srcpos : &srcpos_empty; + srcstr =srcpos_string (pos); + +if (severity >=IR_NUM_SEV ) + severity =IR_SEV_INFO ; + +fprintf (stderr,"%s: %s " , ir_severity_str[severity], srcstr); + +vfprintf (stderr, fmt, va); +fprintf (stderr,"\n" ); + +va_end (va); +}
ir_builtin.c new file +180 -0
180 lines not on this page · raw message
ir_dump.c new file +220 -0
220 lines not on this page · raw message
ir_emit.c new file +491 -0
491 lines not on this page · raw message
ir_scope.c new file +319 -0
319 lines not on this page · raw message
Signature · 1 line
1.6.0.90.g436ed
A message that is not in the archive (sent off-list or not yet received): 1222460748-20127-6-git-send-email-jdl-CYoMK+44s/[email protected]
PATCH v3 6/9 Add the main IR evaluation implementation
--- ir_eval.c | 1504 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 1504 insertions(+), 0 deletions(-) create mode 100644 ir_eval.c
ir_eval.c new file +1504 -0
@@ -0,0 +1,1504 @@ +/* +* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of the +* License, or (at your option) any later version. +* +* This program 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 +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +* USA +*/ + +#include <stdio.h> + +#include "dtc.h" +#include "srcpos.h" +#include "ir.h" +#include "ir_scope.h" + + +/* +* Returns: +* 0 on success, with *val filled in +* -1 == bad characters in literal number +* -2 == literal out of range +* -3 == bad literal +*/ + +int +ir_eval_literal_guessing (const char *s,int base,int bits, +unsigned long long *val) +{ +char *e; + + errno =0 ; + *val =strtoull (s, &e, base); + +if (*e) +return -1 ; +else if ((errno ==ERANGE ) + || ((bits <64 ) && (*val >= (1ULL << bits)))) +return -2 ; +else if (errno !=0 ) +return -3 ; + +return 0 ; +} + +unsigned long long +ir_eval_literal_str (const char *s,int base,int bits) +{ +unsigned long long val; +char *e; + + errno =0 ; + val =strtoull (s, &e, base); + +if (*e) +die ("bad characters in literal" ); +else if ((errno ==ERANGE ) + || ((bits <64 ) && (val >= (1ULL << bits)))) +die ("literal out of range" ); +else if (errno !=0 ) +die ("bad literal" ); + +return val; +} + + +struct ir * +ir_eval_cvt_to_string (struct ir *ir) +{ +char buf[30 ]; +unsigned long long lit1; +struct ir *ir_new; + + ir_new =ir_alloc (IR_LIT_STR , ir->ir_srcpos); +if (ir_is_constant (ir)) { + lit1 =ir_eval_for_addr (ir); +snprintf (buf,30 ,"%llu" , lit1); + ir_new->ir_lit_str =strdup (buf); + }else { +ir_error (ir, +"Can't convert %s to a string\n" , +ir_type_string (ir->ir_type)); + } + +return ir_new; +} + + +/* +* FIXME: This should be named ir_is_constant_number() +*/ +int +ir_is_constant (struct ir *ir) +{ +return ir && + (ir->ir_type ==IR_LITERAL + || ir->ir_type ==IR_LIT_BYTE + || ir->ir_type ==IR_LIT_CELL + || ir->ir_type ==IR_LIT_ADDR ); +} + + +int +ir_is_string (struct ir *ir) +{ +return ir && ir->ir_type ==IR_LIT_STR ; +} + + +char * +ir_eval_for_label (struct ir *ir) +{ +char *str; + +if (ir ==NULL ) +return NULL ; + +if (ir->ir_type ==IR_LABEL + || ir->ir_type ==IR_REF_PATH + || ir->ir_type ==IR_REF_PHANDLE ) { + str =strdup (ir->ir_label_name); + }else if (ir->ir_type ==IR_LIT_STR ) { + str =strdup (ir->ir_lit_str); + }else { + str =NULL ; + } + +return str; +} + + +char * +ir_eval_for_name (struct ir *ir) +{ +struct ir *ir_val; +char *str; + +if (ir ==NULL ) +return NULL ; + + ir_val = ir; + +if (ir_val ==NULL ) { +ir_error (ir,"Expected a name\n" ); +return NULL ; + } + +if (ir_val->ir_type !=IR_PROPNODENAME + && ir_val->ir_type !=IR_ID + && ir_val->ir_type !=IR_LIT_STR ) +return NULL ; + + str =strdup (ir->ir_lit_str); + +return str; +} + + +/* +* FIXME: This is misnamed. Should be more like ir_eval_for_const() +*/ +uint64_t +ir_eval_for_addr (struct ir *ir) +{ +unsigned long long a =0 ; + +struct ir *ir_val; + + ir_val =ir_eval (ir); +if (ir_val ==NULL ) { +ir_error (ir,"Expected a const expression\n" ); +return 0 ; + } + +/* +* FIXME: UH, ir_is_constant() check or something? +*/ + + a = ir_val->ir_literal; +ir_free (ir_val); +debug ("eval_for_addr() is 0x%08llx\n" , a); + +return a; +} + + +char * +ir_eval_for_c_string (struct ir *ir) +{ +struct data dtmp; +char *p; + +if (ir ==NULL ) +return NULL ; + + +if (!ir_is_string (ir)) +return NULL ; + + p = ir->ir_lit_str; + dtmp =data_copy_escape_string (p,strlen (p)); + +return strdup (dtmp.val); +} + + +void +ir_eval_for_data (struct ir *ir,struct data *d) +{ +struct ir *ir_val; +struct ir *iri; +struct data dtmp; +char *lab; +cell_t c; +unsigned long long ulit64; + +if (ir ==NULL ) +return ; + + ir_val =ir_eval (ir); + +switch (ir_val->ir_type) { +case IR_LIST : +for (iri = ir_val->ir_first; iri !=NULL ; iri = iri->ir_next) { +ir_eval_for_data (iri, d); + } +break ; + +case IR_LIT_STR : + dtmp =data_copy_escape_string (ir_val->ir_lit_str, +strlen (ir_val->ir_lit_str)); + *d =data_merge (*d, dtmp); +break ; + +case IR_LIT_BYTE : + *d =data_append_byte (*d, ir_val->ir_literal); +break ; + +case IR_LIT_ADDR : + ulit64 = ir_val->ir_literal; + *d =data_append_addr (*d, ulit64); +break ; + +case IR_LIT_CELL : + c = (cell_t ) ir_val->ir_literal; + *d =data_append_cell (*d, c); +break ; + +case IR_CELL : +ir_eval_for_data (ir_val->ir_expr1, d); +break ; + +case IR_LABEL : + lab =ir_eval_for_label (ir); + *d =data_add_marker (*d,LABEL , lab); +break ; + +case IR_REF_PATH : + lab =ir_eval_for_label (ir); + *d =data_add_marker (*d,REF_PATH , lab); +break ; + +case IR_REF_PHANDLE : + lab =ir_eval_for_label (ir); + *d =data_add_marker (*d,REF_PHANDLE , lab); + *d =data_append_cell (*d,-1 ); +break ; + +case IR_INCBIN : { +struct search_path path = { srcpos_file->dir,NULL ,NULL }; +struct data dinc = empty_data; +char *file_name; +struct dtc_file *file; +unsigned long long start; +unsigned long long len; +struct ir *ir_pos; + +/* +* expr1 is file_name +* expr2 is start, NULL implies start of file +* expr3 is length, NULL implies whole file +*/ + file_name =ir_eval_for_c_string (ir_val->ir_expr1); + file =dtc_open_file (file_name, &path); + + ir_pos = ir_val->ir_expr2; + start =ir_eval_for_addr (ir_val->ir_expr2); +if (ir_val->ir_expr3) + len =ir_eval_for_addr (ir_val->ir_expr3); +else + len =-1 ; + +if (start !=0 ) { +if (fseek (file->file, start,SEEK_SET ) !=0 ) { +ir_error (ir_pos, +"Couldn't seek to offset %llu in \"%s\": %s" , + (unsigned long long )start, + file_name, +strerror (errno)); + } + } + + dinc =data_copy_file (file->file, len); + *d =data_merge (*d, dinc); +dtc_close_file (file); +break ; + } + +default : +ir_error (ir, +"Can't convert IR type %s to data\n" , +ir_type_string (ir_val->ir_type)); +break ; + } +} + + +struct ir_scope * +ir_eval_func_body (struct ir *ir_func) +{ +char *func_name; +struct ir *ir_func_def; +struct ir *ir_parameters; +struct ir *ir_statements; +struct ir_symbol *irsym; +struct ir *ir_p; +struct ir *ir_f; +char *param_name; +struct ir_scope *irs_scope; +struct ir *ir_next; +struct ir *ir_pos; + +if (ir_func ==NULL ) +return NULL ; + +if (ir_func->ir_type !=IR_FUNC_CALL ) +return NULL ; + +/* +* Lookup the function definition. +*/ + ir_pos = ir_func->ir_expr1; + func_name =ir_eval_for_name (ir_func->ir_expr1); +debug ("ir_eval_func_body(): Looking up %s\n" , func_name); + + irsym =irs_lookup (func_name,IRS_ANY ); +if (irsym ==NULL || irsym->irsym_type !=IRSYM_FUNCDEF ) { +ir_error (ir_pos, +"%s isn't a function definition\n" , + func_name); +return NULL ; + } + + ir_func_def = irsym->irsym_value; + ir_statements = ir_func_def->ir_statements; + ir_parameters = ir_func_def->ir_declarations; + +debug ("ir_eval_func_body(): Found definition for %s\n" , + irsym->irsym_name); + +/* +* Set up parameter binding via eval-and-copy-in. +* +* First pass evaluates each parameter expression and +* builds a temporary list of each eval() parameter. +* These evaluations need to be done before the function +* scope is opened. +* +* Remember to dodge a possible parent IR_LIST node. +*/ +debug ("ir_eval_func_body(): Evaluating parameters\n" ); + ir_p =ir_eval (ir_func->ir_expr2); +if (ir_p !=NULL && ir_p->ir_type ==IR_LIST ) { + ir_p = ir_p->ir_first; + } + +/* +* Open an evaluation scope and symbol table for +* the function. +*/ +irs_push_scope (IRS_FUNC_CALL ); + +/* +* Second pass loops over each formal parameter +* and each actual expression simultaneously. +* +* Again remember to dodge a possible parent IR_LIST node. +*/ + ir_f = ir_parameters; +if (ir_f !=NULL && ir_f->ir_type ==IR_LIST ) { + ir_f = ir_f->ir_first; + } + +debug ("ir_eval_func_body(): Binding parameter to formals\n" ); + + ir_pos = ir_p; +while (ir_f !=NULL && ir_p !=NULL ) { + param_name = ir_f->ir_lit_str; + +debug ("ir_eval_func_body(): Binding parameter %s\n" , + param_name); + + irsym =irs_create_local (param_name,IRSYM_VAR ); + + irsym->irsym_value = ir_p; + ir_next = ir_p->ir_next; + ir_p->ir_next = ir_p->ir_prev =NULL ; + + ir_f = ir_f->ir_next; + ir_p = ir_next; + ir_pos = ir_p; + } + +if (ir_f !=NULL && ir_p ==NULL ) { +ir_error (ir_pos, +"Not enough parameters to %s (%s)\n" , + func_name, +srcpos_string (ir_func_def->ir_srcpos)); + } + +if (ir_f ==NULL && ir_p !=NULL ) { +ir_error (ir_pos, +"Too many parameters to %s (%s)\n" , + func_name, +srcpos_string (ir_func_def->ir_srcpos)); + } + +/* +* And "invoke" it. +*/ +ir_emit_statement_list (ir_statements); + +/* +* FIXME: Do parameter copy-out here? +*/ + irs_scope =irs_pop_scope (); + +/* +* FIXME: This is a bit dodgy perhaps. +*/ +return irs_scope; +} + + +struct ir * +ir_eval_func_call (struct ir *ir_func) +{ +struct ir_scope *irs_scope; + +/* +* Perform function body. +* Returned scope has "side effects". +* +* This context really just wants the return value, +* but we could debate using nodes and properties too? +*/ + irs_scope =ir_eval_func_body (ir_func); + +if (!irs_scope) +return NULL ; + +return irs_scope->irs_expr; +} + + +struct ir * +ir_eval (struct ir *ir) +{ +struct ir *ir_new; +struct ir *iri; +struct ir *ir1; +struct ir *ir2; +struct ir_symbol *irsym; +unsigned long long lit1; +unsigned long long lit2; +char *str; +int len; + +if (ir ==NULL ) +return NULL ; + + ir_new =NULL ; + +/* +* Perform IR node-specific evaluations. +*/ +switch (ir->ir_type) { +case IR_LIT_STR : +case IR_LIT_BYTE : +case IR_LIT_CELL : +case IR_LIT_ADDR : +case IR_PROPNODENAME : +case IR_REF_PATH : +/* +* Values already present in the IR node. +*/ + ir_new =ir_copy (ir); +break ; + +case IR_REF_PHANDLE : +/* +* Promote a REF_PHANDLE of a LIT_STR to a +* direct REF_PHANDLE. +*/ + ir_new =ir_copy (ir); +if (ir->ir_label) { + iri =ir_eval (ir->ir_label); +if (ir_is_string (iri)) { + ir_new->ir_label_name = iri->ir_lit_str; + } + } +break ; + +case IR_LABEL : + ir_new =ir_copy (ir); +break ; + +case IR_CVT_PROPNODENAME : + iri =ir_eval (ir->ir_expr1); + str =ir_eval_for_name (iri); +if (str) { + ir_new =ir_alloc (IR_PROPNODENAME , ir->ir_srcpos); + ir_new->ir_lit_str = str; + } +break ; + +case IR_CVT_STRING : + iri =ir_eval (ir->ir_expr1); + ir_new =ir_eval_cvt_to_string (iri); +break ; + +case IR_ID : + irsym =irs_lookup (ir->ir_lit_str,IRS_ANY ); +if (irsym !=NULL ) { + ir_new =ir_eval (irsym->irsym_value); + }else { +ir_error (ir, +"Unknown value for \"%s\"\n" , + ir->ir_lit_str); + } +break ; + +case IR_LIST : + ir_new =ir_alloc (IR_LIST , ir->ir_srcpos); +for (iri = ir->ir_first; iri !=NULL ; iri = iri->ir_next) { +ir_list_append (ir_new,ir_eval (iri)); + } +break ; + +case IR_SELECT : +/* +* Pick the ? or the : side. +*/ + lit1 =ir_eval_for_addr (ir->ir_expr1); +if (lit1) { + ir_new =ir_eval (ir->ir_expr2); + }else { + ir_new =ir_eval (ir->ir_expr3); + } +break ; + +case IR_OR : + lit1 =ir_eval_for_addr (ir->ir_expr1); +if (!lit1) { + lit1 =ir_eval_for_addr (ir->ir_expr2); + } + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = (lit1 !=0 ); +break ; + +case IR_AND : + lit1 =ir_eval_for_addr (ir->ir_expr1); +if (lit1) { + lit1 =ir_eval_for_addr (ir->ir_expr2); + } + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = (lit1 !=0 ); + +break ; + +case IR_BIT_OR : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 | lit2; +break ; + +case IR_BIT_XOR : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 ^ lit2; +break ; + +case IR_BIT_AND : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 & lit2; +break ; + +case IR_EQ : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 == lit2; +break ; + +case IR_LT : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 < lit2; +break ; + +case IR_LE : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 <= lit2; +break ; + +case IR_GT : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 > lit2; +break ; + +case IR_GE : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 >= lit2; +break ; + +case IR_NE : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 != lit2; +break ; + +case IR_LSHIFT : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 << lit2; +break ; + +case IR_RSHIFT : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 >> lit2; +break ; + +case IR_ADD : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 + lit2; +break ; + +case IR_MINUS : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 - lit2; +break ; + +case IR_MULT : + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 * lit2; +break ; + +case IR_DIV : +/* FIXME: check for division by const 0 */ + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 / lit2; +break ; + +case IR_MOD : +/* +* This is really a bit upside down due to not having +* a real typing system. Cope for now. +*/ + ir1 =ir_eval (ir->ir_expr1); + ir2 =ir_eval (ir->ir_expr2); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { +/* +* FIXME: check for division by const 0. +*/ + lit1 =ir_eval_for_addr (ir->ir_expr1); + lit2 =ir_eval_for_addr (ir->ir_expr2); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1 % lit2; + + }else if (ir_is_string (ir1) ||ir_is_string (ir2)) { +if (!ir_is_string (ir1)) + ir1 =ir_eval_cvt_to_string (ir1); +if (!ir_is_string (ir2)) + ir2 =ir_eval_cvt_to_string (ir2); + len =strlen (ir1->ir_lit_str) + +strlen (ir2->ir_lit_str) +1 ; + str =xmalloc (len); +strcpy (str, ir1->ir_lit_str); +strcat (str, ir2->ir_lit_str); + str[len -1 ] =0 ; + ir_new =ir_alloc (IR_LIT_STR , ir->ir_srcpos); + ir_new->ir_lit_str = str; + } +break ; + +case IR_BIT_COMPL : + lit1 =ir_eval_for_addr (ir->ir_expr1); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = ~lit1; +break ; + +case IR_NOT : + lit1 =ir_eval_for_addr (ir->ir_expr1); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = !lit1; +break ; + +case IR_UMINUS : + lit1 =ir_eval_for_addr (ir->ir_expr1); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = -lit1; +break ; + +case IR_FUNC_CALL : + ir_new =ir_eval_func_call (ir); +break ; + +case IR_BUILTIN : + ir_new =ir_eval_builtin (ir); +break ; + +case IR_RANGE : + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_eval (ir->ir_expr1); + ir_new->ir_expr2 =ir_eval (ir->ir_expr2); +break ; + +case IR_CELL : + ir_new =ir_eval (ir->ir_expr1); +if (ir_is_constant (ir_new)) { +/* FIXME: Check for 32-bit range here? */ + ir_new->ir_type =IR_LIT_CELL ; + }else if (ir_is_string (ir_new)) { +/* empty */ + }else { +ir_error (ir,"Can't determine CELL value\n" ); + } +break ; + +case IR_LITERAL : + lit1 =0 ; +if (ir_eval_literal_guessing (ir->ir_lit_str, +0 ,64 , &lit1) ==0 ) { +/* +* Smells like an number. +*/ + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + ir_new->ir_literal = lit1; + }else { +/* +* Dunno what it is. Must be a string. +* FIXME: ir_eval_for_c_string() here? +*/ + ir_new =ir_alloc (IR_LIT_STR , ir->ir_srcpos); + ir_new->ir_lit_str =strdup (ir->ir_lit_str); + } +break ; + +case IR_INCBIN : + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_eval (ir->ir_expr1); + ir_new->ir_expr2 =ir_eval (ir->ir_expr2); + ir_new->ir_expr3 =ir_eval (ir->ir_expr3); +break ; + +case IR_PROP_DEF : +ir_error (ir,"Can't evaluate IR_PROP_DEF here.\n" ); +break ; + +case IR_ROOT : +case IR_RETURN : +case IR_IF : +case IR_FOR : +case IR_ASSIGN : +case IR_MEM_RESERVE : +case IR_FUNC_DEF : +case IR_PARAMDECL : +case IR_NODE : +ir_error (ir, +"Can't evaluate %s statements in expressions\n" , +ir_type_string (ir->ir_type)); +break ; + +default : +ir_error (ir, +"Unknown expression ir_type %s\n" , +ir_type_string (ir->ir_type)); + } + +return ir_new; +} + + +struct ir * +ir_simplify (struct ir *ir,unsigned int ctxt) +{ +struct ir *ir1; +struct ir *ir2; +ir_type ir_type; +struct ir *ir_new; +unsigned long long lit1; +unsigned long long lit2; +unsigned long long ulit64; + +if (ir ==NULL ) +return NULL ; + +/* +* First determine what the evaluation context will be +* for any sub-expression based on the current IR node. +*/ +switch (ir->ir_type) { +case IR_CELL : +/* +* Pass new context down. +*/ + ctxt =IR_EVAL_CTXT_CELL ; +break ; + +case IR_INCBIN : +case IR_IF : +case IR_FOR : +case IR_MEM_RESERVE : +/* +* These are always done in an ANY context. +*/ + ctxt =IR_EVAL_CTXT_ANY ; +break ; + +default : +/* +* Use the supplied (parameter) context. +*/ +break ; + } + + +/* +* Perform IR node-specific optimizations. +*/ +switch (ir->ir_type) { +case IR_ID : +case IR_LIT_STR : +case IR_LIT_BYTE : +case IR_LIT_CELL : +case IR_LIT_ADDR : +case IR_PROPNODENAME : +case IR_LABEL : +case IR_REF_PATH : +/* +* Already as simple as they can be. +*/ + ir_new =ir_copy (ir); +break ; + +case IR_REF_PHANDLE : + ir_new =ir_copy (ir); + ir_new->ir_label =ir_simplify (ir->ir_label, ctxt); +break ; + +case IR_RETURN : + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_simplify (ir->ir_expr1, ctxt); +break ; + +case IR_MEM_RESERVE : +case IR_RANGE : + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_simplify (ir->ir_expr1, ctxt); + ir_new->ir_expr2 =ir_simplify (ir->ir_expr2, ctxt); +break ; + +case IR_CELL : + ir1 =ir_simplify (ir->ir_expr1, ctxt); +if (ir1 && ir1->ir_type ==IR_LIT_CELL ) { + ir_new = ir1; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + } +break ; + +case IR_PROP_DEF : + ir_new =ir_copy (ir); + ir_new->ir_label =ir_simplify (ir->ir_label, ctxt); + ir_new->ir_expr1 =ir_simplify (ir->ir_expr1, ctxt); + ir_new->ir_expr2 =ir_simplify (ir->ir_expr2, ctxt); +break ; + +case IR_LITERAL : +/* +* Based on context, evaluate literal into 32 or 64 bits. +* LIT_ADDR could be a lie; it just means 64-bit. Feh. +*/ +if (ctxt ==IR_EVAL_CTXT_CELL ) { + ulit64 =ir_eval_literal_str (ir->ir_lit_str,0 ,32 ); + ir_new =ir_alloc (IR_LIT_CELL , ir->ir_srcpos); + }else { + ulit64 =ir_eval_literal_str (ir->ir_lit_str,0 ,64 ); + ir_new =ir_alloc (IR_LIT_ADDR , ir->ir_srcpos); + } + ir_new->ir_literal = ulit64; +break ; + +case IR_FUNC_CALL : + { +char *name; +irb_id irb; + + ir_new =ir_copy (ir); + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); + name =ir_eval_for_name (ir1); +if (name) { + irb =ir_lookup_builtin_by_name (name); +if (irb !=IRB_UNDEF ) { +debug ("ir_simplify(): Use builtin %s\n" , + name); + ir_new->ir_type =IR_BUILTIN ; + ir_new->ir_builtin_id = irb; + ir_new->ir_expr1 = ir2; + }else { + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } + }else { +ir_error (ir1,"Unknown function %s\n" , name); + } + } +break ; + +case IR_BUILTIN : + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_simplify (ir->ir_expr1, ctxt); + ir_new->ir_expr2 =ir_simplify (ir->ir_expr2, ctxt); +break ; + +case IR_LIST : + ir_new =ir_alloc (IR_LIST , ir->ir_srcpos); +for (ir1 = ir->ir_first; ir1 !=NULL ; ir1 = ir1->ir_next) { +ir_list_append (ir_new, +ir_simplify (ir1, ctxt)); + } +break ; + +case IR_INCBIN : +/* +* Ponder loading and caching files? +*/ + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_simplify (ir->ir_expr1, ctxt); + ir_new->ir_expr2 =ir_simplify (ir->ir_expr2, ctxt); + ir_new->ir_expr3 =ir_simplify (ir->ir_expr3, ctxt); +break ; + +case IR_ASSIGN : + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_simplify (ir->ir_expr1, ctxt); + ir_new->ir_expr2 =ir_simplify (ir->ir_expr2, ctxt); +break ; + +case IR_IF : + ir1 =ir_simplify (ir->ir_expr1, ctxt); +if (ir_is_constant (ir1)) { +/* +* Eliminate the IR_IF. +* Pick the THEN or ELSE statements only. +* FIXME: Fix leaking ir1 here. +*/ + ulit64 =ir_eval_for_addr (ir1); +if (ulit64) { +/* +* Keep the THEN statements. +*/ + ir_new =ir_simplify (ir->ir_statements, ctxt); + }else { +/* +* Keep the ELSE statements. +*/ + ir_new =ir_simplify (ir->ir_statements2, ctxt); + } + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir1 =ir_simplify (ir->ir_statements, ctxt); + ir_new->ir_statements = ir1; + ir1 =ir_simplify (ir->ir_statements2, ctxt); + ir_new->ir_statements2 = ir1; + } +break ; + +case IR_FOR : +/* +* Lots of optimizations possible here based on +* empty statements and trivial ranges. Later. +* FIXME: Do "for" simplification optimizations. +*/ + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_simplify (ir->ir_expr1, ctxt); + ir_new->ir_expr2 =ir_simplify (ir->ir_expr2, ctxt); + ir_new->ir_expr3 =ir_simplify (ir->ir_expr3, ctxt); + ir_new->ir_statements =ir_simplify (ir->ir_statements, ctxt); +break ; + +case IR_SELECT : + ir1 =ir_simplify (ir->ir_expr1, ctxt); +if (ir_is_constant (ir1)) { +/* +* Pick the ? or the : side. +* FIXME: Fix leaking ir1. +*/ + ulit64 =ir_eval_for_addr (ir1); +if (ulit64) { + ir_new =ir_simplify (ir->ir_expr2, ctxt); + }else { + ir_new =ir_simplify (ir->ir_expr3, ctxt); + } + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_simplify (ir->ir_expr1, ctxt); + ir_new->ir_expr2 =ir_simplify (ir->ir_expr2, ctxt); + ir_new->ir_expr3 =ir_simplify (ir->ir_expr3, ctxt); + } +break ; + +case IR_CVT_PROPNODENAME : +/* +* IR_CVT_PROPNODENAME(IR_PROPNODENAME) == IR_PROPNODENAME, +* so drop the CVT. +*/ + ir1 =ir_simplify (ir->ir_expr1, ctxt); +if (ir1 && ir1->ir_type ==IR_PROPNODENAME ) { + ir_new = ir1; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + } +break ; + +case IR_CVT_STRING : +/* +* IR_CVT_STRING(IR_LIT_STR) == IR_LIT_STR, +* so drop the CVT. +*/ + ir1 =ir_simplify (ir->ir_expr1, ctxt); +if (ir1 && ir1->ir_type ==IR_LIT_STR ) { + ir_new = ir1; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + } +break ; + +case IR_OR : + ir1 =ir_simplify (ir->ir_expr1, ctxt); +if (ir_is_constant (ir1)) { + ulit64 =ir_eval_for_addr (ir1); +if (ulit64) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal =1 ; +break ; + } + } + + ir2 =ir_simplify (ir->ir_expr2, ctxt); + +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new->ir_literal = lit1 || lit2; + + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_simplify (ir1, ctxt); + ir_new->ir_expr2 =ir_simplify (ir2, ctxt); + } +break ; + +case IR_AND : + ir1 =ir_simplify (ir->ir_expr1, ctxt); +if (ir_is_constant (ir1)) { + ulit64 =ir_eval_for_addr (ir1); +if (ulit64 ==0 ) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal =0 ; +break ; + } + } + + ir2 =ir_simplify (ir->ir_expr2, ctxt); + +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new->ir_literal = lit1 && lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_BIT_OR : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 | lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_BIT_XOR : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 ^ lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_BIT_AND : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 & lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_EQ : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 == lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_LT : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 < lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_LE : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 <= lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_GT : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 > lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_GE : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 >= lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_NE : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 != lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_LSHIFT : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 << lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_RSHIFT : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 >> lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_ADD : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 + lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_MINUS : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 - lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_MULT : + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 * lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_DIV : +/* FIXME: check for division by const 0 */ + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 / lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_MOD : +/* FIXME: check for division by const 0 */ + ir1 =ir_simplify (ir->ir_expr1, ctxt); + ir2 =ir_simplify (ir->ir_expr2, ctxt); +if (ir_is_constant (ir1) &&ir_is_constant (ir2)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + lit2 =ir_eval_for_addr (ir2); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = lit1 % lit2; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + ir_new->ir_expr2 = ir2; + } +break ; + +case IR_BIT_COMPL : + ir1 =ir_simplify (ir->ir_expr1, ctxt); +if (ir_is_constant (ir1)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = ~lit1; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + } +break ; + +case IR_NOT : + ir1 =ir_simplify (ir->ir_expr1, ctxt); +if (ir_is_constant (ir1)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = !lit1; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + } +break ; + +case IR_UMINUS : + ir1 =ir_simplify (ir->ir_expr1, ctxt); +if (ir_is_constant (ir1)) { + ir_type = (ctxt ==IR_EVAL_CTXT_CELL ) + ?IR_LIT_CELL :IR_LIT_ADDR ; + lit1 =ir_eval_for_addr (ir1); + ir_new =ir_alloc (ir_type, ir->ir_srcpos); + ir_new->ir_literal = -lit1; + }else { + ir_new =ir_copy (ir); + ir_new->ir_expr1 = ir1; + } +break ; + +case IR_ROOT : + ir_new =ir_copy (ir); + ir_new->ir_mem_reserves = +ir_simplify (ir->ir_mem_reserves, ctxt); + ir_new->ir_declarations = +ir_simplify (ir->ir_declarations, ctxt); + ir_new->ir_statements = +ir_simplify (ir->ir_statements, ctxt); +break ; + +case IR_NODE : + ir_new =ir_copy (ir); + ir_new->ir_label =ir_simplify (ir->ir_label, ctxt); + ir_new->ir_name =ir_simplify (ir->ir_name, ctxt); + ir_new->ir_statements = +ir_simplify (ir->ir_statements, ctxt); +break ; + +case IR_CONST_DEF : + ir_new =ir_copy (ir); + ir_new->ir_expr1 =ir_simplify (ir->ir_expr1, ctxt); + ir_new->ir_expr2 =ir_simplify (ir->ir_expr2, ctxt); +break ; + +case IR_FUNC_DEF : + ir_new =ir_copy (ir); + ir_new->ir_name =ir_simplify (ir->ir_name, ctxt); + ir_new->ir_declarations = +ir_simplify (ir->ir_declarations, ctxt); + ir_new->ir_statements = +ir_simplify (ir->ir_statements, ctxt); +break ; + +case IR_PARAMDECL : +default : + ir_new =NULL ; +ir_error (ir, +"Can't simplify unknown ir_type %s\n" , +ir_type_string (ir->ir_type)); + } + +return ir_new; +}
Signature · 1 line
1.6.0.90.g436ed
A message that is not in the archive (sent off-list or not yet received): 1222460748-20127-7-git-send-email-jdl-CYoMK+44s/[email protected]
PATCH v3 7/9 Introduce new DTS language.
Introduce function defs and statements.
Added support for expressions.
Added if, for, assign and return statements.
Added support for BUILTIN functions.
Added support for /const/ definitions.
Added support for command line defines, eg: -D x=1 Unified /memreserve/ into declaration list.
Add lexical support for column source position information.
Notably, this involved identifying all the newline characters to reset the column count. Had to rewrite the C comment rules, and break \n out of the {WS} set.
Prevent lone +, -, and ? chars from being property names. Add lexical source positions to all IR nodes. Change error reporting to use IR source positions.
Passes test suite.
--- Makefile | 2 +- Makefile.dtc | 18 ++- dtc-lexer.l | 271 ++++++++++++++++++---- dtc-parser.y | 711 ++++++++++++++++++++++++++++++++++++++++++++++------------ dtc.c | 7 +- dtc.h | 1 + ir.h | 1 - ir_dump.c | 9 - ir_emit.c | 67 +++--- ir_eval.c | 2 - ir_scope.c | 3 +- livetree.c | 16 ++ nv.c | 108 +++++++++ nv.h | 34 +++ srcpos.c | 75 +++++-- srcpos.h | 10 +- treesource.c | 3 + 17 files changed, 1068 insertions(+), 270 deletions(-) create mode 100644 nv.c create mode 100644 nv.h
Makefile +1 -1
@@ -18,7 +18,7 @@ CONFIG_LOCALVERSION = CPPFLAGS = -I libfdt CFLAGS = -Wall -g -Os -Wpointer-arith -Wcast-qual -BISON = bison +BISON = bison -v LEX = flex INSTALL = /usr/bin/install
Makefile.dtc +16 -2
@@ -3,7 +3,21 @@ # This is not a complete Makefile of itself. Instead, it is designed to # be easily embeddable into other systems of Makefiles. # -DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \ - checks.c +DTC_SRCS = \ + checks.c \ + data.c \ + dtc.c \ + flattree.c \ + fstree.c \ + ir.c \ + ir_builtin.c \ + ir_dump.c \ + ir_emit.c \ + ir_eval.c \ + ir_scope.c \ + livetree.c \ + nv.c \ + srcpos.c \ + treesource.c DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
dtc-lexer.l +224 -47
394 lines not on this page · raw message
dtc-parser.y +562 -149
871 lines not on this page · raw message
dtc.c +5 -2
@@ -20,6 +20,7 @@#include "dtc.h" #include "srcpos.h" +#include "nv.h" #include "version_gen.h"
@@ -127,7 +128,7 @@ int main(int argc, char *argv[]) minsize =0 ; padsize =0 ; -while ((opt =getopt (argc, argv,"hI:O:o:V:R:S:p:fcqb:v" )) !=EOF ) { +while ((opt =getopt (argc, argv,"hD:I:O:o:V:R:S:p:fcqb:v" )) !=EOF ) {switch (opt) {case 'I' : inform = optarg;
@@ -162,6 +163,9 @@ int main(int argc, char *argv[])case 'b' : cmdline_boot_cpuid =strtoll (optarg,NULL ,0 );break ; +case 'D' : +nv_note_define (optarg); +break ;case 'v' :printf ("Version: %s\n" ,DTC_VERSION );exit (0 );
@@ -203,7 +207,6 @@ int main(int argc, char *argv[])fill_fullpaths (bi->dt,"" );process_checks (force, bi); -if (streq (outname,"-" )) { outf = stdout; }else {
dtc.h +1 -0
@@ -187,6 +187,7 @@ struct property *reverse_properties(struct property *first);struct node *build_node (struct property *proplist,struct node *children);struct node *name_node (struct node *node,char *name,char *label);struct node *chain_node (struct node *first,struct node *list); +struct node *reverse_nodes (struct node *first);void add_property (struct node *node,struct property *prop);void add_child (struct node *parent,struct node *child);
ir.h +0 -1
@@ -100,7 +100,6 @@ struct ir {struct ir *ir_expr2;struct ir *ir_expr3; -struct ir *ir_mem_reserves;struct ir *ir_statements;struct ir *ir_statements2;struct ir *ir_declarations;
ir_dump.c +0 -9
@@ -152,15 +152,6 @@ ir_dump_node(struct ir *ir, unsigned int level) indent, "", ir->ir_prev);/* -* Dump mem-reserves. -*/ -if (ir->ir_mem_reserves) { -printf ("%*sir_mem_reserves: %p\n" , - indent,"" , ir->ir_mem_reserves); -ir_dump_node (ir->ir_mem_reserves, level +1 ); - } - -/* * Dump sub-expressions */ if (ir->ir_expr1) {
ir_emit.c +33 -34
93 lines not on this page · raw message
ir_eval.c +0 -2
@@ -1461,8 +1461,6 @@ ir_simplify(struct ir *ir, unsigned int ctxt)case IR_ROOT : ir_new =ir_copy (ir); - ir_new->ir_mem_reserves = -ir_simplify (ir->ir_mem_reserves, ctxt); ir_new->ir_declarations =ir_simplify (ir->ir_declarations, ctxt); ir_new->ir_statements =
ir_scope.c +1 -2
@@ -97,8 +97,7 @@ irs_append_reserve(struct reserve_info *ri)struct ir_scope *irs; irs =irs_find_scope (IRS_ROOT ); - irs->irs_reserve_list =chain_reserve_entry (ri, - irs->irs_reserve_list); + irs->irs_reserve_list =add_reserve_entry (irs->irs_reserve_list, ri); }
livetree.c +16 -0
@@ -97,6 +97,22 @@ struct node *chain_node(struct node *first, struct node *list)return first; } +struct node *reverse_nodes (struct node *first) +{ +struct node *p = first; +struct node *head =NULL ; +struct node *next; + +while (p) { + next = p->next_sibling; + p->next_sibling = head; + head = p; + p = next; + } +return head; +} + +void add_property (struct node *node,struct property *prop) {struct property **p;
nv.c new file +108 -0
108 lines not on this page · raw message
nv.h new file +34 -0
@@ -0,0 +1,34 @@ +/* +* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of the +* License, or (at your option) any later version. +* +* This program 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 +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +* USA +*/ + +#ifndef _NV_H_ +#define _NV_H_ + + +struct nv_pair { +char *nv_name; +char *nv_value; +struct nv_pair *nv_next; +}; + +extern struct nv_pair *nv_list; + +extern void nv_note_define (char *defstr); + +#endif /* _NV_H_ */
srcpos.c +59 -16
111 lines not on this page · raw message
srcpos.h +5 -5
@@ -81,11 +81,6 @@ typedef YYLTYPE srcpos;*/ extern srcpos srcpos_empty; - - -extern void yyerror (char const *); -extern void yyerrorf (char const *, ...) __attribute__((format (printf,1 ,2 ))); -extern struct dtc_file *srcpos_file;struct search_path {
@@ -101,4 +96,9 @@ extern srcpos *srcpos_copy(srcpos *pos);extern char *srcpos_string (srcpos *pos);extern void srcpos_dump (srcpos *pos); +extern void srcpos_error (srcpos *pos,char const *, ...) + __attribute__((format (printf,2 ,3 ))); +extern void srcpos_warn (srcpos *pos,char const *, ...) + __attribute__((format (printf,2 ,3 ))); +#endif /* _SRCPOS_H_ */
treesource.c +3 -0
@@ -20,6 +20,7 @@#include "dtc.h" #include "srcpos.h" +#include "ir.h" extern FILE *yyin;extern int yyparse (void );
@@ -41,6 +42,8 @@ struct boot_info *dt_from_source(const char *fname)if (treesource_error)die ("Syntax error parsing input tree\n" ); +ir_process (); +return the_boot_info; }
Signature · 1 line
1.6.0.90.g436ed
A message that is not in the archive (sent off-list or not yet received): 1222460748-20127-8-git-send-email-jdl-CYoMK+44s/[email protected]
PATCH v3 8/9 Add documentation for the new DTS language.
From: Jon Loeliger <[email protected]>
--- Documentation/manual.txt | 500 ++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 463 insertions(+), 37 deletions(-)
Documentation/manual.txt +463 -37
@@ -105,13 +105,21 @@ Options: -q Quiet: -q suppress warnings, -qq errors, -qqq all + -D <id> + -D <id>=<value> + Introduce a constant definition for symbol <id> with + possible initial value given by <value>. The RHS + should be a literal number or string value. + + -p <padsize> + Add at least <padsize> additional space to the DTB image. + -R <number> Make space for <number> reserve map entries Relevant for dtb and asm output only. -S <bytes> - Ensure the blob at least <bytes> long, adding additional - space if needed. + Deprecated option. -v Print DTC version and exit.
@@ -131,47 +139,338 @@ Additionally, dtc performs various sanity checks on the tree. 4) Device Tree Source file -4.1) Overview -Here is a very rough overview of the layout of a DTS source file: +4.1) DTS Lexical Components + +Property and node names [a-zA-Z0-9,._+*#?@-]+ +Identifiers \\[a-zA-Z_][a-zA-Z0-9_]* +Labels [a-zA-Z_][a-zA-Z0-9_]* +Strings <C-style-double-quoted-strings> +Comments Both /* ... */ and // style are supported +Numeric literals <C-style-integer-numbers> +Bytes [0-9a-fA-F][0-9a-fA-F] + +Keywords: + else + for + if + in + return + void + /const/ + /define/ + /incbin/ + +C-style expression operators: + << + >> + <= + >= + == + != + && + || + + + - + * + / + % + +Additional tokens: + .. + := + { + } + , + & + + +These constructs are handled and eliminated purely at the +lexical level and do not appear in the grammar proper: + + - Source files included using the syntax: + + /include/ "filename" + + - Both classic C style and C++ style comments are supported. + Comments don't nest. + For example, given: + + 1 /* + 2 * asdasdasd // asdasdad + 3 // */ + 4 asasd + 5 */ + The // comment on line 3 is not effective and is ignored. + The original /* comment ends on line 3. Line 5 is in error. + + And given: + + 1 // /* + 2 * asdasdasd // asdasdad + 3 */ + + The // comment on line 1 hides the opening /*. + Line 2 is in error. + + +4.2) DTS Grammar + +Here is a very rough overview of the grammar of a DTS source file: + + + sourcefile: + '/dts-v1/' ';' possibly_empty_list_of_declarations devicetree + + declaration: + memreserve + | constdef + | funcdef + + memreserve: label '/memreserve/' addr addr ';' + + constdef: '/const/' identifier '=' expr ';' + + funcdef: '/define/' propnodename paramdecls statement_block + + paramdecls: '(' possibly_empty_paramdecl_list ')' + + paramdecl: identifier + + devicetree: '/' statement_block + + statement_block: '{' possibly_empty_list_of_statements '}' + + statement: + subnode + | for_statement + | if_statement + | return_statement + | assign_statement + | property_definition + | statement_block + | ';' + + subnode: + node_label expr statement_block ';' + | label expr statement_block ';' + | expr statement_block ';' + + for_statement: + 'for' identifier 'in' expr '..' expr statement_block + + if_statement: + 'if' '(' expr ')' statement_block + | 'if' '(' expr ')' statement_block 'else' statement_block + + return_statement: 'return' expr ';' + + assign_statement: identifier ':=' expr ';' + + property_definition: + optional_label expr ';' + | optional_label expr '=' list_of_property_data_and_labels ';' + list_of_property_data_and_labels: + STRING + | '<' possibly_empty_list_of_cell_values_and_labels '>' + | '[' possibly_empty_list_of_byte_values_and_labels ']' + | label + | '/incbin/' '(' expr ')' + | '/incbin/' '(' expr ',' expr ',' expr ')' - sourcefile: list_of_memreserve devicetree + cell_value: + expr_primary + | '&' '(' expr ')' + | '&' phandle_reference + | label - memreserve: label 'memreserve' ADDR ADDR ';' - | label 'memreserve' ADDR '-' ADDR ';' - devicetree: '/' nodedef + expr: + expr_primary + | expr '?' expr ':' expr + | expr expr_oper expr - nodedef: '{' list_of_property list_of_subnode '}' ';' + expr_oper: + || + && + | + ^ + & + == + < | > | <= | >= + << | >> + + | - + * | / | % + - | ~ | ! + '(' ')' | '(' non_empty_list_of_param_exprs ')' - property: label PROPNAME '=' propdata ';' + expr_primary: + literal + | string + | propnodename + | identifier + | '(' expr ')' - propdata: STRING - | '<' list_of_cells '>' - | '[' list_of_bytes ']' + addr: expr - subnode: label nodename nodedef + node_label: expr ':' -That structure forms a hierarchical layout of nodes and properties -rooted at an initial node as: + propnodename: <1275-property-name> + + identifier: '\'-<C style name> + + literal: <C style number> + byte: <exactly two hex digits> + string: <C style string> + label: '&'-<label name>-':' + + +4.2) Overview + +The DTS source file begins with the '/dts-v1/' token to state +that it is using "Version 1" style source files. + +Any declarations are executed in order, and can use the +effects of earlier declarations. + +All declarations must precede the required root node definition, +which is introduced with the '/'-named node: / { + ... } -Both classic C style and C++ style comments are supported. +The statement-block structure forms a hierarchical layout of nodes +and properties along with some control-statements that allow for +repeated and alternate statement blocks. + + +4.3) Declarations + +An arbitrary list of declarations can be made between '/dts-v1/' +and the beginning of the root node. These declarations are +introduced in order. + + +4.3.1) Memory Reservations + +A memory reservation is a declaration that a block of memory +from the first address expression, with a size given by the +second address expression, is to be "reserved" and not used +by the kernel. These address ranges are passed through to +the DTB to the kernel. + + +4.3.2) Function Definitions + +A function definition can be introduced using /define/. +These definitions are just "stored" and then later invoked as +either a subroutine in a statement context, or as a function +with a return value in an expression context. -Source files may be directly included using the syntax: +Functions declare the number of formal parameters which will +be passed in at the call site, and must match one-to-one. - /include/ "filename" +Any property definitions generated by the function are emitted +into the caller's context at the point of the call. +Any node definitions generated by the function are emitted +into the caller's context at the point of the call. -4.2) Properties -Properties are named, possibly labeled, values. Each value -is one of: +4.3.3) Constant Definitions - - A null-teminated C-like string, +Constant definitions introduce a named identifier into the outer-most +symbol scope. The constants can not be changed by later assignment +statements, though they can be hidden. (Be careful.) + +Constants may be expressions yielding constant numeric or strings +values. It is an error for them not to be evaluatable at their +point of definition. + +Constant definitions may also be introduced from the command line +using the '-D var=value" options. They will be placed into the +same outer-most scope. Constant definitions from the command line +override the definitions within the source file, but with a warning. + + +4.4) Statements + +A statement block is simply a list of sequentially executed +statements introduced with a required opening brace and terminated +with a required closing brace. + +4.4.1) Subnodes + +Node may contain sub-nodes to obtain a hierarchical structure. + +For example: + + - A child node named "childnode" whose unit name is + "childnode at address". It it turn has a string property + called "childprop". + + childnode@address { + childprop = "hello\n"; + }; + + +4.4.2) 'for' Statement + +The 'for' statement provides iterative execution of a +block of statements. + +The lower bound of the range is evaluated once, and the +upper bound is evaluated once. + +A new scope that contains the loop variable is created +and pushed onto the symbol table scope stack. The loop +variable is initialized with the lower bound value. + +The statement block is executed once for each inclusive value +in the given range in increasing order. + +After the loop terminates, the loop variable scope is popped. + + +4.4.3) 'if' Statement + +The 'if' statement provides alternate execution flow paths. +The expression is evaluated once, and if non-zero, the fist +statement block is executed, otherwise the 'else' block of +statements is executed if present. + + +4.4.4) 'return' Statement + +Inside a function definition, the 'return' statement allows +a value to be passed back to the caller. The return expression +is evaluated once, in the context of the function's scope, +and its resultant value is made available as the function's +return result. + + +4.4.5) Assign Statement + +The ':=' operator allows assignment to non-constant identifiers. + +The identifiers can be either formal parameters or variable as +found by the searching using the dynamic symbol table scoping rules. + +An assignment to an otherwise unknown identifier causes that +identifier to be introduced into the current scope. + +You can't assign to /constant/ identifiers (except in the initial +definition of them). + + +4.4.6) Property Definition + +Properties are named, possibly labeled, values. +Each value within a property is one of: + + - A null-terminated C-like string, - A numeric value fitting in 32 bits, - A list of 32-bit values - A byte sequence
@@ -195,27 +494,126 @@ Here are some example property definitions: property4 = [0a 0b 0c 0d de ea ad be ef]; -Node may contain sub-nodes to obtain a hierarchical structure. -For example: +4.4.7) Subroutine calls - - A child node named "childnode" whose unit name is - "childnode at address". It it turn has a string property - called "childprop". +An expression at the statement level should be a function call, +though it might be considered as just a "subroutine call" as +any return value is thrown away. - childnode@addresss { - childprop = "hello\n"; - }; +Invocation of the function introduces a symbol table scope +in which the formal paramters are introduced and bound. +Initial values for the formals are obtained by evaluating +the actual parameters, in order, and using a copy-in binding. + +Any incidental (dynamically occurring) assignment to an +otherwise unknown identifier will cause the introduction of +a new variable in the function's execution scope. + +Any property definitions generated by the function are emitted +into the caller's context at the point of the subroutine call. + +Any node definitions generated by the function are emitted +into the caller's context at the point of the subroutine call. + +Any return value from a return statement is thrown away. +Execution control is returned to the point of the call. -By default, all numeric values are hexadecimal. Alternate bases -may be specified using a prefix "d#" for decimal, "b#" for binary, -and "o#" for octal. -Strings support common escape sequences from C: "\n", "\t", "\r", -"\(octal value)", "\x(hex value)". +4.5) Expressions +Basically, expressions follow C conventions. However, there +are no assignment operations such as +=, or pre-/post- +increment/decrement. -4.3) Labels and References +The '%' operation is a modulus operation for integers, and +a string concatenation operation if at least one of the operands +is determined to be a string value. + + +4.5.1) Expressions + +Pretend it is C and see how close we get. + + +4.5.2) Function Invocations + +A previously defined function may be invoked from within an +expression. A "return" statement should be used to return +a resulting expression value to the caller's context. + +Invocation of the function introduces a symbol table scope +in which the formal parameters are introduced and bound. +Initial values for the formals are obtained by evaluating +the actual parameters, in order, and using a copy-in binding. + +Any incidental (dynamically occurring) assignment to an +otherwise unknown identifier will cause the introduciton of +a new variable in the function's execution scope. + +Any property definitions generated by the function are emitted +into the caller's context at the point of the subroutine call. + +Any node definitions generated by the function are emitted +into the caller's context at the point of the subroutine call. + +Any return value from a return statement is used as the result +of the function call within the context of the original expression. + +Execution control is returned to the point of the call. + + +4.5.3) Builtin Functions + +There are a few builtin function names; + + join() Concatenate and return a list of expression + as a string. Non-string arguments are coerced + into being a string. + + hexstr() Format and return a hex string representation + of the one parameter without a leading '0x'. + +While not here yet, /incbin/ should be converted into a builtin. + + +4.5.4) Literal Numbers + +Literal numbers follow C conventions. Specifically, they are +base-ten by default, but can be hexadecimal, binary or octal +with a leading 0x or 0X, 0b or OB, or a simple leading zero, +respectively. + +There is no support for floating point representations at all. + +Most math and expression handling is assumed to be 64-bit, but +a cell-context may force a 32-bit container instead. + + +4.5.5) Literal Strings + +Strings support common escape sequences from C: + "\n", "\t", "\r" + "\(octal value)" + "\x(hex value)" + + +4.5.6) Identifiers + +Identifiers references are resolved using dynamic symbol table +scoping rules. An identifier referenced on the right-hand-side +of an expression must be resolvable or else it is an error. + +An identifier occurring on the left-hand-side of a ':=' assignment +is first sought and used if found. If it is not found, it is +introduced dynamically in the innermost, current scope. + +Sometimes identifiers can be used without the leading slash, +other times they are required, especially if to disambiguate +from property names. It's not ideal yet at all. + + +4.6) Labels and References Labels may be applied to nodes or properties. Labels appear before a node name, and are referenced using an ampersand: &label.
@@ -239,6 +637,34 @@ And used in properties, lables may appear before or after any value: ... }; +The names of some labels can be constructed in an expression +context using the representation "&( <string_expr> )". + + +4.7) Symbol Table + +During the execution of the program, the evaluation context for +both statements and expressions is performed in the context of +a dynamic scoping environment. That is, as each function, +subroutine or for-loop is encountered, a new symbol table scope +is pushed onto a dynamic run-time stack. When an identifier's +name needs to be resolved and a value for it determined, a +search is performed from the inner-most, current top of the +scope-stack back through the dynamic scope stack towards the +outer-most and earliest scope. + +At each scope, an attempt is made to locate the symbol. If it +is found, that is the symbol that is used. If the symbol can not +be found at any level, it may be an error, or it may be cause to +introduce the symbol, as determined by the context in which the +identifier occurs. + +Constants from the command line using the "-D id=value" construct +are introduced into the outermost scope prior to beginning to +execute the source file proper. This is the same outer-most scope +into which the /const/ and /define/ function symbols are also +introduced. + II - The DT block format
Signature · 1 line
1.6.0.90.g436ed
A message that is not in the archive (sent off-list or not yet received): 1222460748-20127-9-git-send-email-jdl-CYoMK+44s/[email protected]
PATCH v3 9/9 Test constant expressions in cell contexts.
From: Jon Loeliger <[email protected]>
This code is derived from code posted by David Gibson.
--- tests/Makefile.tests | 1 + tests/cell-expressions.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++ tests/run_tests.sh | 5 ++ 3 files changed, 122 insertions(+), 0 deletions(-) create mode 100644 tests/cell-expressions.c
tests/Makefile.tests +1 -0
@@ -10,6 +10,7 @@ LIB_TESTS_L = get_mem_rsv \ move_and_save mangle-layout nopulate \ open_pack rw_tree1 set_name setprop del_property del_node \ string_escapes references path-references boot-cpuid incbin \ + cell-expressions \ dtbs_equal_ordered \ add_subnode_with_nops path_offset_aliases LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
tests/cell-expressions.c new file +116 -0
116 lines not on this page · raw message
tests/run_tests.sh +5 -0
@@ -274,6 +274,11 @@ dtc_tests () { run_dtc_test -I dtb -O dts -o stdin_odts_test_tree1.dtb.test.dts - < test_tree1.dtb run_wrap_test cmp stdin_odts_test_tree1.dtb.test.dts odts_test_tree1.dtb.test.dts + # Check integer expresisons + run_test cell-expressions -g cell-expressions.test.dts + run_dtc_test -I dts -O dtb -o cell-expressions.test.dtb cell-expressions.test.dts + run_test cell-expressions cell-expressions.test.dtb + # Check for graceful failure in some error conditions run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb
Signature · 1 line
1.6.0.90.g436ed
A message that is not in the archive (sent off-list or not yet received): 1222460748-20127-10-git-send-email-jdl-CYoMK+44s/[email protected]
Re: [PATCH 9/9 V3] Test constant expressions in cell contexts.
Quoted 3 lines · Jon Loeliger
From: Jon Loeliger <[email protected]>
This code is derived from code posted by David Gibson.
[snip]
Review
Quoted 2 lines
(quoted diff) +2
-0+ for (i = 0; i < ARRAY_SIZE(expr_table); i++) + if (fdt32_to_cpu(res[i]) != expr_table[i].result)
Hrm.. when you fixed the endian bug here (I found it myself the other day), you might have thought to fix it...
tests/cell-expressions.c line 111
Quoted 3 lines
tests/cell-expressions.c new file +3
-0+ FAIL("Incorrect result for expression \"%s\"," + " 0x%x instead of 0x%x\n", + expr_table[i].expr, res[i],
^^^^^^
...here, too.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 9/9 V3] Test constant expressions in cell contexts.
Quoted 13 lines · David Gibson
Quoted 3 lines · Jon Loeliger
From: Jon Loeliger <[email protected]>
This code is derived from code posted by David Gibson.
[snip]
Review
Quoted 2 lines
(quoted diff) +2
-0+ for (i = 0; i < ARRAY_SIZE(expr_table); i++) + if (fdt32_to_cpu(res[i]) != expr_table[i].result)Hrm.. when you fixed the endian bug here (I found it myself the other day), you might have thought to fix it...
Quoted 6 lines
tests/cell-expressions.c line 111
Quoted 3 lines
tests/cell-expressions.c new file +3
-0+ FAIL("Incorrect result for expression \"%s\"," + " 0x%x instead of 0x%x\n", + expr_table[i].expr, res[i],^^^^^^...here, too.
Gah. Sorry. I'll definitely pick that up.
jdl
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 6 lines · Jon Loeliger
From: Jon Loeliger <[email protected]>
Signed-off-by Jon Loeliger <[email protected]>--- Documentation/manual.txt | 500 ++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 463 insertions(+), 37 deletions(-)
Hey Jon,
I don't yet have fully formed thoughts about this stuff so I've held off on making comments. But FWIW, here are my initial thoughts.
I'm not convinced about the approach of interleaving the executable and data syntaxes. The whole design of the existing syntax is to represent the data structure. Adding additional syntax to define executable elements doesn't feel right to me. I think many people will find the resulting file structure to be confusing.
I'm also not convinced that it is a good idea to implement a new interpreted language. Any new language is a new thing that needs to be maintained and a new thing for users to learn. I'd prefer to make use of an existing language with a library of support routines for maintaining an internal representation of the data and building up a device tree programmatically with the ability to import and manipulate 'stock' nodes for existing parts. However, I haven't spent enough brain cell cycles on this to make any recommendations on a specific language or to figure out if that will just result in even more complexity for users.
As I said, these are just initial thoughts. My opinion could be swayed.
g.
Quoted 572 lines
Documentation/manual.txt +463
-37@@ -105,13 +105,21 @@ Options: -q Quiet: -q suppress warnings, -qq errors, -qqq all + -D <id> + -D <id>=<value> + Introduce a constant definition for symbol <id> with + possible initial value given by <value>. The RHS + should be a literal number or string value. + + -p <padsize> + Add at least <padsize> additional space to the DTB image. + -R <number> Make space for <number> reserve map entries Relevant for dtb and asm output only. -S <bytes> - Ensure the blob at least <bytes> long, adding additional - space if needed. + Deprecated option. -v Print DTC version and exit.@@ -131,47 +139,338 @@ Additionally, dtc performs various sanity checks on the tree. 4) Device Tree Source file -4.1) Overview -Here is a very rough overview of the layout of a DTS source file: +4.1) DTS Lexical Components + +Property and node names [a-zA-Z0-9,._+*#?@-]+ +Identifiers \\[a-zA-Z_][a-zA-Z0-9_]* +Labels [a-zA-Z_][a-zA-Z0-9_]* +Strings <C-style-double-quoted-strings> +Comments Both /* ... */ and // style are supported +Numeric literals <C-style-integer-numbers> +Bytes [0-9a-fA-F][0-9a-fA-F] + +Keywords: + else + for + if + in + return + void + /const/ + /define/ + /incbin/ + +C-style expression operators: + << + >> + <= + >= + == + != + && + || + + + - + * + / + % + +Additional tokens: + .. + := + { + } + , + & + + +These constructs are handled and eliminated purely at the +lexical level and do not appear in the grammar proper: + + - Source files included using the syntax: + + /include/ "filename" + + - Both classic C style and C++ style comments are supported. + Comments don't nest. + For example, given: + + 1 /* + 2 * asdasdasd // asdasdad + 3 // */ + 4 asasd + 5 */ + The // comment on line 3 is not effective and is ignored. + The original /* comment ends on line 3. Line 5 is in error. + + And given: + + 1 // /* + 2 * asdasdasd // asdasdad + 3 */ + + The // comment on line 1 hides the opening /*. + Line 2 is in error. + + +4.2) DTS Grammar + +Here is a very rough overview of the grammar of a DTS source file: + + + sourcefile: + '/dts-v1/' ';' possibly_empty_list_of_declarations devicetree + + declaration: + memreserve + | constdef + | funcdef + + memreserve: label '/memreserve/' addr addr ';' + + constdef: '/const/' identifier '=' expr ';' + + funcdef: '/define/' propnodename paramdecls statement_block + + paramdecls: '(' possibly_empty_paramdecl_list ')' + + paramdecl: identifier + + devicetree: '/' statement_block + + statement_block: '{' possibly_empty_list_of_statements '}' + + statement: + subnode + | for_statement + | if_statement + | return_statement + | assign_statement + | property_definition + | statement_block + | ';' + + subnode: + node_label expr statement_block ';' + | label expr statement_block ';' + | expr statement_block ';' + + for_statement: + 'for' identifier 'in' expr '..' expr statement_block + + if_statement: + 'if' '(' expr ')' statement_block + | 'if' '(' expr ')' statement_block 'else' statement_block + + return_statement: 'return' expr ';' + + assign_statement: identifier ':=' expr ';' + + property_definition: + optional_label expr ';' + | optional_label expr '=' list_of_property_data_and_labels ';' + list_of_property_data_and_labels: + STRING + | '<' possibly_empty_list_of_cell_values_and_labels '>' + | '[' possibly_empty_list_of_byte_values_and_labels ']' + | label + | '/incbin/' '(' expr ')' + | '/incbin/' '(' expr ',' expr ',' expr ')' - sourcefile: list_of_memreserve devicetree + cell_value: + expr_primary + | '&' '(' expr ')' + | '&' phandle_reference + | label - memreserve: label 'memreserve' ADDR ADDR ';' - | label 'memreserve' ADDR '-' ADDR ';' - devicetree: '/' nodedef + expr: + expr_primary + | expr '?' expr ':' expr + | expr expr_oper expr - nodedef: '{' list_of_property list_of_subnode '}' ';' + expr_oper: + || + && + | + ^ + & + == + < | > | <= | >= + << | >> + + | - + * | / | % + - | ~ | ! + '(' ')' | '(' non_empty_list_of_param_exprs ')' - property: label PROPNAME '=' propdata ';' + expr_primary: + literal + | string + | propnodename + | identifier + | '(' expr ')' - propdata: STRING - | '<' list_of_cells '>' - | '[' list_of_bytes ']' + addr: expr - subnode: label nodename nodedef + node_label: expr ':' -That structure forms a hierarchical layout of nodes and properties -rooted at an initial node as: + propnodename: <1275-property-name> + + identifier: '\'-<C style name> + + literal: <C style number> + byte: <exactly two hex digits> + string: <C style string> + label: '&'-<label name>-':' + + +4.2) Overview + +The DTS source file begins with the '/dts-v1/' token to state +that it is using "Version 1" style source files. + +Any declarations are executed in order, and can use the +effects of earlier declarations. + +All declarations must precede the required root node definition, +which is introduced with the '/'-named node: / { + ... } -Both classic C style and C++ style comments are supported. +The statement-block structure forms a hierarchical layout of nodes +and properties along with some control-statements that allow for +repeated and alternate statement blocks. + + +4.3) Declarations + +An arbitrary list of declarations can be made between '/dts-v1/' +and the beginning of the root node. These declarations are +introduced in order. + + +4.3.1) Memory Reservations + +A memory reservation is a declaration that a block of memory +from the first address expression, with a size given by the +second address expression, is to be "reserved" and not used +by the kernel. These address ranges are passed through to +the DTB to the kernel. + + +4.3.2) Function Definitions + +A function definition can be introduced using /define/. +These definitions are just "stored" and then later invoked as +either a subroutine in a statement context, or as a function +with a return value in an expression context. -Source files may be directly included using the syntax: +Functions declare the number of formal parameters which will +be passed in at the call site, and must match one-to-one. - /include/ "filename" +Any property definitions generated by the function are emitted +into the caller's context at the point of the call. +Any node definitions generated by the function are emitted +into the caller's context at the point of the call. -4.2) Properties -Properties are named, possibly labeled, values. Each value -is one of: +4.3.3) Constant Definitions - - A null-teminated C-like string, +Constant definitions introduce a named identifier into the outer-most +symbol scope. The constants can not be changed by later assignment +statements, though they can be hidden. (Be careful.) + +Constants may be expressions yielding constant numeric or strings +values. It is an error for them not to be evaluatable at their +point of definition. + +Constant definitions may also be introduced from the command line +using the '-D var=value" options. They will be placed into the +same outer-most scope. Constant definitions from the command line +override the definitions within the source file, but with a warning. + + +4.4) Statements + +A statement block is simply a list of sequentially executed +statements introduced with a required opening brace and terminated +with a required closing brace. + +4.4.1) Subnodes + +Node may contain sub-nodes to obtain a hierarchical structure. + +For example: + + - A child node named "childnode" whose unit name is + "childnode at address". It it turn has a string property + called "childprop". + + childnode@address { + childprop = "hello\n"; + }; + + +4.4.2) 'for' Statement + +The 'for' statement provides iterative execution of a +block of statements. + +The lower bound of the range is evaluated once, and the +upper bound is evaluated once. + +A new scope that contains the loop variable is created +and pushed onto the symbol table scope stack. The loop +variable is initialized with the lower bound value. + +The statement block is executed once for each inclusive value +in the given range in increasing order. + +After the loop terminates, the loop variable scope is popped. + + +4.4.3) 'if' Statement + +The 'if' statement provides alternate execution flow paths. +The expression is evaluated once, and if non-zero, the fist +statement block is executed, otherwise the 'else' block of +statements is executed if present. + + +4.4.4) 'return' Statement + +Inside a function definition, the 'return' statement allows +a value to be passed back to the caller. The return expression +is evaluated once, in the context of the function's scope, +and its resultant value is made available as the function's +return result. + + +4.4.5) Assign Statement + +The ':=' operator allows assignment to non-constant identifiers. + +The identifiers can be either formal parameters or variable as +found by the searching using the dynamic symbol table scoping rules. + +An assignment to an otherwise unknown identifier causes that +identifier to be introduced into the current scope. + +You can't assign to /constant/ identifiers (except in the initial +definition of them). + + +4.4.6) Property Definition + +Properties are named, possibly labeled, values. +Each value within a property is one of: + + - A null-terminated C-like string, - A numeric value fitting in 32 bits, - A list of 32-bit values - A byte sequence@@ -195,27 +494,126 @@ Here are some example property definitions: property4 = [0a 0b 0c 0d de ea ad be ef]; -Node may contain sub-nodes to obtain a hierarchical structure. -For example: +4.4.7) Subroutine calls - - A child node named "childnode" whose unit name is - "childnode at address". It it turn has a string property - called "childprop". +An expression at the statement level should be a function call, +though it might be considered as just a "subroutine call" as +any return value is thrown away. - childnode@addresss { - childprop = "hello\n"; - }; +Invocation of the function introduces a symbol table scope +in which the formal paramters are introduced and bound. +Initial values for the formals are obtained by evaluating +the actual parameters, in order, and using a copy-in binding. + +Any incidental (dynamically occurring) assignment to an +otherwise unknown identifier will cause the introduction of +a new variable in the function's execution scope. + +Any property definitions generated by the function are emitted +into the caller's context at the point of the subroutine call. + +Any node definitions generated by the function are emitted +into the caller's context at the point of the subroutine call. + +Any return value from a return statement is thrown away. +Execution control is returned to the point of the call. -By default, all numeric values are hexadecimal. Alternate bases -may be specified using a prefix "d#" for decimal, "b#" for binary, -and "o#" for octal. -Strings support common escape sequences from C: "\n", "\t", "\r", -"\(octal value)", "\x(hex value)". +4.5) Expressions +Basically, expressions follow C conventions. However, there +are no assignment operations such as +=, or pre-/post- +increment/decrement. -4.3) Labels and References +The '%' operation is a modulus operation for integers, and +a string concatenation operation if at least one of the operands +is determined to be a string value. + + +4.5.1) Expressions + +Pretend it is C and see how close we get. + + +4.5.2) Function Invocations + +A previously defined function may be invoked from within an +expression. A "return" statement should be used to return +a resulting expression value to the caller's context. + +Invocation of the function introduces a symbol table scope +in which the formal parameters are introduced and bound. +Initial values for the formals are obtained by evaluating +the actual parameters, in order, and using a copy-in binding. + +Any incidental (dynamically occurring) assignment to an +otherwise unknown identifier will cause the introduciton of +a new variable in the function's execution scope. + +Any property definitions generated by the function are emitted +into the caller's context at the point of the subroutine call. + +Any node definitions generated by the function are emitted +into the caller's context at the point of the subroutine call. + +Any return value from a return statement is used as the result +of the function call within the context of the original expression. + +Execution control is returned to the point of the call. + + +4.5.3) Builtin Functions + +There are a few builtin function names; + + join() Concatenate and return a list of expression + as a string. Non-string arguments are coerced + into being a string. + + hexstr() Format and return a hex string representation + of the one parameter without a leading '0x'. + +While not here yet, /incbin/ should be converted into a builtin. + + +4.5.4) Literal Numbers + +Literal numbers follow C conventions. Specifically, they are +base-ten by default, but can be hexadecimal, binary or octal +with a leading 0x or 0X, 0b or OB, or a simple leading zero, +respectively. + +There is no support for floating point representations at all. + +Most math and expression handling is assumed to be 64-bit, but +a cell-context may force a 32-bit container instead. + + +4.5.5) Literal Strings + +Strings support common escape sequences from C: + "\n", "\t", "\r" + "\(octal value)" + "\x(hex value)" + + +4.5.6) Identifiers + +Identifiers references are resolved using dynamic symbol table +scoping rules. An identifier referenced on the right-hand-side +of an expression must be resolvable or else it is an error. + +An identifier occurring on the left-hand-side of a ':=' assignment +is first sought and used if found. If it is not found, it is +introduced dynamically in the innermost, current scope. + +Sometimes identifiers can be used without the leading slash, +other times they are required, especially if to disambiguate +from property names. It's not ideal yet at all. + + +4.6) Labels and References Labels may be applied to nodes or properties. Labels appear before a node name, and are referenced using an ampersand: &label.@@ -239,6 +637,34 @@ And used in properties, lables may appear before or after any value: }; +The names of some labels can be constructed in an expression +context using the representation "&( <string_expr> )". + + +4.7) Symbol Table + +During the execution of the program, the evaluation context for +both statements and expressions is performed in the context of +a dynamic scoping environment. That is, as each function, +subroutine or for-loop is encountered, a new symbol table scope +is pushed onto a dynamic run-time stack. When an identifier's +name needs to be resolved and a value for it determined, a +search is performed from the inner-most, current top of the +scope-stack back through the dynamic scope stack towards the +outer-most and earliest scope. + +At each scope, an attempt is made to locate the symbol. If it +is found, that is the symbol that is used. If the symbol can not +be found at any level, it may be an error, or it may be cause to +introduce the symbol, as determined by the context in which the +identifier occurs. + +Constants from the command line using the "-D id=value" construct +are introduced into the outermost scope prior to beginning to +execute the source file proper. This is the same outer-most scope +into which the /const/ and /define/ function symbols are also +introduced. + II - The DT block formatSignature · 6 lines
1.6.0.90.g436ed _______________________________________________ devicetree-discuss mailing list [email protected] https://ozlabs.org/mailman/listinfo/devicetree-discuss
A message that is not in the archive (sent off-list or not yet received): 20080930145537.GJ18313-s3s/[email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 30 lines · Grant Likely
Quoted 6 lines · Jon Loeliger
From: Jon Loeliger <[email protected]>
Signed-off-by Jon Loeliger <[email protected]>--- Documentation/manual.txt | 500 ++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 463 insertions(+), 37 deletions(-)Hey Jon,
I don't yet have fully formed thoughts about this stuff so I've held off on making comments. But FWIW, here are my initial thoughts.
I'm not convinced about the approach of interleaving the executable and data syntaxes. The whole design of the existing syntax is to represent the data structure. Adding additional syntax to define executable elements doesn't feel right to me. I think many people will find the resulting file structure to be confusing.
I'm also not convinced that it is a good idea to implement a new interpreted language. Any new language is a new thing that needs to be maintained and a new thing for users to learn. I'd prefer to make use of an existing language with a library of support routines for maintaining an internal representation of the data and building up a device tree programmatically with the ability to import and manipulate 'stock' nodes for existing parts. However, I haven't spent enough brain cell cycles on this to make any recommendations on a specific language or to figure out if that will just result in even more complexity for users.
Quoted 2 lines
As I said, these are just initial thoughts. My opinion could be swayed.
Ah, thank you Grant, you've helped clarify by own objections to the current proposal.
The current device tree description is purely declarative, but this proposal would make it a rather odd hybrid of declarative and imperative components. I do think this could be confusing, particularly to device tree newcomers who may not realise which components are compile time evaluated and which go into the output tree. I had in mind a rather more functional-programming style for macros/computed properties to ameliorate this.
The several new components of not-C-feel syntax worry me greatly. If you recall the one time I stepped away from C-inspired syntax in the original language (bare hex constants), turned out to be a big mistake requiring an incompatible source format change to fix. I really want to avoid doing that again, if we possibly can.
I'm also concerned about adding language-level functions to the language. This requires us to have runtime notions of type and symbols and carry them around for evaluation. I still favour a macro-expansion style preprocessing stage instead of semantic-level functions for several reasons:
- it provides high flexibility for low conceptual complexity
- we don't have to carry around run-time evaluation structures
- it's a form familiar to C programmers from the preprocessor
This could either be done by actually invoking cpp, using some pre-and-post mangling to deal with the #-in-property-names problem. Or we could build our own preprocessor that uses something other than
# as a magic character, but otherwise works like cpp.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
From: David Gibson <[email protected]>
Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Date: Wed, 1 Oct 2008 13:46:56 +1000
Quoted 4 lines
This could either be done by actually invoking cpp, using some pre-and-post mangling to deal with the #-in-property-names problem. Or we could build our own preprocessor that uses something other than
# as a magic character, but otherwise works like cpp.
There's always m4, but that has its own set of issues.
Not sure if I should add a :-) or a :-(.
You could also s/#/$/g on the source and pass that through cpp and then undo it on the other side. Assuming that cpp has been compiled with $ in symbol name support.
The root of the problem here is that the original openfirmware spec wasn't 'C' and many of the new language features are aimed at a 'C' audience...
Warner
A message that is not in the archive (sent off-list or not yet received): 20080930.220151.41675821.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 10 lines · Warner Losh
From: David Gibson <[email protected]>
Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Date: Wed, 1 Oct 2008 13:46:56 +1000Quoted 4 lines
This could either be done by actually invoking cpp, using some pre-and-post mangling to deal with the #-in-property-names problem. Or we could build our own preprocessor that uses something other than
# as a magic character, but otherwise works like cpp.There's always m4, but that has its own set of issues.
Yes. I've thought about m4, but I'm pretty sure I don't want to go there.
Quoted 5 lines
Not sure if I should add a :-) or a :-(.
You could also s/#/$/g on the source and pass that through cpp and then undo it on the other side. Assuming that cpp has been compiled with $ in symbol name support.
Something vaguely like that was what I had in mind - probably using some magic based on '/' instead. I planned to leave the processor directives as #, but with the # only recognized in column 0. Strictly speaking that's a syntax change, but it won't bite any properly indented existing source.
Quoted 3 lines
The root of the problem here is that the original openfirmware spec wasn't 'C' and many of the new language features are aimed at a 'C' audience...
Well, the dtc source format has been aimed at C programmers from day 1, not just the new features.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 9 lines · David Gibson
The current device tree description is purely declarative, but this proposal would make it a rather odd hybrid of declarative and imperative components. I do think this could be confusing, particularly to device tree newcomers who may not realise which components are compile time evaluated and which go into the output tree. I had in mind a rather more functional-programming style for macros/computed properties to ameliorate this.
The several new components of not-C-feel syntax worry me greatly.
Wouldn't a "more functional-programming style" be further away from C?
Quoted 5 lines
If
you recall the one time I stepped away from C-inspired syntax in the original language (bare hex constants), turned out to be a big mistake requiring an incompatible source format change to fix. I really want to avoid doing that again, if we possibly can.
If you really want to be as much like C as possible, nothing's stopping you from just defining the data structures in real C. :-P
Bare hex constants being a bad idea was not purely due to it being different from C.
We also have a substantial difference in the syntax of node/property definitions, which forces syntax differences in other parts of the lanugage to avoid ambiguity.
Quoted 8 lines
I'm also concerned about adding language-level functions to the language. This requires us to have runtime notions of type and symbols and carry them around for evaluation. I still favour a macro-expansion style preprocessing stage instead of semantic-level functions for several reasons:
- it provides high flexibility for low conceptual complexity
- we don't have to carry around run-time evaluation structures
- it's a form familiar to C programmers from the preprocessor
I vote against anything similar to the C preprocessor.
-Scott
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 1 line
I vote against anything similar to the C preprocessor.
The advantage of the current language that's been floated here is that its 'execution' elements offer a far more expressive macro generation capability than the cpp. cpp doesn't have for loops. There's no way to convert a number to hex in cpp. Complicated if statements aren't possible. And so on. m4 allows these things, but imposes restrictions that make it awkward to use in this context, so it is out (despite my comments yesterday, and the fact I use it to genreate the html for my resume). There's really no other widely available preprocessor that would be useful here.
Then again, I'm not sure that I completely buy into the mixing data definitions and execution elements being confusing. We do that right now in every C program you write with global variables... The problem here is that we're inventing a scripting language to generate data structures, much like web pages are generated in some scripting languages by haing the output be html. There's little confusion there (and no, I'm not suggesting we use one of them :-).
Warner
A message that is not in the archive (sent off-list or not yet received): 20081001.094306.71131107.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 6 lines · Warner Losh
Quoted 1 line
I vote against anything similar to the C preprocessor.
The advantage of the current language that's been floated here is that its 'execution' elements offer a far more expressive macro generation capability than the cpp. cpp doesn't have for loops. There's no way to convert a number to hex in cpp.
But those can be done in expressions which the macros can generate. It's just a matter of implementing the right operators and builtin functions.
Quoted 7 lines
Complicated if statements aren't
possible. And so on. m4 allows these things, but imposes restrictions that make it awkward to use in this context, so it is out (despite my comments yesterday, and the fact I use it to genreate the html for my resume). There's really no other widely available preprocessor that would be useful here.
Quoted 7 lines
Then again, I'm not sure that I completely buy into the mixing data definitions and execution elements being confusing. We do that right now in every C program you write with global variables... The problem here is that we're inventing a scripting language to generate data structures, much like web pages are generated in some scripting languages by haing the output be html. There's little confusion there (and no, I'm not suggesting we use one of them :-).
Hrm, yes. And I really dislike the idea of creating yet-another scripting language just for our purposes. It may be simple now, but I greatly fear if we start down this path it will grow to become a Turing-complete monstrosity.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 9 lines · Scott Wood
Quoted 8 lines · David Gibson
The current device tree description is purely declarative, but this proposal would make it a rather odd hybrid of declarative and imperative components. I do think this could be confusing, particularly to device tree newcomers who may not realise which components are compile time evaluated and which go into the output tree. I had in mind a rather more functional-programming style for macros/computed properties to ameliorate this.
Quoted 4 lines
Quoted 1 line
The several new components of not-C-feel syntax worry me greatly.
Wouldn't a "more functional-programming style" be further away from C?
Yes and no - the preprocessor aspects of C are roughly functional-programming style, at least in the sense I'm intending here. Besides, it's not the language as a whole that's supposed to be like C - clearly it's not - it's the syntactic feel. The idea is to make syntactic analogies with C wherever possible, so that C programmers writing dts files won't find themselves continually making little syntactic mistakes.
Quoted 9 lines
Quoted 5 lines
If
you recall the one time I stepped away from C-inspired syntax in the original language (bare hex constants), turned out to be a big mistake requiring an incompatible source format change to fix. I really want to avoid doing that again, if we possibly can.If you really want to be as much like C as possible, nothing's stopping you from just defining the data structures in real C. :-P
Quoted 6 lines
Bare hex constants being a bad idea was not purely due to it being different from C.
We also have a substantial difference in the syntax of node/property definitions, which forces syntax differences in other parts of the lanugage to avoid ambiguity.
Yes. But I think insufficient thought has gone into the current proposal as to how to avoid ambiguity where we have to, while keeping the C-syntactic-feel as much as possible.
Quoted 10 lines
Quoted 8 lines
I'm also concerned about adding language-level functions to the language. This requires us to have runtime notions of type and symbols and carry them around for evaluation. I still favour a macro-expansion style preprocessing stage instead of semantic-level functions for several reasons:
- it provides high flexibility for low conceptual complexity
- we don't have to carry around run-time evaluation structures
- it's a form familiar to C programmers from the preprocessorI vote against anything similar to the C preprocessor.
Why?
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 3 lines · David Gibson
Quoted 1 line
I vote against anything similar to the C preprocessor.
Why?
It's not nearly as powerful as the semantic approach, and it is syntactically clumsy (I do *not* want to have to put a backslash at the end of every line within a macro, for example).
-Scott
A message that is not in the archive (sent off-list or not yet received): 20081002152242.GB22258-VKaLA/[email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 6 lines · Scott Wood
Quoted 3 lines · David Gibson
Quoted 1 line
I vote against anything similar to the C preprocessor.
Why?
It's not nearly as powerful as the semantic approach, and it is
How so? If anything I think it's more powerful, because the macro boundaries can be anywhere, not only at the edges of particular semantic constructs.
Quoted 2 lines
syntactically clumsy (I do *not* want to have to put a backslash at the end of every line within a macro, for example).
Avoiding the backslashes everywhere is a reasonable argument though. That's avoidable without dropping the basic idea of macro expansion, though.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 7 lines · David Gibson
Quoted 4 lines · Scott Wood
Quoted 2 lines · David Gibson
Quoted 1 line
I vote against anything similar to the C preprocessor.
Why?
It's not nearly as powerful as the semantic approach, and it is
How so?
Compare this:
/for/ i in 0..7
do_something(\i);
to this:
#define DO2SOMETIHNGS DOSOMETHING DOSOMETHING
#define DO4SOMETHINGS DO2SOMETHINGS DO2SOMETHINGS
#define DO8SOMETHINGS DO4SOMETHINGS DO4SOMETHINGS
And if you want the number of somethings to be easily tweakable, you may need to do #include/#ifdef recursion.
Quoted 3 lines
If anything I think it's more powerful, because the macro boundaries can be anywhere, not only at the edges of particular semantic constructs.
Is that useful outside the International Obfuscated DTC Contest?
-Scott
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 14 lines · Scott Wood
Quoted 7 lines · David Gibson
Quoted 4 lines · Scott Wood
Quoted 2 lines · David Gibson
Quoted 1 line
I vote against anything similar to the C preprocessor.
Why?
It's not nearly as powerful as the semantic approach, and it is
How so?
Compare this:
/for/ i in 0..7
do_something(\i);
Quoted 8 lines
to this:
#define DO2SOMETIHNGS DOSOMETHING DOSOMETHING
#define DO4SOMETHINGS DO2SOMETHINGS DO2SOMETHINGS
#define DO8SOMETHINGS DO4SOMETHINGS DO4SOMETHINGSAnd if you want the number of somethings to be easily tweakable, you may need to do #include/#ifdef recursion.
Yes, we'd certainly need some sort of iteration operator in the expressions for this sort of thing.
Quoted 6 lines
Quoted 4 lines
If anything I think it's more powerful, because the macro boundaries can be anywhere, not only at the edges of particular semantic constructs.
Is that useful outside the International Obfuscated DTC Contest?
Maybe. I can see uses for both this style:
mynodename@12345 NODE_CONTENTS_MACRO(x,y,z); and this style: NODE_MACRO(p,q,r);
where the macro generates the name as well.
Both are trivially possible with macros, but would need different types of definition with a runtime system, which increases complexity.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 5 lines · David Gibson
Quoted 2 lines
And if you want the number of somethings to be easily tweakable, you may need to do #include/#ifdef recursion.
Yes, we'd certainly need some sort of iteration operator in the expressions for this sort of thing.
OK, but now we're talking about something more complex than running it through CPP with some character conversion.
A more powerful macro language is certainly an option, though I have a personal preference for the semantic approach.
Quoted 6 lines
Quoted 5 lines
Quoted 3 lines
If anything I think it's more powerful, because the macro boundaries can be anywhere, not only at the edges of particular semantic constructs.
Is that useful outside the International Obfuscated DTC Contest?
Quoted 8 lines
Maybe. I can see uses for both this style:
mynodename@12345 NODE_CONTENTS_MACRO(x,y,z); and this style: NODE_MACRO(p,q,r);where the macro generates the name as well.
Both are trivially possible with macros, but would need different types of definition with a runtime system, which increases complexity.
You can do this in the proposed language by either defining a function that takes the node name/unit address as a parameter, or by defining a function that returns a set of properties.
-Scott
A message that is not in the archive (sent off-list or not yet received): 20081003152700.GA9115-VKaLA/[email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 4 lines · Scott Wood
Quoted 3 lines · David Gibson
Quoted 2 lines
And if you want the number of somethings to be easily tweakable, you may need to do #include/#ifdef recursion.
Quoted 8 lines
Quoted 2 lines
Yes, we'd certainly need some sort of iteration operator in the expressions for this sort of thing.
OK, but now we're talking about something more complex than running it through CPP with some character conversion.
A more powerful macro language is certainly an option, though I have a personal preference for the semantic approach.
Ugh.. actually. What I had in mind was not macro features to do iteration, but iteration constructs in expressions that macros could expand to. But I just realised that might not suffice. It's a fairly limited number of use cases that that will work for, although I think they will be common ones.
But you do have a point here.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveIn message: <20081002152242.GB22258-VKaLA/[email protected]>
Scott Wood <[email protected]> writes:
: On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
: > > I vote against anything similar to the C preprocessor.
: >
: > Why?
:
: It's not nearly as powerful as the semantic approach, and it is
: syntactically clumsy (I do *not* want to have to put a backslash at the
: end of every line within a macro, for example).
And there are no looping constructs at all in CPP. You flat out can't do a generalized for loop with the macro language, for example. Its symbols also do not map 1-1/onto symbols used by the dts files. It can only grok macros you define for it, so it has no way of knowing many useful things that dts just knows.
Basically, it is using a hammer to pound screws in. Sure, it seems to work, but the results are shoddy.
Warner
A message that is not in the archive (sent off-list or not yet received): 20081002.135004.1723231860.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 17 lines · M. Warner Losh
In message: <20081002152242.GB22258-VKaLA/[email protected]>
Scott Wood <[email protected]> writes:
: On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
: > > I vote against anything similar to the C preprocessor.
: >
: > Why?
:
: It's not nearly as powerful as the semantic approach, and it is
: syntactically clumsy (I do *not* want to have to put a backslash at the
: end of every line within a macro, for example).And there are no looping constructs at all in CPP. You flat out can't do a generalized for loop with the macro language, for example. Its symbols also do not map 1-1/onto symbols used by the dts files. It can only grok macros you define for it, so it has no way of knowing many useful things that dts just knows.
Quoted 4 lines
Basically, it is using a hammer to pound screws in. Sure, it seems to work, but the results are shoddy.
Warner
Also, it might be worth noting that if one uses "-I dts -O dts" with my patch set, it is pretty-darn similar behavior to a simple pre-processing pass that simply expands the original constructs into a flat DTS file like we have today.
jdl
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 21 lines · Jon Loeliger
Quoted 20 lines · M. Warner Losh
In message: <20081002152242.GB22258-VKaLA/[email protected]>
Scott Wood <[email protected]> writes:
: On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
: > > I vote against anything similar to the C preprocessor.
: >
: > Why?
:
: It's not nearly as powerful as the semantic approach, and it is
: syntactically clumsy (I do *not* want to have to put a backslash at the
: end of every line within a macro, for example).And there are no looping constructs at all in CPP. You flat out can't do a generalized for loop with the macro language, for example. Its symbols also do not map 1-1/onto symbols used by the dts files. It can only grok macros you define for it, so it has no way of knowing many useful things that dts just knows.
Basically, it is using a hammer to pound screws in. Sure, it seems to work, but the results are shoddy.
Quoted 6 lines
Quoted 1 line
Warner
Also, it might be worth noting that if one uses "-I dts -O dts" with my patch set, it is pretty-darn similar behavior to a simple pre-processing pass that simply expands the original constructs into a flat DTS file like we have today.
Sorry, I don't see the relevance of this.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 11 lines · M. Warner Losh
In message: <20081002152242.GB22258-VKaLA/[email protected]>
Scott Wood <[email protected]> writes:
: On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
: > > I vote against anything similar to the C preprocessor.
: >
: > Why?
:
: It's not nearly as powerful as the semantic approach, and it is
: syntactically clumsy (I do *not* want to have to put a backslash at the
: end of every line within a macro, for example).
Quoted 2 lines
And there are no looping constructs at all in CPP. You flat out can't do a generalized for loop with the macro language, for example. Its
But we can put looping constructs into the expression support which macros can then use.
Quoted 3 lines
symbols also do not map 1-1/onto symbols used by the dts files. It can only grok macros you define for it, so it has no way of knowing many useful things that dts just knows.
Uh.. I'm not sure what you mean by this.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In message: <[email protected]>
David Gibson <[email protected]> writes:
: On Thu, Oct 02, 2008 at 01:50:04PM -0600, M. Warner Losh wrote:
: > In message: <20081002152242.GB22258-VKaLA/[email protected]>
: > Scott Wood <[email protected]> writes:
: > : On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
: > : > > I vote against anything similar to the C preprocessor.
: > : >
: > : > Why?
: > :
: > : It's not nearly as powerful as the semantic approach, and it is
: > : syntactically clumsy (I do *not* want to have to put a backslash at the
: > : end of every line within a macro, for example).
: >
: > And there are no looping constructs at all in CPP. You flat out can't
: > do a generalized for loop with the macro language, for example. Its
:
: But we can put looping constructs into the expression support which
: macros can then use.
:
: > symbols also do not map 1-1/onto symbols used by the dts files. It
: > can only grok macros you define for it, so it has no way of knowing
: > many useful things that dts just knows.
:
: Uh.. I'm not sure what you mean by this.
I mean that identifiers have # in them in the dts language. cpp deals with identifiers that are similar to, but not the same thing as dts.
Warner
A message that is not in the archive (sent off-list or not yet received): 20081002.191705.-108805802.imp-uzTCJ5RojNnQT0dZR+AlfA@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 26 lines · M. Warner Losh
In message: <[email protected]>
David Gibson <[email protected]> writes:
: On Thu, Oct 02, 2008 at 01:50:04PM -0600, M. Warner Losh wrote:
: > In message: <20081002152242.GB22258-VKaLA/[email protected]>
: > Scott Wood <[email protected]> writes:
: > : On Thu, Oct 02, 2008 at 11:18:00AM +1000, David Gibson wrote:
: > : > > I vote against anything similar to the C preprocessor.
: > : >
: > : > Why?
: > :
: > : It's not nearly as powerful as the semantic approach, and it is
: > : syntactically clumsy (I do *not* want to have to put a backslash at the
: > : end of every line within a macro, for example).
: >
: > And there are no looping constructs at all in CPP. You flat out can't
: > do a generalized for loop with the macro language, for example. Its
:
: But we can put looping constructs into the expression support which
: macros can then use.
:
: > symbols also do not map 1-1/onto symbols used by the dts files. It
: > can only grok macros you define for it, so it has no way of knowing
: > many useful things that dts just knows.
:
: Uh.. I'm not sure what you mean by this.
Quoted 2 lines
I mean that identifiers have # in them in the dts language. cpp deals with identifiers that are similar to, but not the same thing as dts.
No. Property and node names can have # in them in the dts. I don't think of those as identifiers - bare propnodenames are only recognized in limited contexts.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveOkay, I'm going to reach way into the past here and reopen an old argument...
Here's a link to the original conversation:
http://www.mail-archive.com/[email protected]/msg00161.html
Quoted 8 lines · David Gibson
Quoted 7 lines · Grant Likely
Quoted 6 lines · Jon Loeliger
From: Jon Loeliger <[email protected]>
Signed-off-by Jon Loeliger <[email protected]>---
Documentation/manual.txt | 500 ++++++++++++++++++++++++++++++++++++++++++----1 files changed, 463 insertions(+), 37 deletions(-)
[snip Jon's new language proposal]
Quoted 5 lines
Quoted 5 lines
I'm not convinced about the approach of interleaving the executable and data syntaxes. The whole design of the existing syntax is to represent the data structure. Adding additional syntax to define executable elements doesn't feel right to me. I think many people will find the resulting file structure to be confusing.
[Snip the rest of my comments]
Quoted 7 lines
The current device tree description is purely declarative, but this proposal would make it a rather odd hybrid of declarative and imperative components. I do think this could be confusing, particularly to device tree newcomers who may not realise which components are compile time evaluated and which go into the output tree. I had in mind a rather more functional-programming style for macros/computed properties to ameliorate this.
[snip the rest of David's comments]
Now that I've had about a year and a half to simmer about it, I think I have a counter proposal on a dts syntax extension.
First, I should state the problems I'm trying to solve. I have two use cases that interest me:
1) Multiple boards that use the same SoC.
Right now each dts file carries around the full dts definition, even though 95% of it is 'stock' description of the soc. For example, arch/powerpc/boot/dts/*5200* and arch/powerpc/boot/dts/*8349*. I want a way to put all the common description into an SoC dts file, and then be able to tailor it (add nodes, change properties, etc) for the specific board.
2) FPGA designs
The Xilinx FPGA toolchain will generate a dts file to describe a PowerPC or Microblaze FPGA design. However, the generated file is usually not complete. Properties need to be modified (ie. console device or kernel command line) and additional devices need to be added (devices hanging off the i2c, mdio and spi busses, gpio connections). The tool doesn't have a way to tailor the device tree generation, and the FPGA toolchain doesn't know about board level details. I want a way for the developer to write a board-level .dts file that "wraps" or includes the generated file so that it doesn't need to be modified by hand.
I also have some design goals for the proposed solution. First, I want to avoid design a new programming language. If we need full programmatic generation of device trees, there are plenty of general purpose languages that can do the job. I already know of two existing device tree generators; I wrote a prototype generator written in Python, and the Michal wrote the Xilinx dts generator using TCL. I don't want users to have to learn a new language, and I don't want it to be more complex than is needed to solve the specific use cases. As such, I've got no loops, no macros, and no conditionals.
The model that I'm using to approach the problem is to add syntax for including .dts files (exactly how Jon proposed) and syntax for going back after the tree is parsed and changing things. I'm not an expert on syntax, so I'm open to changes in the details, but this is what I'm thinking. Add the following directives to the syntax:
/include/ Include a file
/cd/ Change the 'working node', accepts a full or relative path to a node. Also accepts labels.
/delete-node/ Delete a child node. Similar to /cd/, accepts a full path, a relative path, or a label.
/delete-property/ Delete a property from the working node.
So, for example, I might have the following for the pcm030.dts:
/dts-v1/;
/include/ mpc5200.dtsi; /* dts include file */
/* at this point the basic structure of an mpc5200 board is layed down */
/* Change some properties in the chosen and memory nodes. */ /cd/ /chosen;
linux,stdout-path = &psc1;
/cd/ /memory
reg = <0 0x10000000>;
/* Add some devices to the i2c bus */
/cd/ &i2c1; /* "i2c1" is a label from mpc5200.dtsi */
rtc@51 {
compatible = "nxp,pcf8563";
reg = <0x51>;
};
eeprom@52 {
compatible = "catalyst,24c32";
reg = <0x52>;
};/* Remove the first i2c bus because it isn't used */ /delete-node/ &i2c0
/* The watchdog doesn't work, so remove the fsl,has-wdt property */ /cd/ &timer0;
/delete-prop/ fsl,has-wdt;
And that's it. I think this covers the functionality that I need. What does everyone think? Are there other important use cases that I should also be addressing?
Cheers,
g.
A message that is not in the archive (sent off-list or not yet received): fa686aa41002200813o3fea9a34s198be367ad81b367-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 112 lines · Grant Likely
Okay, I'm going to reach way into the past here and reopen an old argument...
Here's a link to the original conversation:
http://www.mail-archive.com/[email protected]/msg00161.html
Quoted 8 lines · David Gibson
Quoted 7 lines · Grant Likely
Quoted 6 lines · Jon Loeliger
From: Jon Loeliger <[email protected]>
Signed-off-by Jon Loeliger <[email protected]>---
Documentation/manual.txt | 500 ++++++++++++++++++++++++++++++++++++++++++----1 files changed, 463 insertions(+), 37 deletions(-)[snip Jon's new language proposal]
Quoted 5 lines
Quoted 5 lines
I'm not convinced about the approach of interleaving the executable and data syntaxes. The whole design of the existing syntax is to represent the data structure. Adding additional syntax to define executable elements doesn't feel right to me. I think many people will find the resulting file structure to be confusing.
[Snip the rest of my comments]
Quoted 7 lines
The current device tree description is purely declarative, but this proposal would make it a rather odd hybrid of declarative and imperative components. I do think this could be confusing, particularly to device tree newcomers who may not realise which components are compile time evaluated and which go into the output tree. I had in mind a rather more functional-programming style for macros/computed properties to ameliorate this.
[snip the rest of David's comments]
Now that I've had about a year and a half to simmer about it, I think I have a counter proposal on a dts syntax extension.
First, I should state the problems I'm trying to solve. I have two use cases that interest me:
1) Multiple boards that use the same SoC.
Right now each dts file carries around the full dts definition, even though 95% of it is 'stock' description of the soc. For example,arch/powerpc/boot/dts/*5200*andarch/powerpc/boot/dts/*8349*. I want a way to put all the common description into an SoC dts file, and then be able to tailor it (add nodes, change properties, etc) for the specific board.2) FPGA designs
The Xilinx FPGA toolchain will generate a dts file to describe a PowerPC or Microblaze FPGA design. However, the generated file is usually not complete. Properties need to be modified (ie. console device or kernel command line) and additional devices need to be added (devices hanging off the i2c, mdio and spi busses, gpio connections). The tool doesn't have a way to tailor the device tree generation, and the FPGA toolchain doesn't know about board level details. I want a way for the developer to write a board-level .dts file that "wraps" or includes the generated file so that it doesn't need to be modified by hand.I also have some design goals for the proposed solution. First, I want to avoid design a new programming language. If we need full programmatic generation of device trees, there are plenty of general purpose languages that can do the job. I already know of two existing device tree generators; I wrote a prototype generator written in Python, and the Michal wrote the Xilinx dts generator using TCL. I don't want users to have to learn a new language, and I don't want it to be more complex than is needed to solve the specific use cases. As such, I've got no loops, no macros, and no conditionals.
The model that I'm using to approach the problem is to add syntax for including .dts files (exactly how Jon proposed) and syntax for going back after the tree is parsed and changing things. I'm not an expert on syntax, so I'm open to changes in the details, but this is what I'm thinking. Add the following directives to the syntax:
/include/ Include a file
/cd/ Change the 'working node', accepts a full or relative path to a node. Also accepts labels.
/delete-node/ Delete a child node. Similar to /cd/, accepts a full path, a relative path, or a label.
/delete-property/ Delete a property from the working node.So, for example, I might have the following for the
pcm030.dts:/dts-v1/;
/include/mpc5200.dtsi; /* dts include file */
/* at this point the basic structure of an mpc5200 board is layed down *//* Change some properties in the chosen and memory nodes. */ /cd/ /chosen;
linux,stdout-path = &psc1;
/cd/ /memory
reg = <00x10000000>;/* Add some devices to the i2c bus */
/cd/ &i2c1; /* "i2c1" is a label frommpc5200.dtsi*/ rtc@51 {
compatible = "nxp,pcf8563";
reg = <0x51>;
};
eeprom@52 {
compatible = "catalyst,24c32";
reg = <0x52>;
};/* Remove the first i2c bus because it isn't used */ /delete-node/ &i2c0
Quoted 7 lines
/* The watchdog doesn't work, so remove the fsl,has-wdt property */ /cd/ &timer0;
/delete-prop/ fsl,has-wdt;And that's it. I think this covers the functionality that I need. What does everyone think? Are there other important use cases that I should also be addressing?
So the "commands" are interpreted at DTS compile time right? They have no representation in the DTB?
How about support for adding nodes, such as MTD partitions as child nodes of a flash device and so on?
Does inclusion happen only at the root? If so is it meaningful to have multiple includes in a single dts?
Again with the flash partition example, it might be usefiul to include a partitional table .dtsi insidethe flash device node.
Seems overall like a useful functionality, we tend to create tools to tweak the DTS based upon preferences that cannot be expressed to or known by the device tree generator, their needs would be mostly served by what you are proposing I think.
John
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 2 lines · Grant Likely
Okay, I'm going to reach way into the past here and reopen an old argument...
And it's probably about time, too.
[snip]
Quoted 26 lines
Now that I've had about a year and a half to simmer about it, I think I have a counter proposal on a dts syntax extension.
First, I should state the problems I'm trying to solve. I have two use cases that interest me:
1) Multiple boards that use the same SoC.
Right now each dts file carries around the full dts definition, even though 95% of it is 'stock' description of the soc. For example,arch/powerpc/boot/dts/*5200*andarch/powerpc/boot/dts/*8349*. I want a way to put all the common description into an SoC dts file, and then be able to tailor it (add nodes, change properties, etc) for the specific board.2) FPGA designs
The Xilinx FPGA toolchain will generate a dts file to describe a PowerPC or Microblaze FPGA design. However, the generated file is usually not complete. Properties need to be modified (ie. console device or kernel command line) and additional devices need to be added (devices hanging off the i2c, mdio and spi busses, gpio connections). The tool doesn't have a way to tailor the device tree generation, and the FPGA toolchain doesn't know about board level details. I want a way for the developer to write a board-level .dts file that "wraps" or includes the generated file so that it doesn't need to be modified by hand.
Quoted 9 lines
I also have some design goals for the proposed solution. First, I want to avoid design a new programming language. If we need full programmatic generation of device trees, there are plenty of general purpose languages that can do the job. I already know of two existing device tree generators; I wrote a prototype generator written in Python, and the Michal wrote the Xilinx dts generator using TCL. I don't want users to have to learn a new language, and I don't want it to be more complex than is needed to solve the specific use cases. As such, I've got no loops, no macros, and no conditionals.
A good goal. Certainly I think it's preferable to use a device tree generator in an existing good language that to make ourselves a new bad language.
Quoted 7 lines
The model that I'm using to approach the problem is to add syntax for including .dts files (exactly how Jon proposed) and syntax for going back after the tree is parsed and changing things. I'm not an expert on syntax, so I'm open to changes in the details, but this is what I'm thinking. Add the following directives to the syntax:
/include/ Include a file
Uh.. we already have /include/, which works pretty much exactly as you want it to.
Quoted 29 lines
/cd/ Change the 'working node', accepts a full or relative path to a node. Also accepts labels.
/delete-node/ Delete a child node. Similar to /cd/, accepts a full path, a relative path, or a label.
/delete-property/ Delete a property from the working node.So, for example, I might have the following for the
pcm030.dts:/dts-v1/;
/include/mpc5200.dtsi; /* dts include file */
/* at this point the basic structure of an mpc5200 board is layed down *//* Change some properties in the chosen and memory nodes. */ /cd/ /chosen;
linux,stdout-path = &psc1;
/cd/ /memory
reg = <00x10000000>;/* Add some devices to the i2c bus */
/cd/ &i2c1; /* "i2c1" is a label frommpc5200.dtsi*/rtc@51 { compatible = "nxp,pcf8563"; reg = <0x51>; }; eeprom@52 { compatible = "catalyst,24c32"; reg = <0x52>; };
Quoted 6 lines
/* Remove the first i2c bus because it isn't used */ /delete-node/ &i2c0
/* The watchdog doesn't work, so remove the fsl,has-wdt property */ /cd/ &timer0;
/delete-prop/ fsl,has-wdt;
Ok, I quite like the functionality, but I'm not that fond of the syntax. I think I have a similar but neater proposal, at least for the adding-stuff parts. There's two parts to my counter-proposal
1) This is essentially part of your proposal, but I'm separating it out from the /cd/ syntax.
We allow redefinition of properties, nodes, or even the whole device tree. For properties the later definition overrides the earlier. For nodes, or the whole tree, the definitions are merged in the obvious way (again with later property definitions overriding earlier). In this way an include could define a base tree, and you could then define an "overlay" tree which adds things or changes properties where necessary.
Optional extension: because allowing redefinitions potentially allows genuine mistakes to silently generate unexpected output, it might be wise to allow only "weak" definitions, marked somehow, to be overriden. I'm not sure what syntax we'd use for that.
I think (1) fits very naturally into the existing syntax.
2) The trouble with the above is that having included a template device tree, redefining some property deep within it is unpleasantly verbose. You address that with /cd/, which I don't like very much. So my counter proposal is that we allow a path instead of just a name at the beginning of a node definition. This would essentially define an empty node for all the initial path elements, then let the node body define the final path element in the appropriate location. So:
/include/ template.dtsi;
/somebus@XX/someotherbus@XX/i2c@XX/board-control-widget@XXX {
board-specific-property = "whatever";
};Optional extension 1: Give an error if the earlier path components haven't been defined yet (i.e. _don't+ allow implicit mkdir -p like behaviour). I suspect this would rarely to never be an inconvenience, because you don't generally want to define a node with no properties at all, and it would catch some genuine mistakes (like a typo which adds a / to a node name).
Optional extension 2: Allow a node label to be invoked at the beginning of a node redefinition in. That would let include files put labels on the nodes most likely to be extended or overriden, particularly if they're buried deep in the tree and then the necessary redefinitions become less verbose again.
(2) is a bit more problematic syntax-wise. The fact that paths are now possible before the node definition raises some lexical issues. In particular it means the /-surrounded "reserved words" might no longer be clearly lexically distinct from a node definition (I chose to make the reserved words surround by / specifically so that that would be the case). I suspect this is not a fatal problem, but I'll need to think about it some more.
That still leaves node and property deletion to cover. In keeping with the above approach, I'd like to do that in the form of "negative redefinitions" of properties or nodes. A neat syntax for that doesn't immediately occur to be for that yet, though.
Quoted 3 lines
And that's it. I think this covers the functionality that I need. What does everyone think? Are there other important use cases that I should also be addressing?
Probably, but I'm not really sure what they are.
So I think my proposal (1) above accomplishes some of what you want, while being unlikely to badly conflict with any of the various paths we might want to take in the future. So, shall we proceed in that direction while we think about the rest?
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 10 lines · David Gibson
Quoted 7 lines
The model that I'm using to approach the problem is to add syntax for including .dts files (exactly how Jon proposed) and syntax for going back after the tree is parsed and changing things. I'm not an expert on syntax, so I'm open to changes in the details, but this is what I'm thinking. Add the following directives to the syntax:
/include/ Include a file
Uh.. we already have /include/, which works pretty much exactly as you want it to.
Well how about that. I guess we do. I learned something today.
Quoted 7 lines
Ok, I quite like the functionality, but I'm not that fond of the syntax. I think I have a similar but neater proposal, at least for the adding-stuff parts. There's two parts to my counter-proposal
1) This is essentially part of your proposal, but I'm separating it out from the /cd/ syntax.
Quoted 7 lines
We allow redefinition of properties, nodes, or even the whole device tree. For properties the later definition overrides the earlier. For nodes, or the whole tree, the definitions are merged in the obvious way (again with later property definitions overriding earlier). In this way an include could define a base tree, and you could then define an "overlay" tree which adds things or changes properties where necessary.
Yes, I agree with this. It's pretty well describes the functionality that I was thinking about.
Quoted 4 lines
Optional extension: because allowing redefinitions potentially allows genuine mistakes to silently generate unexpected output, it might be wise to allow only "weak" definitions, marked somehow, to be overriden. I'm not sure what syntax we'd use for that.
Examples? I'm not clear on what potential mistakes you're thinking about.
That being said, I could see it potentially being valuable to be able to assign an 'invalid' value to a property so that is *must* get overridden before dtc will generate valid output.
Quoted 1 line
I think (1) fits very naturally into the existing syntax.
I agree. It certainly provides better containment than my /cd/ suggestion.
Quoted 14 lines
2) The trouble with the above is that having included a template device tree, redefining some property deep within it is unpleasantly verbose. You address that with /cd/, which I don't like very much. So my counter proposal is that we allow a path instead of just a name at the beginning of a node definition. This would essentially define an empty node for all the initial path elements, then let the node body define the final path element in the appropriate location. So:
/include/
template.dtsi;/somebus@XX/someotherbus@XX/i2c@XX/board-control-widget@XXX { board-specific-property = "whatever";
};
Quoted 6 lines
Optional extension 1: Give an error if the earlier path components haven't been defined yet (i.e. _don't+ allow implicit mkdir -p like behaviour). I suspect this would rarely to never be an inconvenience, because you don't generally want to define a node with no properties at all, and it would catch some genuine mistakes (like a typo which adds a / to a node name).
Yeah, this sounds reasonable.
Quoted 5 lines
Optional extension 2: Allow a node label to be invoked at the beginning of a node redefinition in. That would let include files put labels on the nodes most likely to be extended or overriden, particularly if they're buried deep in the tree and then the necessary redefinitions become less verbose again.
I think this is absolutely essential. With respect to the FPGA use case, nodes are going to move around, possibly quite a bit as the FPGA design develops. It is critical to have some kind of handle to a node other than the node name or location because they will change. I think this might even be able to be handled as part (3) because it doesn't have the '/' processing issue that part (2) has. For example:
instead of:
/ {
parent@1234 {
child@abcd {
new-property = <0x01234567>;
};
};
};do this:
&child-label {
new-property = <0x01234567>;
};Quoted 7 lines
(2) is a bit more problematic syntax-wise. The fact that paths are now possible before the node definition raises some lexical issues. In particular it means the /-surrounded "reserved words" might no longer be clearly lexically distinct from a node definition (I chose to make the reserved words surround by / specifically so that that would be the case). I suspect this is not a fatal problem, but I'll need to think about it some more.
Actually, as long as I can reference a specific node by label, I don't think I need the ability to pass in the full path. Label provides the functionality I need.
Quoted 4 lines
That still leaves node and property deletion to cover. In keeping with the above approach, I'd like to do that in the form of "negative redefinitions" of properties or nodes. A neat syntax for that doesn't immediately occur to be for that yet, though.
hmmm. I'll think more about it too. I agree that a negative redefinition sounds like a reasonable approach. I do want the ability to drop nodes easily. It would make it easy to handle SoC or FPGA design variants.
Quoted 10 lines
Quoted 3 lines
And that's it. I think this covers the functionality that I need. What does everyone think? Are there other important use cases that I should also be addressing?
Probably, but I'm not really sure what they are.
So I think my proposal (1) above accomplishes some of what you want, while being unlikely to badly conflict with any of the various paths we might want to take in the future. So, shall we proceed in that direction while we think about the rest?
Yeah, I think so. Okay, so how about some examples then of what I think you're describing:
1) Add or modify properties to a node
/include/ "base-tree.dtsi"
/ {
node {
new-property = <0x1234>;
};
};2) Add a new node:
/include/ "base-tree.dtsi"
/ {
parent {
new-child {
new-properties;
};
};
};3) Add a new node with a label:
/include/ "base-tree.dtsi"
/ {
parent {
new-label: new-child {
new-properties;
};
};
};4) add a label to an existing node
/include/ "base-tree.dtsi"
/ {
new-label: existing-node { };
};5) Start from a labeled node instead of the root node:
/include/ "base-tree.dtsi"
&existing-label {
new-property = <0xabcd>;
};Do I have this right?
g.
A message that is not in the archive (sent off-list or not yet received): fa686aa41002212226i4c83376cn8d88a045dd13fe00-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 4 lines
Quoted 3 lines
That still leaves node and property deletion to cover. In keeping with the above approach, I'd like to do that in the form of
"negative
Quoted 8 lines
Quoted 1 line
redefinitions" of properties or nodes. A neat syntax for
that doesn't
Quoted 1 line
immediately occur to be for that yet, though.
hmmm. I'll think more about it too. I agree that a negative redefinition sounds like a reasonable approach. I do want the ability to drop nodes easily. It would make it easy to handle SoC or FPGA design variants.
We had a similar problem in the Freescale Embedded Hypervisor
to control the generation of guest device trees. We defined
several 'magic' properties that had special meaning in the context of a node update.
delete-prop <stringlist> The value identifies one or more names of
properties that should be deleted from the node.
delete-node <stringlist> The value identifies one or more names of
nodes that should be deleted. The node and all descendants will be deleted.
We also had the need to prepend to a <stringlist> so that compatible properties could be updated.
prepend-stringlist <stringlist> The value is a string list that
specifies on or more property name/value pairs.
"prop-name1," "prop-value1,"
"prop-name2," "propvalue2,"
Each name/value pair consists of two strings-the first is the name of the property, the second is a string to prepend to the property. If the property does not already exist it will be created.
Examples
/ {
parent {
child1 {
new-property = "stuff";
delete-prop = "foo", "bar";
};
};
};
/ {
parent {
child1 {
delete-node = "childA", "childB";
};
};
};
/ {
parent {
child1 {
prepend-stringlist = "compatible", "fsl,foo-bar";
};
};
};Regards,
Stuart
A message that is not in the archive (sent off-list or not yet received): 9696D7A991D0824DBA8DFAC74A9C5FA305B2021A-ofAVchDyotYzzZk0BCvKg5jmvxFtTJ+o0e7PPNI6Mm0@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 13 lines · On Mon, Feb 22, 2010 at 9:13 AM, Yoder Stuart-B08248…
Quoted 4 lines
Quoted 3 lines
That still leaves node and property deletion to cover. In keeping with the above approach, I'd like to do that in the form of
"negative
Quoted 8 lines
Quoted 1 line
redefinitions" of properties or nodes. A neat syntax for
that doesn't
Quoted 1 line
immediately occur to be for that yet, though.
hmmm. I'll think more about it too. I agree that a negative redefinition sounds like a reasonable approach. I do want the ability to drop nodes easily. It would make it easy to handle SoC or FPGA design variants.
Quoted 4 lines
We had a similar problem in the Freescale Embedded Hypervisor to control the generation of guest device trees. We defined several 'magic' properties that had special meaning in the context of a node update.
heh, so the functionality is definitely needed, but boy is that ugly! :-) I really do think there needs to be a syntactically distinct method of deleting nodes and properties. Magic property names that look like normal properties worry me.
What about something like this: Right now nodes are defined by <name> { [<property>|<node>]; ... }; and properties are defined by <name>; or <name> = <value>; To differentiate a command from either a node or property definition, perhaps round braces could be used:
so for the definition:
a-node {
property-1;
property-2 = "blah";
child-1 {
...
};
};you could delete property-2 and node-1 with:
a-node {
delete-node(child-1);
delete-property(property-2);
};Quoted 6 lines
We also had the need to prepend to a <stringlist> so that compatible properties could be updated.
prepend-stringlist <stringlist> The value is a string list that specifies on or more property name/value pairs.
This is a bit of a harder problem. I've go no ideas on how to handle this in a syntactically elegant way.
g.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
A message that is not in the archive (sent off-list or not yet received): fa686aa41002221359m4d857e4cn3a1c56c32a24d21d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 8 lines · Grant Likely
On Mon, Feb 22, 2010 at 9:13 AM, Yoder Stuart-B08248
Quoted 4 lines
We had a similar problem in the Freescale Embedded Hypervisor
to control the generation of guest device trees. We defined
several 'magic' properties that had special meaning in the context of a node update.heh, so the functionality is definitely needed, but boy is that ugly! :-)
And we haven't even mentioned node-update-phandle yet. :-)
Quoted 3 lines
I really do think there needs to be a syntactically distinct method of deleting nodes and properties. Magic property names that look like normal properties worry me.
The problem in our case is that the updates have to be done at runtime (modifications contained in a config tree are applied to a hardware devtree node (or hv-generated node) to produce a guest devtree node), so to use something that doesn't look like a normal property would require dtb format changes.
The whole node-update subtree in such a case could be considered magic.
The problem domain of this thread has no such requirement, of course.
Quoted 23 lines
What about something like this: Right now nodes are defined by <name> { [<property>|<node>]; ... }; and properties are defined by <name>; or <name> = <value>; To differentiate a command from either a node or property definition, perhaps round braces could be used:
so for the definition:
a-node { property-1; property-2 = "blah"; child-1 { ... }; };you could delete property-2 and node-1 with:
a-node { delete-node(child-1); delete-property(property-2); };Quoted 3 lines
We also had the need to prepend to a <stringlist> so that compatible properties could be updated.
Quoted 6 lines
Quoted 3 lines
prepend-stringlist <stringlist> The value is a string list that
specifies on or more property name/value pairs.This is a bit of a harder problem. I've go no ideas on how to handle this in a syntactically elegant way.
As long as we're talking about dts-level static manipulation (i.e. not magic properties), we're not limited to one instance of each command name, so we could just do:
prepend-stringlist("compatible", "foo,bar");
prepend-stringlist("compatible", "foo,bar-X.Y");
prepend-stringlist("something-else", "aoeuhtns");
We need the quotes around node/property names since comma is a legal character in them.
-Scott
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 20 lines · Grant Likely
Quoted 13 lines · On Mon, Feb 22, 2010 at 9:13 AM, Yoder Stuart-B08248…
Quoted 4 lines
Quoted 3 lines
That still leaves node and property deletion to cover. In keeping with the above approach, I'd like to do that in the form of
"negative
Quoted 8 lines
Quoted 1 line
redefinitions" of properties or nodes. A neat syntax for
that doesn't
Quoted 1 line
immediately occur to be for that yet, though.
hmmm. I'll think more about it too. I agree that a negative redefinition sounds like a reasonable approach. I do want the ability to drop nodes easily. It would make it easy to handle SoC or FPGA design variants.
Quoted 4 lines
We had a similar problem in the Freescale Embedded Hypervisor to control the generation of guest device trees. We defined several 'magic' properties that had special meaning in the context of a node update.
Quoted 4 lines
heh, so the functionality is definitely needed, but boy is that ugly! :-) I really do think there needs to be a syntactically distinct method of deleting nodes and properties. Magic property names that look like normal properties worry me.
Ah, yeah. However, as Stuart said, the magic properties need to be interpreted at runtime, so in that case it kind of makes sense. What we're discussing here, does have the interesting possibility that we could extend it so that with the right flag set from command line option and/or a special directive in the .dts we could have a mode where instead of immediately processing node and property redefinitions in our new syntax, we instead build them into magic properties in the FEH format. Doubtless there would be some complications, but it's something to think about later, maybe.
Quoted 14 lines
What about something like this: Right now nodes are defined by <name> { [<property>|<node>]; ... }; and properties are defined by <name>; or <name> = <value>; To differentiate a command from either a node or property definition, perhaps round braces could be used:
so for the definition:
a-node { property-1; property-2 = "blah"; child-1 { ... }; };
Quoted 5 lines
you could delete property-2 and node-1 with:
a-node { delete-node(child-1); delete-property(property-2); };
Hrm. I don't particularly like it, but I guess it's an option.
Quoted 9 lines
Quoted 6 lines
We also had the need to prepend to a <stringlist> so that compatible properties could be updated.
prepend-stringlist <stringlist> The value is a string list that specifies on or more property name/value pairs.
This is a bit of a harder problem. I've go no ideas on how to handle this in a syntactically elegant way.
Actually, that I think we can handle relatively neatly. We define a special symbol which can be used in property definitions and expands to the property's previous value. So you could do:
compatible = "newthing", /prev/;
(I don't particularly like '/prev/' as the symbol, but you get the basic idea).
Actually, here's one thought. At present, a reference to a node label expands to the node's full path. I don't think it's too far out of keeping with that for a reference to a property label to expand to the property's value. Then we could have a special form of that which means reference to this property's previous value, instead of explicitly giving a property label. Still not sure what to make the actual symbols.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 39 lines · Grant Likely
Quoted 13 lines · On Mon, Feb 22, 2010 at 9:13 AM, Yoder Stuart-B08248…
Quoted 4 lines
Quoted 3 lines
That still leaves node and property deletion to cover. In keeping with the above approach, I'd like to do that in the form of
"negative
Quoted 8 lines
Quoted 1 line
redefinitions" of properties or nodes. A neat syntax for
that doesn't
Quoted 1 line
immediately occur to be for that yet, though.
hmmm. I'll think more about it too. I agree that a negative redefinition sounds like a reasonable approach. I do want the ability to drop nodes easily. It would make it easy to handle SoC or FPGA design variants.
Quoted 4 lines
We had a similar problem in the Freescale Embedded Hypervisor to control the generation of guest device trees. We defined several 'magic' properties that had special meaning in the context of a node update.
heh, so the functionality is definitely needed, but boy is that ugly! :-) I really do think there needs to be a syntactically distinct method of deleting nodes and properties. Magic property names that look like normal properties worry me.
What about something like this: Right now nodes are defined by <name> { [<property>|<node>]; ... }; and properties are defined by <name>; or <name> = <value>; To differentiate a command from either a node or property definition, perhaps round braces could be used:
so for the definition:
a-node {
property-1;
property-2 = "blah";
child-1 {
...
};
};
Quoted 5 lines
you could delete property-2 and node-1 with:
a-node {
delete-node(child-1);
delete-property(property-2);
};
Okay. So the redefinition of nodes feature got implemented far faster than I expected it would. Woohoo! :-)
That leaves the last bit that I really care about; deleting nodes and properties. I can probably find the time to implement the C code for this, but have no idea how to do the grammer, and I don't think we've got a consensus on syntax.
Given the following tree...
/ {
child-label: child {
prop = <0xbad>;
grandchild-label: grandchild {
};
};
};...here are the use cases that I see as important (plus some suggested syntax. I'm not happy with it though, and I'm open to better ideas).
1) Deleting a property from a node:
&child-label {
/* syntax to delete "prop" property */
delete-prop("prop");
^prop; /* this isn't very good, hard to differentiate from
node deletion */
__delete_property = "prop";
};2) Delete a child node:
&child-label {
/* syntax to delete "grandchild" node */
delete-node("grandchild");
^grandchild;
__delete_node = "grandchild";
grandchild = ^{};
};3) Delete a labelled node from the top level:
delete-node(&grandchild-label);
Comments? Suggestions? Better ideas? Please? Don't inflict pain on yourself by letting me decide the syntax.
g.
A message that is not in the archive (sent off-list or not yet received): fa686aa41003011115m1bb0b644g5014340f6c312ee9-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 39 lines · Grant Likely
Okay. So the redefinition of nodes feature got implemented far faster than I expected it would. Woohoo! :-)
That leaves the last bit that I really care about; deleting nodes and properties. I can probably find the time to implement the C code for this, but have no idea how to do the grammer, and I don't think we've got a consensus on syntax.
Given the following tree...
/ { child-label: child { prop = <0xbad>; grandchild-label: grandchild { }; }; };...here are the use cases that I see as important (plus some suggested syntax. I'm not happy with it though, and I'm open to better ideas).
1) Deleting a property from a node:
&child-label { /* syntax to delete "prop" property */ delete-prop("prop"); ^prop; /* this isn't very good, hard to differentiate from node deletion */ __delete_property = "prop"; };2) Delete a child node:
&child-label { /* syntax to delete "grandchild" node */ delete-node("grandchild"); ^grandchild; __delete_node = "grandchild"; grandchild = ^{}; };
Quoted 2 lines
3) Delete a labelled node from the top level:
delete-node(&grandchild-label);
I vote for the function-like option -- delete-prop("prop"), etc.
-Scott
RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 93 lines
-----Original Message-----
From: devicetree-discuss-bounces+stephen.neuendorffer=xilinx.com@lists.ozlabs.org [mailto:devicetree- discuss-bounces+stephen.neuendorffer=xilinx.com-uLR06cmDAlY/[email protected]] On Behalf Of Grant Likely
Sent: Monday, March 01, 2010 11:16 AM
To: Yoder Stuart-B08248
Cc: Wood Scott-B07421; [email protected]; John Williams; Jeremy Kerr
Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.Quoted 39 lines · Grant Likely
Quoted 13 lines · On Mon, Feb 22, 2010 at 9:13 AM, Yoder Stuart-B08248…
Quoted 4 lines
Quoted 3 lines
That still leaves node and property deletion to cover. In keeping with the above approach, I'd like to do that in the form of
"negative
Quoted 8 lines
Quoted 1 line
redefinitions" of properties or nodes. A neat syntax for
that doesn't
Quoted 1 line
immediately occur to be for that yet, though.
hmmm. I'll think more about it too. I agree that a negative redefinition sounds like a reasonable approach. I do want the ability to drop nodes easily. It would make it easy to handle SoC or FPGA design variants.
Quoted 4 lines
We had a similar problem in the Freescale Embedded Hypervisor to control the generation of guest device trees. We defined several 'magic' properties that had special meaning in the context of a node update.
heh, so the functionality is definitely needed, but boy is that ugly! :-) I really do think there needs to be a syntactically distinct method of deleting nodes and properties. Magic property names that look like normal properties worry me.
What about something like this: Right now nodes are defined by <name> { [<property>|<node>]; ... }; and properties are defined by <name>; or <name> = <value>; To differentiate a command from either a node or property definition, perhaps round braces could be used:
so for the definition:
a-node {
property-1;
property-2 = "blah";
child-1 {
...
};
};Quoted 5 lines
you could delete property-2 and node-1 with:
a-node {
delete-node(child-1);
delete-property(property-2);
};Okay. So the redefinition of nodes feature got implemented far faster than I expected it would. Woohoo! :-)
That leaves the last bit that I really care about; deleting nodes and properties. I can probably find the time to implement the C code for this, but have no idea how to do the grammer, and I don't think we've got a consensus on syntax.
Given the following tree...
/ { child-label: child { prop = <0xbad>; grandchild-label: grandchild { }; }; };...here are the use cases that I see as important (plus some suggested syntax. I'm not happy with it though, and I'm open to better ideas).
1) Deleting a property from a node:
&child-label { /* syntax to delete "prop" property */ delete-prop("prop"); ^prop; /* this isn't very good, hard to differentiate from node deletion */ __delete_property = "prop"; };2) Delete a child node:
&child-label { /* syntax to delete "grandchild" node */ delete-node("grandchild"); ^grandchild; __delete_node = "grandchild"; grandchild = ^{}; };
Quoted 7 lines
3) Delete a labelled node from the top level:
delete-node(&grandchild-label);Comments? Suggestions? Better ideas? Please? Don't inflict pain on yourself by letting me decide the syntax.
g.
One thing I've seen in the past is that there is a sequentialization question in this, which becomes more apparent once deletion is allowed.
First off, my assumption is that each node name is always unique in a tree, even when overrides are allowed. Otherwise the sub-node and property ordering becomes important.
foo {
bar = 2;
bar = 3; // Illegal
} ;foo {
bar = 2;
}
foo {
bar = 3; // Legal
};So, essentially, sequentialization of operation is forced by the concatenation of trees.
Similarly:
foo {
bar-label: bar = 2;
}&bar-label = 3;
delete has the similar problem.
foo {
bar = 2;
delete(bar); // Should be illegal
}foo {
bar-label: bar = 2;
}delete(&bar-label); // Legal.
foo {
bar-label: bar = 4; // Legal, even though previously deleted
}
So, regardless of the syntax, I think it's important to ensure the above checks and sequentiality. There's also a canonicalization question, because you can spit out the original source, or the 'reduction'
which results in all the overrides and deletions. I think from looking at Grant's patch, this is already
the way things work, but I don't think anyone had really explicitly stated that.
One trick is that the below is problematic, or at least hard to verify statically.
foo {
delete(&bar-label); // Legal.
delete(bar); // May or may not be Illegal, since don't know what bar-label references
}So, to syntax: the sequentialization property may be more syntactically obvious if deletion resembles setting a property or node like:
^bar
!bar
or even
bar = !;
bar !;
Which brings up the question 'undeletion question'. Can you do:
d-label: delete(bar);delete(&d-label);
Steve
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
A message that is not in the archive (sent off-list or not yet received): 4B8C2C4C.8070901@freescale <[email protected]
A message that is not in the archive (sent off-list or not yet received): [email protected]
RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 1 line
Quoted 1 line
Quoted 1 line
That raises the question of whether it's legal to delete things
that aren't
Quoted 6 lines
Quoted 6 lines
Quoted 1 line
there.
It isn't currently, which seems sane to me.
Quoted 2 lines
There may be cases where a dts fragment A doesn't know whether
fragment B will have defined something, and fragment A wants to
make sure it
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
ends up undefined one way or another.
Later fragments should always override earlier ones. So if A is defined before B, then B can override anything that A does.
Sorry for the confusing enumeration -- A comes after B.
To put it in more concrete terms, suppose you're writing an update
wrapper
Quoted 1 line
around the autogenerated FPGA dts. In some configurations a given
node/property
Quoted 1 line
will be autogenerated, in others not -- but you want the wrapper to
make sure
Quoted 1 line
it's gone, because it doesn't work with the system the FPGA is
connected to.
Quoted 2 lines
If it's an error to delete something that doesn't exist, you'd have to
have two
Quoted 1 line
update trees, first adding/replacing the thing in question to make
sure it's
Quoted 3 lines
there, and the second to delete it.
Allowing such an operation also lines up better with your suggestion
to think of
Quoted 1 line
it as masking, rather than deleting.
FWIW, I tend to agree with Scott... I find it more natural to think of deletion
as a well-defined total function, rather than as an operation which may fail.
Steve
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
A message that is not in the archive (sent off-list or not yet received): 7c070166-6cd5-48e4-ab8e-cb062e3dbb00-RaUQJvECHiusiP+nND6G/7jjLBE8jN/[email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 31 lines · Stephen Neuendorffer
Quoted 1 line
Quoted 1 line
Quoted 1 line
That raises the question of whether it's legal to delete things
that aren't
Quoted 6 lines
Quoted 6 lines
Quoted 1 line
there.
It isn't currently, which seems sane to me.
Quoted 2 lines
There may be cases where a dts fragment A doesn't know whether
fragment B will have defined something, and fragment A wants tomake sure it
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
ends up undefined one way or another.
Later fragments should always override earlier ones. So if A is defined before B, then B can override anything that A does.
Sorry for the confusing enumeration -- A comes after B.
To put it in more concrete terms, suppose you're writing an update
wrapper
Quoted 1 line
around the autogenerated FPGA dts. In some configurations a given
node/property
Quoted 1 line
will be autogenerated, in others not -- but you want the wrapper to
make sure
Quoted 1 line
it's gone, because it doesn't work with the system the FPGA is
connected to.
Quoted 2 lines
If it's an error to delete something that doesn't exist, you'd have to
have two
Quoted 1 line
update trees, first adding/replacing the thing in question to make
sure it's
Quoted 2 lines
there, and the second to delete it.
Quoted 7 lines
Quoted 1 line
Allowing such an operation also lines up better with your suggestion
to think of
Quoted 1 line
it as masking, rather than deleting.
FWIW, I tend to agree with Scott... I find it more natural to think of deletion as a well-defined total function, rather than as an operation which may fail.
I tend to agree, although I'm not sure that "total function" is quite the right term.
I think the approach that makes the most sense in the context of this "stack of overlays" approach, is to think of "non-existent" as a special type of value (which is different from merely empty, of course). So, deletion is overriding a node or property's existing value with "non-existent".
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 29 lines · Scott Wood
Quoted 25 lines · Grant Likely
Quoted 6 lines · Scott Wood
Hmm, I'd think it would be useful to e.g. include a template and subsequently modify it within the same node, rather than a more verbose and
error-prone process of referencing labels later.Quoted 6 lines
If sequential operations within a tree are supported, I'm not sure that there's any remaining need for separate top-level trees -- you could express
the same thing as top-level property/node redefinitions.What are the problems with supporting this?
The main problem is that it doesn't fit the use cases I need to solve. I need to start with a 'stock' or 'vanilla' tree, and then add into it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
Quoted 2 lines
To reverse the question, what is the use case that is best solved with sequential operations within the root tree?
Quoted 8 lines
The case I had in mind was having includable templates for fragments of the tree, rather than starting with a generic full tree. Though I'd probably end up wanting things like template arguments and math as well (is any existing macro language going to do cell arithmetic?), so the focus on that kind of use case at this point should probably be limited to not defining syntax that's going to make things harder on future language extensions. The only thing that immediately comes to mind from that perspective is that symbols are a more limited resource than keywords.
Right. I thought about that too, and came to the conclusion that while it might be nice to have templates and the like, it isn't as big a deal as handling all the crazy board files duplicating the SoC bits and subtly changing bits all through the tree. At least after the SoC .dts is written, even if it has a lot of similar nodes, it doesn't really need to have bits added or removed from it on a regular basis. And on the FPGA, we've got a real programming language (well, TCL) to do complex tree generation with.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
If you don't reuse the label, but bar is redefined, where does bar-label point?
It doesn't point to anything because when a property is deleted, the label also goes away.
Is it the same way with node labels?
yes
Quoted 1 line
What happens to previous references?
They are either already resolved (in the case of node redefines at the top level), or they will fail.
Quoted 2 lines
Is it detected by dtc, or does a bad phandle/path stick around to be found at runtime? And what if the node is added back?
All phandles are resolved after the tree is fully parsed. This could probably use more thought/discussion to think about the implications.
Quoted 16 lines
Quoted 7 lines
Quoted 4 lines
There may be cases where a dts fragment A doesn't know whether fragment B will have defined something, and fragment A wants to make sure it
ends up undefined one way or another.Later fragments should always override earlier ones. So if A is defined before B, then B can override anything that A does.
Sorry for the confusing enumeration -- A comes after B.
To put it in more concrete terms, suppose you're writing an update wrapper around the autogenerated FPGA dts. In some configurations a given node/property will be autogenerated, in others not -- but you want the wrapper to make sure it's gone, because it doesn't work with the system the FPGA is connected to.
Quoted 6 lines
If it's an error to delete something that doesn't exist, you'd have to have two update trees, first adding/replacing the thing in question to make sure it's there, and the second to delete it.
Allowing such an operation also lines up better with your suggestion to think of it as masking, rather than deleting.
This is a good argument. Let me think about it for a bit, but I think you're probably right.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 21 lines · Scott Wood
Quoted 20 lines · Grant Likely
Quoted 9 lines · Scott Wood
Hmm, I'd think it would be useful to e.g. include a template and subsequently modify it within the same node, rather than a more verbose and error-prone process of referencing labels later.
If sequential operations within a tree are supported, I'm not sure that there's any remaining need for separate top-level trees -- you could express the same thing as top-level property/node redefinitions.
What are the problems with supporting this?
The main problem is that it doesn't fit the use cases I need to solve. I need to start with a 'stock' or 'vanilla' tree, and then add into it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
Quoted 8 lines
Quoted 2 lines
To reverse the question, what is the use case that is best solved with sequential operations within the root tree?
The case I had in mind was having includable templates for fragments of the tree, rather than starting with a generic full tree. Though I'd probably end up wanting things like template arguments and math as well (is any existing macro language going to do cell arithmetic?),
m4 can do arithmetic, but it's pretty hideous. But I still have allowing expressions as a reasonable extension within dtc itself. Macros or templates with parameters raise a lot more complex issues.
[snip]
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
If you don't reuse the label, but bar is redefined, where does bar-label point?
It doesn't point to anything because when a property is deleted, the label also goes away.
Is it the same way with node labels?
Yes, node labels are attached to the node, so if the node is removed, so is the label.
Quoted 3 lines
What happens to previous
references? Is it detected by dtc, or does a bad phandle/path stick around to be found at runtime? And what if the node is added back?
References aren't resolved until the whole tree is built. So references will always resolve to the *last* definition of a label, and if the last "definition" is an undefinition / deletion, then the references will fail to resolve and give an error.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 47 lines · David Gibson
Quoted 21 lines · Scott Wood
Quoted 20 lines · Grant Likely
Quoted 9 lines · Scott Wood
Hmm, I'd think it would be useful to e.g. include a template and subsequently modify it within the same node, rather than a more verbose and error-prone process of referencing labels later.
If sequential operations within a tree are supported, I'm not sure that there's any remaining need for separate top-level trees -- you could express the same thing as top-level property/node redefinitions.
What are the problems with supporting this?
The main problem is that it doesn't fit the use cases I need to solve. I need to start with a 'stock' or 'vanilla' tree, and then add into it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
Quoted 8 lines
Quoted 2 lines
To reverse the question, what is the use case that is best solved with sequential operations within the root tree?
The case I had in mind was having includable templates for fragments of the tree, rather than starting with a generic full tree. Though I'd probably end up wanting things like template arguments and math as well (is any existing macro language going to do cell arithmetic?),
m4 can do arithmetic, but it's pretty hideous. But I still have allowing expressions as a reasonable extension within dtc itself. Macros or templates with parameters raise a lot more complex issues.
[snip]
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
If you don't reuse the label, but bar is redefined, where does bar-label point?
It doesn't point to anything because when a property is deleted, the label also goes away.
Is it the same way with node labels?
Yes, node labels are attached to the node, so if the node is removed, so is the label.
Quoted 8 lines
Quoted 3 lines
What happens to previous
references? Is it detected by dtc, or does a bad phandle/path stick around to be found at runtime? And what if the node is added back?References aren't resolved until the whole tree is built. So references will always resolve to the *last* definition of a label, and if the last "definition" is an undefinition / deletion, then the references will fail to resolve and give an error.
...except for when processing node redefinitions by label in the current patch.
g.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
A message that is not in the archive (sent off-list or not yet received): fa686aa41003011810w2e7b6278t6aaaf192f8d7c8c1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 53 lines · Grant Likely
Quoted 51 lines · David Gibson
Quoted 21 lines · Scott Wood
Quoted 20 lines · Grant Likely
Quoted 9 lines · Scott Wood
Hmm, I'd think it would be useful to e.g. include a template and subsequently modify it within the same node, rather than a more verbose and error-prone process of referencing labels later.
If sequential operations within a tree are supported, I'm not sure that there's any remaining need for separate top-level trees -- you could express the same thing as top-level property/node redefinitions.
What are the problems with supporting this?
The main problem is that it doesn't fit the use cases I need to solve. I need to start with a 'stock' or 'vanilla' tree, and then add into it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
Quoted 8 lines
Quoted 2 lines
To reverse the question, what is the use case that is best solved with sequential operations within the root tree?
The case I had in mind was having includable templates for fragments of the tree, rather than starting with a generic full tree. Though I'd probably end up wanting things like template arguments and math as well (is any existing macro language going to do cell arithmetic?),
m4 can do arithmetic, but it's pretty hideous. But I still have allowing expressions as a reasonable extension within dtc itself. Macros or templates with parameters raise a lot more complex issues.
[snip]
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
If you don't reuse the label, but bar is redefined, where does bar-label point?
It doesn't point to anything because when a property is deleted, the label also goes away.
Is it the same way with node labels?
Yes, node labels are attached to the node, so if the node is removed, so is the label.
Quoted 3 lines
What happens to previous
references? Is it detected by dtc, or does a bad phandle/path stick around to be found at runtime? And what if the node is added back?
Quoted 6 lines
Quoted 4 lines
References aren't resolved until the whole tree is built. So references will always resolve to the *last* definition of a label, and if the last "definition" is an undefinition / deletion, then the references will fail to resolve and give an error.
...except for when processing node redefinitions by label in the current patch.
In fact, I think this has to be the case, otherwise it would be possible to create circular references in node redefiniton.
g.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
A message that is not in the archive (sent off-list or not yet received): fa686aa41003011816j534bf335o6fafe6f1c4a63436-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 59 lines · Grant Likely
Quoted 58 lines · Grant Likely
Quoted 55 lines · David Gibson
Quoted 21 lines · Scott Wood
Quoted 20 lines · Grant Likely
Quoted 9 lines · Scott Wood
Hmm, I'd think it would be useful to e.g. include a template and subsequently modify it within the same node, rather than a more verbose and error-prone process of referencing labels later.
If sequential operations within a tree are supported, I'm not sure that there's any remaining need for separate top-level trees -- you could express the same thing as top-level property/node redefinitions.
What are the problems with supporting this?
The main problem is that it doesn't fit the use cases I need to solve. I need to start with a 'stock' or 'vanilla' tree, and then add into it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
Quoted 8 lines
Quoted 2 lines
To reverse the question, what is the use case that is best solved with sequential operations within the root tree?
The case I had in mind was having includable templates for fragments of the tree, rather than starting with a generic full tree. Though I'd probably end up wanting things like template arguments and math as well (is any existing macro language going to do cell arithmetic?),
m4 can do arithmetic, but it's pretty hideous. But I still have allowing expressions as a reasonable extension within dtc itself. Macros or templates with parameters raise a lot more complex issues.
[snip]
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
If you don't reuse the label, but bar is redefined, where does bar-label point?
It doesn't point to anything because when a property is deleted, the label also goes away.
Is it the same way with node labels?
Yes, node labels are attached to the node, so if the node is removed, so is the label.
Quoted 3 lines
What happens to previous
references? Is it detected by dtc, or does a bad phandle/path stick around to be found at runtime? And what if the node is added back?References aren't resolved until the whole tree is built. So references will always resolve to the *last* definition of a label, and if the last "definition" is an undefinition / deletion, then the references will fail to resolve and give an error.
Quoted 4 lines
Quoted 1 line
...except for when processing node redefinitions by label in the current patch.
In fact, I think this has to be the case, otherwise it would be possible to create circular references in node redefiniton.
Ah, yes. Node redefinition references act in order with the labels. Which is a potentially nasty inconsistency. Ugh.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
A message that is not in the archive (sent off-list or not yet received): fa686aa41002221359m4d857e4cn3a1c56c32a24d21d@mail
<[email protected]
A message that is not in the archive (sent off-list or not yet received): 4288fc0b-79a4-42fd-9e77-573dbad79210-RaUQJvECHiuXHCJdrdq+zrjjLBE8jN/[email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 12 lines · Stephen Neuendorffer
One thing I've seen in the past is that there is a sequentialization question in this, which becomes more apparent once deletion is allowed.
First off, my assumption is that each node name is always unique in a tree, even when overrides are allowed. Otherwise the sub-node and property ordering becomes important.
foo { bar = 2; bar = 3; // Illegal } ;
Quoted 8 lines
foo { bar = 2; } foo { bar = 3; // Legal };So, essentially, sequentialization of operation is forced by the concatenation of trees.
Hmm, I'd think it would be useful to e.g. include a template and subsequently modify it within the same node, rather than a more verbose and error-prone process of referencing labels later.
If sequential operations within a tree are supported, I'm not sure that there's any remaining need for separate top-level trees -- you could express the same thing as top-level property/node redefinitions.
What are the problems with supporting this?
Quoted 7 lines
foo { bar-label: bar = 2; }
delete(&bar-label); // Legal.
foo {
bar-label: bar = 4; // Legal, even though previously deleted
}
Is it legal to reuse the label, even though it sort of points to the same spot?
If you don't reuse the label, but bar is redefined, where does bar-label point?
Do all labels to nodes in separate trees that end up referring to the same node in the final tree have the same phandle? Are they interchangeable in subsequent delete commands?
Quoted 6 lines
One trick is that the below is problematic, or at least hard to verify statically.
foo { delete(&bar-label); // Legal. delete(bar); // May or may not be Illegal, since don't know what bar-label references }
That raises the question of whether it's legal to delete things that aren't there. There may be cases where a dts fragment A doesn't know whether fragment B will have defined something, and fragment A wants to make sure it ends up undefined one way or another.
Quoted 8 lines
So, to syntax: the sequentialization property may be more syntactically obvious if deletion resembles setting a property or node like:
^bar
!bar
or even
bar = !;
bar !;
What specifically is made more obvious? Using symbols rather than names seems more cryptic to me.
Only the "bar = !" form seems to clearly indicate that, for the purposes of this particular tree, you're assigning some special placeholder to bar rather than performing an immediate action. That could just as well be done with something like "bar = /delete-prop/".
I'd rather make them actually behave like immediate commands, though.
Quoted 4 lines
Which brings up the question 'undeletion question'. Can you do:
d-label: delete(bar);
delete(&d-label);
I'd say no -- delete operates on data, not commands.
-Scott
A message that is not in the archive (sent off-list or not yet received): [email protected]
RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 7 lines
-----Original Message-----
From: Scott Wood [mailto:[email protected]]
Sent: Monday, March 01, 2010 1:06 PM
To: Stephen Neuendorffer
Cc: grant.likely-s3s/[email protected]; Yoder Stuart-B08248; Wood Scott-B07421;
Quoted 2 lines
John Williams; Jeremy Kerr
Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS
language.
Quoted 3 lines
Quoted 1 line · Stephen Neuendorffer
One thing I've seen in the past is that there is a sequentialization
question in this, which becomes
Quoted 3 lines
Quoted 3 lines
more apparent once deletion is allowed.
First off, my assumption is that each node name is always unique in
a tree, even when overrides are
Quoted 18 lines
allowed.
Quoted 17 lines
Otherwise the sub-node and property ordering becomes important.
foo { bar = 2; bar = 3; // Illegal } ;foo { bar = 2; } foo { bar = 3; // Legal };So, essentially, sequentialization of operation is forced by the
concatenation of trees.
Quoted 2 lines
Hmm, I'd think it would be useful to e.g. include a template and
subsequently
Quoted 1 line
modify it within the same node, rather than a more verbose and
error-prone
Quoted 3 lines
process of referencing labels later.
If sequential operations within a tree are supported, I'm not sure
that there's
Quoted 1 line
any remaining need for separate top-level trees -- you could express
the same
Quoted 1 line
thing as top-level property/node redefinitions.
I agree, *IF* sequential operations are supported.
But then you have a sequential programming language, not a structured data
description. I think this is a bad idea.
Quoted 1 line
What are the problems with supporting this?
Mainly the fact that properties and sub-nodes have a semantically important ordering.
This can be done, but it's not as clean.
Quoted 9 lines
Quoted 7 lines
foo { bar-label: bar = 2; }
delete(&bar-label); // Legal.
foo {
bar-label: bar = 4; // Legal, even though previously deleted
}Is it legal to reuse the label, even though it sort of points to the
same spot?
Quoted 2 lines
If you don't reuse the label, but bar is redefined, where does
bar-label point?
Quoted 2 lines
Do all labels to nodes in separate trees that end up referring to the
same node
Quoted 1 line
in the final tree have the same phandle? Are they interchangeable in
subsequent
Quoted 1 line
delete commands?
I think these are all good questions which someone who has a much better grasp of the
intention of labels probably has to answer. Since they are somewhat separate from the point
I was trying to show with the example (and as Grant replied, my examples are perhaps poorly
formed anyway), I'm just going to duck them.
Quoted 1 line
Quoted 1 line
One trick is that the below is problematic, or at least hard to
verify statically.
Quoted 4 lines
Quoted 4 lines
foo { delete(&bar-label); // Legal. delete(bar); // May or may not be Illegal, since don't know what
bar-label references
Quoted 3 lines
Quoted 1 line
}
That raises the question of whether it's legal to delete things that
aren't
Quoted 1 line
there. There may be cases where a dts fragment A doesn't know whether
fragment
Quoted 1 line
B will have defined something, and fragment A wants to make sure it
ends up
Quoted 1 line
undefined one way or another.
Yes... A very good question. I would say that it could probably be either way
without screwing things up too badly.
Quoted 1 line
Quoted 1 line
So, to syntax: the sequentialization property may be more
syntactically obvious if deletion
Quoted 10 lines
resembles
Quoted 7 lines
setting a property or node like:
^bar
!bar
or even
bar = !;
bar !;What specifically is made more obvious? Using symbols rather than
names seems
Quoted 3 lines
more cryptic to me.
Only the "bar = !" form seems to clearly indicate that, for the
purposes of this
Quoted 1 line
particular tree, you're assigning some special placeholder to bar
rather than
Quoted 1 line
performing an immediate action. That could just as well be done with
something
Quoted 3 lines
like "bar = /delete-prop/".
I'd rather make them actually behave like immediate commands, though.
But the question is, what is the semantics of the 'command language' (where ordering matters)
from the 'structure language' (where ordering is unimportant). My suggestion is to cleanly separate
these two. The only ordering that is defined is between sequential trees. Within a sequential tree,
only things which have the same meaning in any ordering of sub-nodes and properties should be allowed.
Quoted 6 lines
Quoted 4 lines
Which brings up the question 'undeletion question'. Can you do:
d-label: delete(bar);
delete(&d-label);I'd say no -- delete operates on data, not commands.
This implies that data and commands are different. And commands have to be ordered, which means that you have
to keep the order of everything under a node, which chucks alot of the beauty of device trees, IMHO.
Steve
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
A message that is not in the archive (sent off-list or not yet received): 4d16ecf4-27b2-4c73-a3be-5b2a8ff95820-+Ck8Kgl/v0+J1bAq5m18RLjjLBE8jN/[email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 11 lines · Stephen Neuendorffer
From: Scott Wood [mailto:[email protected]]
Quoted 1 line
If sequential operations within a tree are supported, I'm not sure
that there's
Quoted 1 line
any remaining need for separate top-level trees -- you could express
the same
Quoted 1 line
thing as top-level property/node redefinitions.
I agree, *IF* sequential operations are supported.
But then you have a sequential programming language, not a structured data
description. I think this is a bad idea.
Indeed. We've got lots of sequential programming languages. I don't want us to create for ourselves a new (and poorly implemented) language.
Quoted 10 lines
Quoted 1 line
I'd rather make them actually behave like immediate commands, though.
But the question is, what is the semantics of the 'command language' (where ordering matters)
from the 'structure language' (where ordering is unimportant). My suggestion is to cleanly separate
these two. The only ordering that is defined is between sequential trees. Within a sequential tree,
only things which have the same meaning in any ordering of sub-nodes and properties should be allowed.
Yes, I think I agree with this. The only ordering that matters is the ordering of top level node redefinition blocks.
Quoted 11 lines
Quoted 6 lines
Quoted 4 lines
Which brings up the question 'undeletion question'. Can you do:
d-label: delete(bar);
delete(&d-label);I'd say no -- delete operates on data, not commands.
This implies that data and commands are different. And commands have to be ordered, which means that you have
to keep the order of everything under a node, which chucks alot of the beauty of device trees, IMHO.
Right, well said. I think the right thing to do is to avoid the concept of commands entirely from the tree.
g.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
A message that is not in the archive (sent off-list or not yet received): fa686aa41003011425i734ee434m95b62d57a271bd1f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 9 lines · Grant Likely
Quoted 7 lines · Stephen Neuendorffer
From: Scott Wood [mailto:[email protected]]
Quoted 1 line
If sequential operations within a tree are supported, I'm not sure
that there's
Quoted 1 line
any remaining need for separate top-level trees -- you could express
the same
Quoted 1 line
thing as top-level property/node redefinitions.
Quoted 8 lines
Quoted 4 lines
I agree, *IF* sequential operations are supported.
But then you have a sequential programming language, not a structured data
description. I think this is a bad idea.Indeed. We've got lots of sequential programming languages. I don't want us to create for ourselves a new (and poorly implemented) language.
I agree that we don't want to turn this into a procedural programming language. On the other hand, there is plenty of precedent for declarative languages where order of declarations remains important for deciding which takes precedence.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 30 lines · Scott Wood
Quoted 22 lines · Stephen Neuendorffer
One thing I've seen in the past is that there is a sequentialization question in this, which becomes
more apparent once deletion is allowed.First off, my assumption is that each node name is always unique in a tree, even when overrides are allowed.
Otherwise the sub-node and property ordering becomes important.foo {
bar = 2;
bar = 3; // Illegal
} ;foo {
bar = 2;
} foo {
bar = 3; // Legal
};Quoted 2 lines
So, essentially, sequentialization of operation is forced by the concatenation of trees.
Hmm, I'd think it would be useful to e.g. include a template and subsequently modify it within the same node, rather than a more verbose and error-prone process of referencing labels later.
Quoted 5 lines
If sequential operations within a tree are supported, I'm not sure that there's any remaining need for separate top-level trees -- you could express the same thing as top-level property/node redefinitions.
What are the problems with supporting this?
The main problem is that it doesn't fit the use cases I need to solve.
I need to start with a 'stock' or 'vanilla' tree, and then add into
it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
To reverse the question, what is the use case that is best solved with sequential operations within the root tree?
Quoted 10 lines
Quoted 7 lines
foo {
bar-label: bar = 2;
}delete(&bar-label); // Legal.
foo {
bar-label: bar = 4; // Legal, even though previously deleted }Is it legal to reuse the label, even though it sort of points to the same spot?
In the overlay model that is currently being approached. Yes.
Quoted 2 lines
If you don't reuse the label, but bar is redefined, where does bar-label point?
It doesn't point to anything because when a property is deleted, the label also goes away.
Quoted 3 lines
Do all labels to nodes in separate trees that end up referring to the same node in the final tree have the same phandle? Are they interchangeable in subsequent delete commands?
Yes.
Quoted 11 lines
Quoted 8 lines
One trick is that the below is problematic, or at least hard to verify statically.
foo {
delete(&bar-label); // Legal.
delete(bar); // May or may not be Illegal, since don't know what bar-label references
}That raises the question of whether it's legal to delete things that aren't there.
It isn't currently, which seems sane to me.
Quoted 3 lines
There may be cases where a dts fragment A doesn't know whether fragment B will have defined something, and fragment A wants to make sure it ends up undefined one way or another.
Later fragments should always override earlier ones. So if A is defined before B, then B can override anything that A does.
Quoted 18 lines
Quoted 9 lines
So, to syntax: the sequentialization property may be more syntactically obvious if deletion resembles
setting a property or node like:^bar
!bar
or even
bar = !;
bar !;What specifically is made more obvious? Using symbols rather than names seems more cryptic to me.
Only the "bar = !" form seems to clearly indicate that, for the purposes of this particular tree, you're assigning some special placeholder to bar rather than performing an immediate action. That could just as well be done with something like "bar = /delete-prop/".
Quoted 8 lines
I'd rather make them actually behave like immediate commands, though.
Quoted 4 lines
Which brings up the question 'undeletion question'. Can you do:
d-label: delete(bar);
delete(&d-label);I'd say no -- delete operates on data, not commands.
Yes, I agree. However, the command() syntax may be a bad idea if following the 'stack of overlays' model to its logical conclusion. In a sense, properties and nodes are getting masked out of the earlier tree, not deleted. It is more of an operation (mask) than a command (delete) being applied. delete-node() may give the misleading impression that something is being executed at that point in the tree.
g.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
A message that is not in the archive (sent off-list or not yet received): fa686aa41003011418x339884c9md61c49948b31a8d1-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 47 lines
-----Original Message-----
From: glikely-s3s/[email protected] [mailto:glikely-s3s/[email protected]] On Behalf Of Grant Likely
Sent: Monday, March 01, 2010 2:19 PM
To: Scott Wood
Cc: Stephen Neuendorffer; Yoder Stuart-B08248; Wood Scott-B07421; [email protected]; John Williams; Jeremy Kerr
Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.Quoted 30 lines · Scott Wood
Quoted 22 lines · Stephen Neuendorffer
One thing I've seen in the past is that there is a sequentialization question in this, which becomes
more apparent once deletion is allowed.First off, my assumption is that each node name is always unique in a tree, even when overrides are allowed.
Otherwise the sub-node and property ordering becomes important.foo {
bar = 2;
bar = 3; // Illegal
} ;foo {
bar = 2;
} foo {
bar = 3; // Legal
};Quoted 2 lines
So, essentially, sequentialization of operation is forced by the concatenation of trees.
Hmm, I'd think it would be useful to e.g. include a template and subsequently modify it within the same node, rather than a more verbose and error-prone process of referencing labels later.
Quoted 5 lines
If sequential operations within a tree are supported, I'm not sure that there's any remaining need for separate top-level trees -- you could express the same thing as top-level property/node redefinitions.
What are the problems with supporting this?
Quoted 8 lines
The main problem is that it doesn't fit the use cases I need to solve.
I need to start with a 'stock' or 'vanilla' tree, and then add into
it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
Aside: I always pictured this the other way round, where the DTS for an FPGA design includes the DTS for the board. Then again, as long as they are independent, it probably doesn't matter.
Quoted 40 lines
To reverse the question, what is the use case that is best solved with sequential operations within the root tree?
Quoted 10 lines
Quoted 7 lines
foo {
bar-label: bar = 2;
}delete(&bar-label); // Legal.
foo {
bar-label: bar = 4; // Legal, even though previously deleted }Is it legal to reuse the label, even though it sort of points to the same spot?
In the overlay model that is currently being approached. Yes.
Quoted 2 lines
If you don't reuse the label, but bar is redefined, where does bar-label point?
It doesn't point to anything because when a property is deleted, the label also goes away.
Quoted 3 lines
Do all labels to nodes in separate trees that end up referring to the same node in the final tree have the same phandle? Are they interchangeable in subsequent delete commands?
Yes.
Quoted 11 lines
Quoted 8 lines
One trick is that the below is problematic, or at least hard to verify statically.
foo {
delete(&bar-label); // Legal.
delete(bar); // May or may not be Illegal, since don't know what bar-label references
}That raises the question of whether it's legal to delete things that aren't there.
Quoted 8 lines
It isn't currently, which seems sane to me.
Quoted 3 lines
There may be cases where a dts fragment A doesn't know whether fragment B will have defined something, and fragment A wants to make sure it ends up undefined one way or another.
Later fragments should always override earlier ones. So if A is defined before B, then B can override anything that A does.
So the idiom to do this safely would be:
foo {
bar {} // Ensure that bar exists.
}
foo {
delete(bar);
}Seems baroque, but OK...
Quoted 25 lines
Quoted 25 lines
Quoted 9 lines
So, to syntax: the sequentialization property may be more syntactically obvious if deletion resembles
setting a property or node like:^bar
!bar
or even
bar = !;
bar !;What specifically is made more obvious? Using symbols rather than names seems more cryptic to me.
Only the "bar = !" form seems to clearly indicate that, for the purposes of this particular tree, you're assigning some special placeholder to bar rather than performing an immediate action. That could just as well be done with something like "bar = /delete-prop/".
I'd rather make them actually behave like immediate commands, though.
Quoted 4 lines
Which brings up the question 'undeletion question'. Can you do:
d-label: delete(bar);
delete(&d-label);
Quoted 8 lines
Quoted 1 line
I'd say no -- delete operates on data, not commands.
Yes, I agree. However, the
command()syntax may be a bad idea if following the 'stack of overlays' model to its logical conclusion. In a sense, properties and nodes are getting masked out of the earlier tree, not deleted. It is more of an operation (mask) than a command (delete) being applied. delete-node() may give the misleading impression that something is being executed at that point in the tree.
Regardless of what the syntax is, if the *semantics* is overlay, then there doesn't seem to be any reason to disallow undeletion, and in fact, this semantics gives a way to implement it. I'll defer whether this is *needed*: In the case of device trees it's not clear that it is.
Steve
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
A message that is not in the archive (sent off-list or not yet received): 1012f9aa-1642-41ab-b8cd-a4ab4a7b269e-+Ck8Kgl/v0989VwWyyPjfbjjLBE8jN/[email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 56 lines · Stephen Neuendorffer
Quoted 47 lines
-----Original Message-----
From: glikely-s3s/[email protected] [mailto:glikely-s3s/[email protected]] On Behalf Of Grant Likely
Sent: Monday, March 01, 2010 2:19 PM
To: Scott Wood
Cc: Stephen Neuendorffer; Yoder Stuart-B08248; Wood Scott-B07421; [email protected]; John Williams; Jeremy Kerr
Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.Quoted 30 lines · Scott Wood
Quoted 22 lines · Stephen Neuendorffer
One thing I've seen in the past is that there is a sequentialization question in this, which becomes
more apparent once deletion is allowed.First off, my assumption is that each node name is always unique in a tree, even when overrides are allowed.
Otherwise the sub-node and property ordering becomes important.foo {
bar = 2;
bar = 3; // Illegal
} ;foo {
bar = 2;
} foo {
bar = 3; // Legal
};Quoted 2 lines
So, essentially, sequentialization of operation is forced by the concatenation of trees.
Hmm, I'd think it would be useful to e.g. include a template and subsequently modify it within the same node, rather than a more verbose and error-prone process of referencing labels later.
Quoted 5 lines
If sequential operations within a tree are supported, I'm not sure that there's any remaining need for separate top-level trees -- you could express the same thing as top-level property/node redefinitions.
What are the problems with supporting this?
Quoted 8 lines
The main problem is that it doesn't fit the use cases I need to solve. I need to start with a 'stock' or 'vanilla' tree, and then add into it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
Quoted 3 lines
Aside: I always pictured this the other way round, where the DTS for an FPGA design includes the DTS for the board. Then again, as long as they are independent, it probably doesn't matter.
Heh, interesting. Yeah, I suppose it could be done that way too. The /include/ directive works pretty much anywhere in the input file, so a file could either lay down a structure and then include a modifer, or include a structure and then modify it. I was thinking in terms of the board file including the FPGA file because it matches the pattern for say an SoC where there would be a common SoC .dts file and all the boards using that SoC would include it.
Also, I was thinking that the SoC or FPGA structure needs to be layed down first so that the board file has nodes in the tree to anchor new nodes to. For example, the FPGA's i2c controller needs to be in place so that i2c devices can be grafted onto it.
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
There may be cases where a dts fragment A doesn't know whether fragment B will have defined something, and fragment A wants to make sure it ends up undefined one way or another.
Later fragments should always override earlier ones. So if A is defined before B, then B can override anything that A does.
So the idiom to do this safely would be:
Quoted 8 lines
foo {
bar {} // Ensure that bar exists.
}
foo {
delete(bar);
}Seems baroque, but OK...
Just to make sure I understand you, what bit is striking you as baroque? The bit about the node needing to exist before it can be deleted?
Scott does make a good point in one of his emails, especially within the 'stack of overlays' model. Maybe it should be perfectly fine to mask a node or property, regardless of whether or not it exists in the previous tree. Maybe this should be just fine:
foo {
};
foo {
mask-node(bar);
};Quoted 10 lines
Quoted 5 lines
following the 'stack of overlays' model to its logical conclusion. In a sense, properties and nodes are getting masked out of the earlier tree, not deleted. It is more of an operation (mask) than a command (delete) being applied. delete-node() may give the misleading impression that something is being executed at that point in the tree.
Regardless of what the syntax is, if the *semantics* is overlay, then there doesn't seem to be any reason to disallow undeletion, and in fact, this semantics gives a way to implement it. I'll defer whether this is *needed*: In the case of device trees it's not clear that it is.
The only reason is a practical one. The way the node redefinitions are currently processed makes this difficult. dtc fully processes and resolves a node definition before moving on to the next one. The data is already gone by the time any kind of undelete occurs (but a new node which the same name can certainly be created).
With my current love affair of wanting to know the use-case before committing to a feature, I'd like to know where undelete would be used before doing the rework required to implement it.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
A message that is not in the archive (sent off-list or not yet received): fa686aa41003011603w12c0a7f1y88b5fc7a008af1d5-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 13 lines
Quoted 9 lines
Quoted 8 lines
The main problem is that it doesn't fit the use cases I need to solve. I need to start with a 'stock' or 'vanilla' tree, and then add into it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
Quoted 3 lines
Aside: I always pictured this the other way round, where the DTS for an FPGA design includes the DTS for the board. Then again, as long as they are independent, it probably doesn't matter.
Quoted 7 lines
Heh, interesting. Yeah, I suppose it could be done that way too. The /include/ directive works pretty much anywhere in the input file, so a file could either lay down a structure and then include a modifer, or include a structure and then modify it. I was thinking in terms of the board file including the FPGA file because it matches the pattern for say an SoC where there would be a common SoC .dts file and all the boards using that SoC would include it.
Yeah, but in FPGA, the board is likely to be more stable than the FPGA design... :) Or maybe 'some' FPGA designs are that way and others are not.
Quoted 4 lines
Also, I was thinking that the SoC or FPGA structure needs to be layed down first so that the board file has nodes in the tree to anchor new nodes to. For example, the FPGA's i2c controller needs to be in place so that i2c devices can be grafted onto it.
Hmm... I think we should try it and make sure that things will work...
I started to make a 'test case' based on a real system, but all the
device trees I have lying around are moldy and full of dry rot. I think it should be able to work either way...
Quoted 16 lines
Quoted 16 lines
Quoted 6 lines
Quoted 3 lines
There may be cases where a dts fragment A doesn't know whether fragment B will have defined something, and fragment A wants to make sure it ends up undefined one way or another.
Later fragments should always override earlier ones. So if A is defined before B, then B can override anything that A does.
So the idiom to do this safely would be:
foo {
bar {} // Ensure that bar exists.
}
foo {
delete(bar);
}
Quoted 5 lines
Quoted 1 line
Seems baroque, but OK...
Just to make sure I understand you, what bit is striking you as baroque? The bit about the node needing to exist before it can be deleted?
Yes, since there is a bizarre workaround I show above, which basically ensures that the error never occurs.
Quoted 9 lines
Scott does make a good point in one of his emails, especially within the 'stack of overlays' model. Maybe it should be perfectly fine to mask a node or property, regardless of whether or not it exists in the previous tree. Maybe this should be just fine:
foo {
};foo { mask-node(bar); };
Yes... I think this should just be allowed... or at the very least I don't see a reason to make this an error... It does occur to me that it might be useful to explicitly note the 'extension' of a previous node, which asserts that it *must* exist. i.e.
foo {
bar + {
bar = 3;
}
}Here it is explicitly clear that bar is an incomplete definition?
Steve
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
A message that is not in the archive (sent off-list or not yet received): f9885aa5-5c11-4118-9980-f17378d7cbd5-RaUQJvECHiuXHCJdrdq+zrjjLBE8jN/[email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
On Mon, Mar 01, 2010 at 04:13:30PM -0800, Stephen Neuendorffer wrote:
[snip]
Quoted 5 lines
Yes... I think this should just be allowed... or at the very least I don't see a reason to make this an error... It does occur to me that it might be useful to explicitly note the 'extension' of a previous node, which asserts that it *must* exist. i.e.
Quoted 7 lines
foo { bar + { bar = 3; } }Here it is explicitly clear that bar is an incomplete definition?
Hrm, interesting idea, and one that could have some merit. However, that specific syntax won't work, since '+' is a valid character in node and property names.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 21 lines · Stephen Neuendorffer
Quoted 13 lines
Quoted 9 lines
Quoted 8 lines
The main problem is that it doesn't fit the use cases I need to solve. I need to start with a 'stock' or 'vanilla' tree, and then add into it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
Quoted 3 lines
Aside: I always pictured this the other way round, where the DTS for an FPGA design includes the DTS for the board. Then again, as long as they are independent, it probably doesn't matter.
Quoted 7 lines
Heh, interesting. Yeah, I suppose it could be done that way too. The /include/ directive works pretty much anywhere in the input file, so a file could either lay down a structure and then include a modifer, or include a structure and then modify it. I was thinking in terms of the board file including the FPGA file because it matches the pattern for say an SoC where there would be a common SoC .dts file and all the boards using that SoC would include it.
Quoted 2 lines
Yeah, but in FPGA, the board is likely to be more stable than the FPGA design... :) Or maybe 'some' FPGA designs are that way and others are not.
Ah, but even the board file has to change depending on the FPGA design, and nodes will move around depending on the FPGA internal bus structure, but I understand what you're saying. This is why being able to redefine labelled nodes is a critical feature. For instance, the following isn't actually very useful because it assumes knowledge of the exact location of the i2c bus node:
/ {
plb@0 {
ranges;
i2c@c0000000 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0xc0000000 0x1000>;
};
};
};/ {
plb@0 {
i2c@c0000000 {
rtc@0 {
reg = <0>;
};
eeprom@1 {
reg = <1>;
};
};
};
};However, the following is really useful because the xilinx toolchain already generates the device labels, and the i2c node can move without breaking the board devices:
/ {
plb@0 {
ranges;
i2c-bus-0: i2c@c0000000 {
#address-cells = <1>;
#size-cells = <1>;
reg = <0xc0000000 0x1000>;
};
};
};&i2c-bus-0 {
rtc@0 {
reg = <0>;
};
eeprom@1 {
reg = <1>;
};
};And this way the Platform Studio toolchain doesn't need to be taught anything about the board layout. A board file could look something like this:
/include/ "fpga-design-file.dts"
&i2c-bus-0 {
rtc@0 {
reg = <0>;
};
eeprom@1 {
reg = <1>;
};
};Now, if we're talking about Xilinx eval boards, I can see the argument for having a stock file like ml507.dts, and then a project .dts file might look something like this:
/include/ "fpga-design-file.dts"
/* Map between FPGA device names and ML507 board file labels by applying the ml507 labels to the nodes from the FPGA file */
ml507-i2c-bus-0: &fpga-i2c-bus-0 { };
ml507-i2c-bus-1: &fpga-i2c-bus-1 { };
/include/ "ml507.dts"
This needs new syntax of course, but you get the idea, and it doesn't require teaching the FPGA toochain all kinds of details about the board or project files.
Quoted 5 lines
Yes... I think this should just be allowed... or at the very least I don't see a reason to make this an error... It does occur to me that it might be useful to explicitly note the 'extension' of a previous node, which asserts that it *must* exist. i.e.
Quoted 7 lines
foo {
bar + {
bar = 3;
}
}Here it is explicitly clear that bar is an incomplete definition?
hmmm... I don't think I like this so much, and I don't yet see a use case where this is really a required feature.
g.
A message that is not in the archive (sent off-list or not yet received): fa686aa41003011808h586e3dc3x11ef14af9c6e5fb8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 11 lines · Grant Likely
Quoted 11 lines
Yes... I think this should just be allowed... or at the very least I don't see a reason to make this an error... It does occur to me that it might be useful to explicitly note the 'extension' of a previous node, which asserts that it *must* exist. i.e.
foo {
bar + {
bar = 3;
}
}
Quoted 4 lines
Quoted 1 line
Here it is explicitly clear that bar is an incomplete definition?
hmmm... I don't think I like this so much, and I don't yet see a use case where this is really a required feature.
I could see it being useful if instead of being an error if bar (the node) doesn't already exist, it is ignored. In other words, "if there is a bar, add this property to it, but don't create a new bar just for me".
-Scott
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 20 lines · Grant Likely
Quoted 9 lines · Scott Wood
Hmm, I'd think it would be useful to e.g. include a template and subsequently modify it within the same node, rather than a more verbose and error-prone process of referencing labels later.
If sequential operations within a tree are supported, I'm not sure that there's any remaining need for separate top-level trees -- you could express the same thing as top-level property/node redefinitions.
What are the problems with supporting this?
The main problem is that it doesn't fit the use cases I need to solve.
I need to start with a 'stock' or 'vanilla' tree, and then add into
it board details. ie. lay down a generic MPC5200 tree (include a .dts file), and then fill it in with i2c and spi devices. Or include the .dts file generated by the XIlinx FPGA toolchain, and then populate it with board details. Sequential operations within the tree doesn't do anything to support this use case because the board level fixups will be applied all over the tree.
Quoted 2 lines
To reverse the question, what is the use case that is best solved with sequential operations within the root tree?
The case I had in mind was having includable templates for fragments of the tree, rather than starting with a generic full tree. Though I'd probably end up wanting things like template arguments and math as well (is any existing macro language going to do cell arithmetic?), so the focus on that kind of use case at this point should probably be limited to not defining syntax that's going to make things harder on future language extensions. The only thing that immediately comes to mind from that perspective is that symbols are a more limited resource than keywords.
Quoted 10 lines
Quoted 9 lines
Quoted 7 lines
foo { bar-label: bar = 2; }
delete(&bar-label); // Legal.
foo {
bar-label: bar = 4; // Legal, even though previously deleted
}Is it legal to reuse the label, even though it sort of points to the same spot?
Quoted 7 lines
In the overlay model that is currently being approached. Yes.
Quoted 2 lines
If you don't reuse the label, but bar is redefined, where does bar-label point?
It doesn't point to anything because when a property is deleted, the label also goes away.
Is it the same way with node labels? What happens to previous references? Is it detected by dtc, or does a bad phandle/path stick around to be found at runtime? And what if the node is added back?
Quoted 11 lines
Quoted 10 lines
Quoted 8 lines
One trick is that the below is problematic, or at least hard to verify statically.
foo {
delete(&bar-label); // Legal.
delete(bar); // May or may not be Illegal, since don't know what
bar-label references
}That raises the question of whether it's legal to delete things that aren't there.
Quoted 8 lines
It isn't currently, which seems sane to me.
Quoted 3 lines
There may be cases where a dts fragment A doesn't know whether
fragment B will have defined something, and fragment A wants to make sure it ends up undefined one way or another.Later fragments should always override earlier ones. So if A is defined before B, then B can override anything that A does.
Sorry for the confusing enumeration -- A comes after B.
To put it in more concrete terms, suppose you're writing an update wrapper around the autogenerated FPGA dts. In some configurations a given node/property will be autogenerated, in others not -- but you want the wrapper to make sure it's gone, because it doesn't work with the system the FPGA is connected to.
If it's an error to delete something that doesn't exist, you'd have to have two update trees, first adding/replacing the thing in question to make sure it's there, and the second to delete it.
Allowing such an operation also lines up better with your suggestion to think of it as masking, rather than deleting.
-Scott
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveHi Stephen, good comments...
Quoted 37 lines · Stephen Neuendorffer
Quoted 37 lines
Given the following tree...
/ {
child-label: child {
prop = <0xbad>;
grandchild-label: grandchild {
};
};
};...here are the use cases that I see as important (plus some suggested syntax. I'm not happy with it though, and I'm open to better ideas).
1) Deleting a property from a node:
&child-label {
/* syntax to delete "prop" property */ delete-prop("prop");
^prop; /* this isn't very good, hard to differentiate from node deletion */
__delete_property= "prop";
};2) Delete a child node:
&child-label {
/* syntax to delete "grandchild" node */
delete-node("grandchild");
^grandchild;
__delete_node= "grandchild";
grandchild = ^{};
};3) Delete a labelled node from the top level:
delete-node(&grandchild-label);Comments? Suggestions? Better ideas? Please? Don't inflict pain on yourself by letting me decide the syntax.
Quoted 7 lines
Quoted 1 line
g.
One thing I've seen in the past is that there is a sequentialization question in this, which becomes more apparent once deletion is allowed.
First off, my assumption is that each node name is always unique in a tree, even when overrides are allowed. Otherwise the sub-node and property ordering becomes important.
Yes, multiple sibling nodes with the same name are not allowed by dtc.
I believe multiple siblings of the same name is legal with
OpenFirmware, but that is at least partially because in OpenFirmware the @<addr> portion isn't necessarily part of the name. (Imagine having triplets and naming them Sally@1, Sally@2 and Sally@3!)
However, the same name can be used by non-siblings. For example, the following is totally legal:
/ {
foo {
foo {
};
};
};Quoted 14 lines
foo {
bar = 2;
bar = 3; // Illegal
} ;foo {
bar = 2;
}
foo {
bar = 3; // Legal
};
Quoted 1 line
So, essentially, sequentialization of operation is forced by the concatenation of trees.
Yes, you are exactly correct. The model is to fully form 2 trees, and then overlay the latter on the former.
Quoted 6 lines
Similarly:
foo {
bar-label: bar = 2;
}
&bar-label = 3;
This actually isn't legal, but for an entirely different reason. Even though labels can be applied to properties, property labels aren't actually used for anything unless asm output is selected. All tree modification as of now is done from the context of nodes. Redefinition can start from the root node, or it can start from a labelled node, but there is no syntax defined for modifying a labelled property.
It is possible to add redefinition of labelled properties, but I'd like to see a use case first, and why it is better than the current form (similar to the arguments I put forth for node redefinition by label).
So, if I rework your example to use nodes...
foo {
bar-label: bar {
prop = 2;
};
};
&bar-label {
prop = 3;
};So, yes, prop in the second tree overrides the prop in the first tree because it is the same property name in the 'bar' node.
Quoted 7 lines
delete has the similar problem.
foo {
bar = 2;
delete(bar); // Should be illegal
}
Quoted 7 lines
foo {
bar-label: bar = 2;
}delete(&bar-label); // Legal.
foo {
bar-label: bar = 4; // Legal, even though previously deleted }
reworked to use nodes:
foo {
bar-label: bar {
prop = 2;
delete(bar); // should be illegal
};
};foo {
bar-label: bar { /* legal, adds label to node */
prop = 3; /* legal, changes prop */
};
};
delete-node(&bar-label}; // legal
foo {
bar-label: bar { /* Legal, even though previously deleted */
prop = 4;
};
};Quoted 4 lines
So, regardless of the syntax, I think it's important to ensure the above checks and sequentiality. There's also a canonicalization question, because you can spit out the original source, or the 'reduction' which results in all the overrides and deletions. I think from looking at Grant's patch, this is already the way things work, but I don't think anyone had really explicitly stated that.
Hmmm, perhaps nobody has. Yes, each node redefinition is fully processed before going on to the next one. Think: a stack of transparencies where each new sheet masks/changed/adds to the one below it.
Quoted 4 lines
One trick is that the below is problematic, or at least hard to verify statically.
foo {
delete(&bar-label); // Legal.
This is never legal. If deleting by label, it must be at the top level. It doesn't make sense to use a label reference inside a node block, since the node block is already supposed to define where you are working in the tree.
Quoted 1 line
delete(bar); // May or may not be Illegal, since don't know what bar-label references
No longer an issue since the previous line is illegal.
Also, must be either delete-node() or delete-prop() since nodes and properties can use the same names.
Quoted 10 lines
}
So, to syntax: the sequentialization property may be more syntactically obvious if deletion resembles setting a property or node like:
^bar
!bar
or even
bar = !;
bar !;
That's an interesting point. Perhaps it would be better to use a syntax that enforces the concept of overlays, and talk about masking out instead of deleting nodes and properties from the earlier tree.
I kind of like the ^ syntax, but there would have to be syntax variations for both node and property masking. I'm not sure it's a good idea to dedicate otherwise valid node name characters to the purpose of masking.
Quoted 5 lines
Which brings up the question 'undeletion question'. Can you do:
d-label: delete(bar);
delete(&d-label);
Not sure I follow. It certainly isn't be valid to apply a label to a command like delete().
g.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
A message that is not in the archive (sent off-list or not yet received): fa686aa41003011349i367a423cx2c59953e6afc9b75-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 8 lines
Yes, multiple sibling nodes with the same name are not allowed by dtc.
I believe multiple siblings of the same name is legal with
OpenFirmware, but that is at least partially because in OpenFirmware the @<addr> portion isn't necessarily part of the name. (Imagine having triplets and naming them Sally@1, Sally@2 and Sally@3!)
I'm not sure how to parse the above because the word "name" seems to be used somewhat informally.
The Open Firmware situation is this:
a) At a given level of the tree, there can be any number of nodes with the same value for the "name" property. For example, you could plug in several PCI Ethernet adapters and each would have "ethernet" as the value of the "name" property. In general, the "name" property is not intended as a unique identifier, but rather as a mnemonic for human convenience. The unique identifier is the first component of the "reg" property (within the context of the parent node). The whole schema for reg properties is driven by this uniqueness requirement, along with the observation that the computer hardware must have some physical means of addressing specific devices. The "reg" properties mimic physical addresses on various bus domains.
b) A fully-qualified device specifier component includes both the name property value and the reg property value (AKA the unit address), for example "ethernet@5".
c) It is possible to have a "wildcard" device node that contains an Open Firmware driver for a given device, but its bus has not been fully probed so you don't yet know the addresses (reg properties) for the actual devices. In that case, you can have a "name" property but no "reg" property. You can have a wildcard node "disk" and some explicit nodes "disk@1", "disk@2" as siblings. When searching the device tree, nodes with reg properties take precedence over wildcard nodes, so the wildcard node is a "fallback" to use if you can't find an explicit "name@reg" match. In principle, you could have several wildcard nodes with the same name at the same level of the tree, but if so, the search would find only the most recently defined one, so for all practical purposes it is as if only one exists.
Wildcard nodes are useful for Open Firmware driver binding, and could potentially be used for OS driver binding for either hot-plugged or late-probed devices. Whether or not they fit well into the dtc scheme, I can't say.
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 41 lines · Mitch Bradley
Quoted 8 lines
Yes, multiple sibling nodes with the same name are not allowed by dtc. I believe multiple siblings of the same name is legal with OpenFirmware, but that is at least partially because in OpenFirmware the @<addr> portion isn't necessarily part of the name. (Imagine having triplets and naming them Sally@1, Sally@2 and Sally@3!)
I'm not sure how to parse the above because the word "name" seems to be used somewhat informally.
The Open Firmware situation is this:
a) At a given level of the tree, there can be any number of nodes with the same value for the "name" property. For example, you could plug in several PCI Ethernet adapters and each would have "ethernet" as the value of the "name" property. In general, the "name" property is not intended as a unique identifier, but rather as a mnemonic for human convenience. The unique identifier is the first component of the "reg" property (within the context of the parent node). The whole schema for reg properties is driven by this uniqueness requirement, along with the observation that the computer hardware must have some physical means of addressing specific devices. The "reg" properties mimic physical addresses on various bus domains.
b) A fully-qualified device specifier component includes both the name property value and the reg property value (AKA the unit address), for example "ethernet@5".
c) It is possible to have a "wildcard" device node that contains an Open Firmware driver for a given device, but its bus has not been fully probed so you don't yet know the addresses (reg properties) for the actual devices. In that case, you can have a "name" property but no "reg" property. You can have a wildcard node "disk" and some explicit nodes "disk@1", "disk@2" as siblings. When searching the device tree, nodes with reg properties take precedence over wildcard nodes, so the wildcard node is a "fallback" to use if you can't find an explicit "name@reg" match. In principle, you could have several wildcard nodes with the same name at the same level of the tree, but if so, the search would find only the most recently defined one, so for all practical purposes it is as if only one exists.
Quoted 4 lines
Wildcard nodes are useful for Open Firmware driver binding, and could potentially be used for OS driver binding for either hot-plugged or late-probed devices. Whether or not they fit well into the dtc scheme, I can't say.
Thanks for the clarification. The flat tree does stay with the Open Firmware standard, however it does have the quirk that the name value in the flat tree includes the reg address. This is mostly because when Linux on PowerPC reads the tree out of Open Firmware and creates the flat representation it stores the full path including the reg address. The dts representation duplicates that behaviour.
I haven't entirely decided whether or not wildcard nodes are a good idea in the flat representation, but I am leaning in that direction. You already know about the discussion on how to handle Ethernet PHYs at an unknown address. That may very well be the way we decide to handle it.
However, the node name issue does raise a question about dtc. Right now it doesn't do any checks in this regard, but an argument could be made that dtc should warn or fail if a dts file sets the @<reg> component in a way inconsistent with the first entry in the reg property. Perhaps dtc should also automatically add @<reg> when the node name string omits it. (again, this only applies to the flat representation).
Cheers,
g.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
A message that is not in the archive (sent off-list or not yet received): fa686aa41003011533x3d2d00abyb8d7cf33344a3bde-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 1 line · Grant Likely
On Mon, Mar 1, 2010 at 3:15 PM, Mitch Bradley <[email protected]> wrote:
[snip]
Quoted 6 lines
Thanks for the clarification. The flat tree does stay with the Open Firmware standard, however it does have the quirk that the name value in the flat tree includes the reg address. This is mostly because when Linux on PowerPC reads the tree out of Open Firmware and creates the flat representation it stores the full path including the reg address. The dts representation duplicates that behaviour.
Well, it's more that in the flat tree we treat the "node name" as a separate entity to the node's name property, and containing the equivalent of both the name property and unit address as they'd be treated in real OF. And having done that, we typically omit the name property entirely, and just generate it on the fly from the node name when we need to.
Quoted 5 lines
I haven't entirely decided whether or not wildcard nodes are a good idea in the flat representation, but I am leaning in that direction. You already know about the discussion on how to handle Ethernet PHYs at an unknown address. That may very well be the way we decide to handle it.
Well.. the difficulty with wildcard nodes in a flat tree is that we have a number of cases where we already use nodes with no reg property to represent things that aren't really wildcards. The common use is for things which are addressable only on a sideband bus which doesn't form part of the normal reg address space hierarchy, such as DCR devices on 4xx.
Quoted 7 lines
However, the node name issue does raise a question about dtc. Right now it doesn't do any checks in this regard, but an argument could be made that dtc should warn or fail if a dts file sets the @<reg> component in a way inconsistent with the first entry in the reg property. Perhaps dtc should also automatically add @<reg> when the node name string omits it. (again, this only applies to the flat representation).
I've been intending that for ages. The complication is that the way the reg property is formatted into the unit address string is dependent on the parent bus. There's no inherent barrier to implementing this, and indeed the infrastructure in checks.c was created with this in mind amongst other things, but it's just a moderately large amount of coding because we need per-bus hooks to supply unit address formatting functions.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
RE: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 101 lines
-----Original Message-----
From: glikely-s3s/[email protected] [mailto:glikely-s3s/[email protected]] On Behalf Of Grant Likely
Sent: Monday, March 01, 2010 1:49 PM
To: Stephen Neuendorffer
Cc: Yoder Stuart-B08248; Wood Scott-B07421; [email protected]; John Williams; Jeremy Kerr
Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.Hi Stephen, good comments...
Quoted 37 lines · Stephen Neuendorffer
Quoted 37 lines
Given the following tree...
/ {
child-label: child {
prop = <0xbad>;
grandchild-label: grandchild {
};
};
};...here are the use cases that I see as important (plus some suggested syntax. I'm not happy with it though, and I'm open to better ideas).
1) Deleting a property from a node:
&child-label {
/* syntax to delete "prop" property */ delete-prop("prop");
^prop; /* this isn't very good, hard to differentiate from node deletion */
__delete_property= "prop";
};2) Delete a child node:
&child-label {
/* syntax to delete "grandchild" node */
delete-node("grandchild");
^grandchild;
__delete_node= "grandchild";
grandchild = ^{};
};3) Delete a labelled node from the top level:
delete-node(&grandchild-label);Comments? Suggestions? Better ideas? Please? Don't inflict pain on yourself by letting me decide the syntax.
Quoted 6 lines
Quoted 1 line
g.
One thing I've seen in the past is that there is a sequentialization question in this, which becomes more apparent once deletion is allowed.
First off, my assumption is that each node name is always unique in a tree, even when overrides are
allowed.
Quoted 1 line
Otherwise the sub-node and property ordering becomes important.
Yes, multiple sibling nodes with the same name are not allowed by dtc.
I believe multiple siblings of the same name is legal with
OpenFirmware, but that is at least partially because in OpenFirmware the @<addr> portion isn't necessarily part of the name. (Imagine having triplets and naming them Sally@1, Sally@2 and Sally@3!)However, the same name can be used by non-siblings. For example, the following is totally legal:
/ { foo { foo { }; }; };Quoted 14 lines
foo {
bar = 2;
bar = 3; // Illegal
} ;foo {
bar = 2;
}
foo {
bar = 3; // Legal
};Quoted 1 line
So, essentially, sequentialization of operation is forced by the concatenation of trees.
Yes, you are exactly correct. The model is to fully form 2 trees, and then overlay the latter on the former.
Quoted 6 lines
Similarly:
foo {
bar-label: bar = 2;
}
&bar-label = 3;
Quoted 7 lines
This actually isn't legal, but for an entirely different reason. Even though labels can be applied to properties, property labels aren't actually used for anything unless asm output is selected. All tree modification as of now is done from the context of nodes. Redefinition can start from the root node, or it can start from a labelled node, but there is no syntax defined for modifying a labelled property.
Ah, OK.
Quoted 4 lines
It is possible to add redefinition of labelled properties, but I'd like to see a use case first, and why it is better than the current form (similar to the arguments I put forth for node redefinition by label).
Ah, right, they have separate namespaces. When I implemented this in the past, properties and hierarchy shared a single namespace.
Quoted 29 lines
So, if I rework your example to use nodes...
foo { bar-label: bar { prop = 2; }; }; &bar-label { prop = 3; };So, yes, prop in the second tree overrides the prop in the first tree because it is the same property name in the 'bar' node.
Quoted 7 lines
delete has the similar problem.
foo {
bar = 2;
delete(bar); // Should be illegal
}Quoted 7 lines
foo {
bar-label: bar = 2;
}delete(&bar-label); // Legal.
foo {
bar-label: bar = 4; // Legal, even though previously deleted }
Quoted 7 lines
reworked to use nodes:
foo { bar-label: bar { prop = 2; delete(bar); // should be illegal }; };
Um, my original intent was:
foo {
bar-label: bar {
prop = 2;
};
delete(bar); // should be illegal
};Quoted 15 lines
foo {
bar-label: bar { /* legal, adds label to node */
prop = 3; /* legal, changes prop */
};
};
delete-node(&bar-label}; // legalfoo { bar-label: bar { /* Legal, even though previously deleted */ prop = 4; }; };Quoted 2 lines
So, regardless of the syntax, I think it's important to ensure the above checks and sequentiality. There's also a canonicalization question, because you can spit out the original source, or the
'reduction'
Quoted 8 lines
Quoted 1 line
which results in all the overrides and deletions. I think from looking at Grant's patch, this is
already
Quoted 1 line
the way things work, but I don't think anyone had really explicitly stated that.
Hmmm, perhaps nobody has. Yes, each node redefinition is fully processed before going on to the next one. Think: a stack of transparencies where each new sheet masks/changed/adds to the one below it.
I think this makes alot of sense.
Quoted 10 lines
Quoted 4 lines
One trick is that the below is problematic, or at least hard to verify statically.
foo {
delete(&bar-label); // Legal.This is never legal. If deleting by label, it must be at the top level. It doesn't make sense to use a label reference inside a node block, since the node block is already supposed to define where you are working in the tree.
Quoted 6 lines
Quoted 1 line
delete(bar); // May or may not be Illegal, since don't know what bar-label references
No longer an issue since the previous line is illegal.
Also, must be either delete-node() or delete-prop() since nodes and properties can use the same names.
So, is it true that a tree which is overlayed on another tree can be independently verified to be independent of internal ordering? This would be nice if so.
Quoted 12 lines
Quoted 3 lines
}
So, to syntax: the sequentialization property may be more syntactically obvious if deletion
resembles
Quoted 7 lines
setting a property or node like:
^bar
!bar
or even
bar = !;
bar !;
Quoted 8 lines
That's an interesting point. Perhaps it would be better to use a syntax that enforces the concept of overlays, and talk about masking out instead of deleting nodes and properties from the earlier tree.
I kind of like the ^ syntax, but there would have to be syntax variations for both node and property masking. I'm not sure it's a good idea to dedicate otherwise valid node name characters to the purpose of masking.
I'm not necessarily wild about these syntax options either, BTW...
Quoted 7 lines
Quoted 4 lines
Which brings up the question 'undeletion question'. Can you do:
d-label: delete(bar);
delete(&d-label);Not sure I follow. It certainly isn't be valid to apply a label to a command like
delete().
But the best thing of the above is that there is no longer a distinction between commands and data! delete is just a tag which gets interpreted during 'reduction' or 'overlay'.
For instance, deleting a subnode could be:
foo {
bar {
delete;
}
}I guess this ends up conflicting with a property named 'delete' though.
Steve
This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
A message that is not in the archive (sent off-list or not yet received): 72f497af-412c-4a05-90c2-5df0be00d93f-+Ck8Kgl/v09CYczPSvLbDrjjLBE8jN/[email protected]
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 9 lines · Stephen Neuendorffer
From: glikely-s3s/[email protected] [mailto:glikely-s3s/[email protected]] On Behalf Of Grant Likely
Quoted 7 lines
reworked to use nodes:
foo {
bar-label: bar {
prop = 2;
delete(bar); // should be illegal
};
};
Quoted 7 lines
Um, my original intent was:
foo {
bar-label: bar {
prop = 2;
};
delete(bar); // should be illegal
};
Ah, yes. And you are right, that should be illegal.
Quoted 2 lines
So, is it true that a tree which is overlayed on another tree can be independently verified to be independent of internal ordering? This would be nice if so.
Yes, I think that is a valid statement, with the assumption that label references at the top level are first resolved.
Quoted 8 lines
Quoted 2 lines
Not sure I follow. It certainly isn't be valid to apply a label to a command like
delete().But the best thing of the above is that there is no longer a distinction between commands and data! delete is just a tag which gets interpreted during 'reduction' or 'overlay'.
For instance, deleting a subnode could be:
Quoted 7 lines
foo {
bar {
delete;
}
}I guess this ends up conflicting with a property named 'delete' though.
Right. It should be something syntactically distinct.
g.
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 6 lines · Stephen Neuendorffer
Quoted 6 lines
-----Original Message-----
From: glikely-s3s/[email protected] [mailto:glikely-s3s/[email protected]] On Behalf Of Grant Likely
Sent: Monday, March 01, 2010 1:49 PM
To: Stephen Neuendorffer
Cc: Yoder Stuart-B08248; Wood Scott-B07421; [email protected]; John Williams; Jeremy Kerr
Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
[snip]
Quoted 7 lines
Quoted 7 lines
This is never legal. If deleting by label, it must be at the top level. It doesn't make sense to use a label reference inside a node block, since the node block is already supposed to define where you are working in the tree.
Quoted 1 line
delete(bar); // May or may not be Illegal, since don't know what bar-label references
Quoted 8 lines
Quoted 4 lines
No longer an issue since the previous line is illegal.
Also, must be either delete-node() or delete-prop() since nodes and properties can use the same names.
So, is it true that a tree which is overlayed on another tree can be independently verified to be independent of internal ordering? This would be nice if so.
Hrm, yes and no. Most of our tests for duplicate labels and so forth are only performed after all the overlay/merging is completed.
Which brings up another inconsistency in the current processing. Although:
/ {
foo = "bar";
foo = "baz";
};is illegal and will cause an error, the way that merge_nodes() is implemented means that the following will be accepted:
/ {
};
/ {
foo = "bar";
foo = "baz";
};(and the foo property will have the final value "baz").
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 38 lines · David Gibson
Quoted 6 lines · Stephen Neuendorffer
Quoted 6 lines
-----Original Message-----
From: glikely-s3s/[email protected] [mailto:glikely-s3s/[email protected]] On Behalf Of Grant Likely
Sent: Monday, March 01, 2010 1:49 PM
To: Stephen Neuendorffer
Cc: Yoder Stuart-B08248; Wood Scott-B07421; [email protected]; John Williams; Jeremy Kerr
Subject: Re: [PATCH 8/9 V3] Add documentation for the new DTS language.[snip]
Quoted 7 lines
Quoted 7 lines
This is never legal. If deleting by label, it must be at the top level. It doesn't make sense to use a label reference inside a node block, since the node block is already supposed to define where you are working in the tree.
Quoted 1 line
delete(bar); // May or may not be Illegal, since don't know what bar-label references
Quoted 8 lines
Quoted 4 lines
No longer an issue since the previous line is illegal.
Also, must be either delete-node() or delete-prop() since nodes and properties can use the same names.
So, is it true that a tree which is overlayed on another tree can be independently verified to be independent of internal ordering? This would be nice if so.
Hrm, yes and no. Most of our tests for duplicate labels and so forth are only performed after all the overlay/merging is completed.
Which brings up another inconsistency in the current processing. Although:
/ {
foo = "bar";
foo = "baz";
};is illegal and will cause an error, the way that
merge_nodes()is implemented means that the following will be accepted:
Quoted 8 lines
/ {
};
/ {
foo = "bar";
foo = "baz";
};(and the foo property will have the final value "baz").
That should be easy to fix. How about the following change to prevent duplicate properties even getting added to the livetree. This patch isn't complete, it breaks some of the test cases because it fails in a different way, and it makes some of the post-checks redundant.
g.
commit f676848929e6764b3a6c14f14eafacdfcaab5f15
Author: Grant Likely <grant.likely-s3s/[email protected]> Date: Wed Mar 3 09:15:30 2010 -0700
Don't add duplicate properties to the live tree
dtc-parser.y +5 -0
@@ -156,6 +156,11 @@ proplist: } | proplist propdef { + if (find_property($1, $2->name)) { + yyerror("syntax error: duplicate property"); + YYERROR; + } + $$ = chain_property($2, $1); } ;
dtc.h +1 -0
@@ -170,6 +170,7 @@ void add_label(struct label **labels, char *label);struct property *build_property (char *name,struct data val);struct property *chain_property (struct property *first,struct property *list);struct property *reverse_properties (struct property *first); +struct property *find_property (struct property *proplist,const char *name);struct node *build_node (struct property *proplist,struct node *children);struct node *name_node (struct node *node,char *name);
livetree.c +9 -0
@@ -74,6 +74,15 @@ struct property *reverse_properties(struct property *first)return head; } +struct property *find_property (struct property *proplist,const char *name) +{ +for (; proplist; proplist = proplist->next) +if (streq (proplist->name, name)) +return proplist; + +return NULL ; +} +struct node *build_node (struct property *proplist,struct node *children) {struct node *new =xmalloc (sizeof (*new));
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
In reply to a message not in the archiveQuoted 34 lines · Grant Likely
Quoted 10 lines · David Gibson
Quoted 7 lines
The model that I'm using to approach the problem is to add syntax for including .dts files (exactly how Jon proposed) and syntax for going back after the tree is parsed and changing things. I'm not an expert on syntax, so I'm open to changes in the details, but this is what I'm thinking. Add the following directives to the syntax:
/include/ Include a file
Uh.. we already have /include/, which works pretty much exactly as you want it to.
Well how about that. I guess we do. I learned something today.
Quoted 7 lines
Ok, I quite like the functionality, but I'm not that fond of the syntax. I think I have a similar but neater proposal, at least for the adding-stuff parts. There's two parts to my counter-proposal
1) This is essentially part of your proposal, but I'm separating it out from the /cd/ syntax.
Quoted 7 lines
We allow redefinition of properties, nodes, or even the whole device tree. For properties the later definition overrides the earlier. For nodes, or the whole tree, the definitions are merged in the obvious way (again with later property definitions overriding earlier). In this way an include could define a base tree, and you could then define an "overlay" tree which adds things or changes properties where necessary.
Yes, I agree with this. It's pretty well describes the functionality that I was thinking about.
Quoted 7 lines
Quoted 4 lines
Optional extension: because allowing redefinitions potentially allows genuine mistakes to silently generate unexpected output, it might be wise to allow only "weak" definitions, marked somehow, to be overriden. I'm not sure what syntax we'd use for that.
Examples? I'm not clear on what potential mistakes you're thinking about.
Erm, I was thinking about making a typo and overriding something you didn't intend intstead of something you did. But I can't really come up with something more concrete than that, so yeah, it's probably not that big a deal.
Quoted 3 lines
That being said, I could see it potentially being valuable to be able to assign an 'invalid' value to a property so that is *must* get overridden before dtc will generate valid output.
That is a very good point. And it ties in with something I've considered before of having some sort of invalid value (which might or might not also reserve space in the dtb) to mark things which ought to be poked by the bootloader before the tree is passed to the kernel. Thoughts have varied on whether that would be purely a documentation thing, or whether this would also have a dtb representation so it could actually be checked at runtime, but then syntax which allows the first would easily allow a later extension to implement the second.
Obviously that's not quite the same thing as here, since clearly it would be permissible to generate trees with this sort of invalid value, unlike your proposal. But I don't think that's an insurmountable problem.
Quoted 33 lines
Quoted 1 line
I think (1) fits very naturally into the existing syntax.
I agree. It certainly provides better containment than my /cd/ suggestion.
Quoted 14 lines
2) The trouble with the above is that having included a template device tree, redefining some property deep within it is unpleasantly verbose. You address that with /cd/, which I don't like very much. So my counter proposal is that we allow a path instead of just a name at the beginning of a node definition. This would essentially define an empty node for all the initial path elements, then let the node body define the final path element in the appropriate location. So:
/include/
template.dtsi;/somebus@XX/someotherbus@XX/i2c@XX/board-control-widget@XXX { board-specific-property = "whatever";
};Quoted 6 lines
Optional extension 1: Give an error if the earlier path components haven't been defined yet (i.e. _don't+ allow implicit mkdir -p like behaviour). I suspect this would rarely to never be an inconvenience, because you don't generally want to define a node with no properties at all, and it would catch some genuine mistakes (like a typo which adds a / to a node name).
Yeah, this sounds reasonable.
Quoted 5 lines
Optional extension 2: Allow a node label to be invoked at the beginning of a node redefinition in. That would let include files put labels on the nodes most likely to be extended or overriden, particularly if they're buried deep in the tree and then the necessary redefinitions become less verbose again.
Quoted 4 lines
I think this is absolutely essential. With respect to the FPGA use case, nodes are going to move around, possibly quite a bit as the FPGA design develops. It is critical to have some kind of handle to a node other than the node name or location because they will change.
Yes, I thought that might be the case.
Quoted 13 lines
I
think this might even be able to be handled as part (3) because it doesn't have the '/' processing issue that part (2) has. For example:instead of:
/ { parent@1234 { child@abcd { new-property = <0x01234567>; }; }; };
Quoted 5 lines
do this:
&child-label { new-property = <0x01234567>; };
And, you know, it turns out '&' is one of the other characters that is neither in the current grammar for node names, nor does it appear in any device tree I've encountered. So this syntax is probably ok, too. Ah.. with the proviso that I think to make sense you could only use this form at the top level (so at the top level nodes would be introduced by either '/' or '&label' whereas at lowever levels it would be by a nodepropname token.
[Something to be aware of in the lexical issues that surround node and property names is that while IEEE1275 specifies a fairly limited set of characters for them, there exist device trees in the wild (in Apple and IBM firmwares, mostly) that have characters not in that set. So to be pragmatic we have to allow a pretty wide selection here]
Quoted 11 lines
Quoted 7 lines
(2) is a bit more problematic syntax-wise. The fact that paths are now possible before the node definition raises some lexical issues. In particular it means the /-surrounded "reserved words" might no longer be clearly lexically distinct from a node definition (I chose to make the reserved words surround by / specifically so that that would be the case). I suspect this is not a fatal problem, but I'll need to think about it some more.
Actually, as long as I can reference a specific node by label, I don't think I need the ability to pass in the full path. Label provides the functionality I need.
You know, I was kind of hoping you'd say that :). After all it is still possible to override by explicit path, it's just a bit verbose, which is ok if it's not needed particularly often.
Quoted 9 lines
Quoted 4 lines
That still leaves node and property deletion to cover. In keeping with the above approach, I'd like to do that in the form of "negative redefinitions" of properties or nodes. A neat syntax for that doesn't immediately occur to be for that yet, though.
hmmm. I'll think more about it too. I agree that a negative redefinition sounds like a reasonable approach. I do want the ability to drop nodes easily. It would make it easy to handle SoC or FPGA design variants.
Yeah. Unfortunately we can't use something as simple as '- propname;' because '-' is a valid character in node and propery names. For properties we could maybe do something like:
obsolete-property = /null/;
But that doesn't extend neatly to node removal.
Quoted 14 lines
Quoted 10 lines
Quoted 3 lines
And that's it. I think this covers the functionality that I need. What does everyone think? Are there other important use cases that I should also be addressing?
Probably, but I'm not really sure what they are.
So I think my proposal (1) above accomplishes some of what you want, while being unlikely to badly conflict with any of the various paths we might want to take in the future. So, shall we proceed in that direction while we think about the rest?
Yeah, I think so. Okay, so how about some examples then of what I think you're describing:
Quoted 7 lines
1) Add or modify properties to a node
/include/ "base-tree.dtsi"/ { node { new-property = <0x1234>; }; };
Yes.
Quoted 9 lines
2) Add a new node:
/include/ "base-tree.dtsi"/ { parent { new-child { new-properties; }; }; };
Yes.
Quoted 9 lines
3) Add a new node with a label:
/include/ "base-tree.dtsi"/ { parent { new-label: new-child { new-properties; }; }; };
Yes.
Quoted 5 lines
4) add a label to an existing node
/include/ "base-tree.dtsi"/ { new-label: existing-node { }; };
Ah.. yes, hadn't thought of that. Which reminds me of another extension I've had in mind for a while, which I suspect we'll want along with this stuff to avoid having some really weird corner cases. At present, because of the way things are stored in the internal data structures, it's only possible to have a single label on a node or property (which a wart already, since you can have any number of labels at the same point within a property value). I think having redefinitions would significantly increase the chances that this limitation will be a problem in practice.
Quoted 7 lines
5) Start from a labeled node instead of the root node:
/include/ "base-tree.dtsi"&existing-label { new-property = <0xabcd>; };Do I have this right?
I think so.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 14 lines · David Gibson
Quoted 3 lines · Grant Likely
That being said, I could see it potentially being valuable to be able to assign an 'invalid' value to a property so that is *must* get overridden before dtc will generate valid output.
That is a very good point. And it ties in with something I've considered before of having some sort of invalid value (which might or might not also reserve space in the dtb) to mark things which ought to be poked by the bootloader before the tree is passed to the kernel. Thoughts have varied on whether that would be purely a documentation thing, or whether this would also have a dtb representation so it could actually be checked at runtime, but then syntax which allows the first would easily allow a later extension to implement the second.
Quoted 4 lines
Obviously that's not quite the same thing as here, since clearly it would be permissible to generate trees with this sort of invalid value, unlike your proposal. But I don't think that's an insurmountable problem.
Right, not quite the same thing, but this easy can easily be deferred.
I don't actually have any real use cases that depend on this, so I
don't think we need to jump through hoops right now to get it.
Quoted 15 lines
Quoted 15 lines
I
think this might even be able to be handled as part (3) because it doesn't have the '/' processing issue that part (2) has. For example:instead of:
/ {
parent@1234 {
child@abcd {
new-property = <0x01234567>; };
};
};do this:
Quoted 8 lines
Quoted 3 lines
&child-label {
new-property = <0x01234567>;
};And, you know, it turns out '&' is one of the other characters that is neither in the current grammar for node names, nor does it appear in any device tree I've encountered. So this syntax is probably ok, too.
I specifically chose this syntax because it matches the "property = &label;" syntax used when assigning a path to a property, so .dts authors know that a bare "&label" means the full path to a node. I think it helps with clarity.
Quoted 4 lines
Ah.. with the proviso that I think to make sense you could only
use this form at the top level (so at the top level nodes would be introduced by either '/' or '&label' whereas at lowever levels it would be by a nodepropname token.
Absolutely. I also made the assumption that &label is only valid at the top level.
Quoted 5 lines
[Something to be aware of in the lexical issues that surround node and property names is that while IEEE1275 specifies a fairly limited set of characters for them, there exist device trees in the wild (in Apple and IBM firmwares, mostly) that have characters not in that set. So to be pragmatic we have to allow a pretty wide selection here]
On that note, does the grammer support an escape sequence for characters with a special meaning? ie. a \<char> sequence? Doing so would sidestep the issue for any exotic trees that come across.
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
(2) is a bit more problematic syntax-wise. The fact that paths are now possible before the node definition raises some lexical issues. In particular it means the /-surrounded "reserved words" might no longer be clearly lexically distinct from a node definition (I chose to make the reserved words surround by / specifically so that that would be the case). I suspect this is not a fatal problem, but I'll need to think about it some more.
Quoted 7 lines
Quoted 3 lines
Actually, as long as I can reference a specific node by label, I don't think I need the ability to pass in the full path. Label provides the functionality I need.
You know, I was kind of hoping you'd say that :). After all it is still possible to override by explicit path, it's just a bit verbose, which is ok if it's not needed particularly often.
:-) I'm okay with verbose in this case.
Quoted 6 lines
Quoted 5 lines
4) add a label to an existing node
/include/ "base-tree.dtsi"
/ {
new-label: existing-node { };
};
Quoted 9 lines
Ah.. yes, hadn't thought of that. Which reminds me of another extension I've had in mind for a while, which I suspect we'll want along with this stuff to avoid having some really weird corner cases. At present, because of the way things are stored in the internal data structures, it's only possible to have a single label on a node or property (which a wart already, since you can have any number of labels at the same point within a property value). I think having redefinitions would significantly increase the chances that this limitation will be a problem in practice.
Okay, this will probably need to be solved then. It would probably be a bad idea to encode limitations into the language that are really just an artifact of the current implementation. That being said, while I would use this, I won't be hamstrung by the lack of this feature in the near term.
Quoted 10 lines
Quoted 8 lines
5) Start from a labeled node instead of the root node:
/include/ "base-tree.dtsi"
&existing-label {
new-property = <0xabcd>;
};Do I have this right?
I think so.
Cool. Are you able to prototype the new features? I have no idea where to start, and I'm pretty buried in the ARM port at the moment. However, if you implement it then I'll immediately convert all the MPC5200 .dts files to use it.
Cheers,
g.
A message that is not in the archive (sent off-list or not yet received): fa686aa41002221817s5f15dc4cy5ab873a61de2cb2f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH 8/9 V3] Add documentation for the new DTS language.
Quoted 16 lines · Grant Likely
Quoted 14 lines · David Gibson
Quoted 3 lines · Grant Likely
That being said, I could see it potentially being valuable to be able to assign an 'invalid' value to a property so that is *must* get overridden before dtc will generate valid output.
That is a very good point. And it ties in with something I've considered before of having some sort of invalid value (which might or might not also reserve space in the dtb) to mark things which ought to be poked by the bootloader before the tree is passed to the kernel. Thoughts have varied on whether that would be purely a documentation thing, or whether this would also have a dtb representation so it could actually be checked at runtime, but then syntax which allows the first would easily allow a later extension to implement the second.
Quoted 8 lines
Quoted 4 lines
Obviously that's not quite the same thing as here, since clearly it would be permissible to generate trees with this sort of invalid value, unlike your proposal. But I don't think that's an insurmountable problem.
Right, not quite the same thing, but this easy can easily be deferred.
I don't actually have any real use cases that depend on this, so I
don't think we need to jump through hoops right now to get it.
Yes, quite so.
Quoted 24 lines
Quoted 15 lines
Quoted 15 lines
I
think this might even be able to be handled as part (3) because it doesn't have the '/' processing issue that part (2) has. For example:instead of:
/ {
parent@1234 {
child@abcd {
new-property = <0x01234567>; };
};
};do this:
Quoted 8 lines
Quoted 3 lines
&child-label {
new-property = <0x01234567>;
};And, you know, it turns out '&' is one of the other characters that is neither in the current grammar for node names, nor does it appear in any device tree I've encountered. So this syntax is probably ok, too.
Quoted 4 lines
I specifically chose this syntax because it matches the "property = &label;" syntax used when assigning a path to a property, so .dts authors know that a bare "&label" means the full path to a node. I think it helps with clarity.
Yes, I concur.
Quoted 7 lines
Quoted 4 lines
Ah.. with the proviso that I think to make sense you could only
use this form at the top level (so at the top level nodes would be introduced by either '/' or '&label' whereas at lowever levels it would be by a nodepropname token.Absolutely. I also made the assumption that &label is only valid at the top level.
Excellent.
Quoted 9 lines
Quoted 5 lines
[Something to be aware of in the lexical issues that surround node and property names is that while IEEE1275 specifies a fairly limited set of characters for them, there exist device trees in the wild (in Apple and IBM firmwares, mostly) that have characters not in that set. So to be pragmatic we have to allow a pretty wide selection here]
On that note, does the grammer support an escape sequence for characters with a special meaning? ie. a \<char> sequence? Doing so would sidestep the issue for any exotic trees that come across.
Not at present, though I have considered it on several occasions. My preferred would probably be that for anything with exotic characters a quoted string is instead used for the node name (including the C-like \-escapes which we already support).
One of the uses I had in mind for this is to be able to do -Idtb -Odts on a mildly corrupted tree and have something that's at least syntactically correct and reversible.
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines
Quoted 7 lines
(2) is a bit more problematic syntax-wise. The fact that paths are now possible before the node definition raises some lexical issues. In particular it means the /-surrounded "reserved words" might no longer be clearly lexically distinct from a node definition (I chose to make the reserved words surround by / specifically so that that would be the case). I suspect this is not a fatal problem, but I'll need to think about it some more.
Actually, as long as I can reference a specific node by label, I don't think I need the ability to pass in the full path. Label provides the functionality I need.
Quoted 5 lines
Quoted 3 lines
You know, I was kind of hoping you'd say that :). After all it is still possible to override by explicit path, it's just a bit verbose, which is ok if it's not needed particularly often.
:-) I'm okay with verbose in this case.
Seems we agree.
Quoted 16 lines
Quoted 6 lines
Quoted 5 lines
4) add a label to an existing node
/include/ "base-tree.dtsi"
/ {
new-label: existing-node { };
};Quoted 9 lines
Ah.. yes, hadn't thought of that. Which reminds me of another extension I've had in mind for a while, which I suspect we'll want along with this stuff to avoid having some really weird corner cases. At present, because of the way things are stored in the internal data structures, it's only possible to have a single label on a node or property (which a wart already, since you can have any number of labels at the same point within a property value). I think having redefinitions would significantly increase the chances that this limitation will be a problem in practice.
Quoted 5 lines
Okay, this will probably need to be solved then. It would probably be a bad idea to encode limitations into the language that are really just an artifact of the current implementation. That being said, while I would use this, I won't be hamstrung by the lack of this feature in the near term.
Right.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
5) Start from a labeled node instead of the root node:
/include/ "base-tree.dtsi"
&existing-label {
new-property = <0xabcd>;
};
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
Do I have this right?
I think so.
Cool. Are you able to prototype the new features? I have no idea where to start, and I'm pretty buried in the ARM port at the moment. However, if you implement it then I'll immediately convert all the MPC5200 .dts files to use it.
Heh, yes, well. I'm pretty busy myself with things of direct interest to my employer. So.. I'll see what I can do, but no promises.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 7/9 V3] Introduce new DTS language.
In reply to a message not in the archiveQuoted 6 lines · Jon Loeliger
Introduce function defs and statements.
Add lexical support for column source position information.
Notably, this involved identifying all the newline characters to reset the column count. Had to rewrite the C comment rules, and break \n out of the {WS} set.
This really doesn't belong in this patch. It ought to be folded in with the rest of the srcpos changes.
Except, I'm a fair way through implementing srcpos cleanups of my own which will subsume these.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 4/9 V3] Add header files for new Internal Representation form.
In reply to a message not in the archiveQuoted 1 line · Jon Loeliger
Signed-off-by Jon Loeliger <[email protected]>
I think patches 4, 5, 6 and 7 should be merged together. Splitting patches into logical sections is ok, but these are all basically interdependent. Sure, the ordering you have doesn't actually break bisect, but the earlier patches don't *do* anything until the later ones activate them, so there's really no point separating them out.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 3/9 V3] Enhance source position implementation.
In reply to a message not in the archiveQuoted 3 lines · Jon Loeliger
Implemented some print and copy routines. Made empty srcpos objects that will be used later. Protected .h file from multiple #include's.
Can we separate this out as a different series. I've been thinking the srcpos stuff needs some cleanup for a while, and this is not directly relevant to the IR stuff, which I think needs considerably more discussion and thought.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [PATCH 1/9 V3] Remove support for the legacy DTS source file format.
In reply to a message not in the archiveQuoted 8 lines · Jon Loeliger
Now that all in-kernel-tree DTS files are properly /dts-v1/, remove direct support for the older, un-numbered DTS source file format.
Convert existing tests to /dts-v1/ and remove support for the conversion tests themselves.
For now, though, the conversion tool still exists.
Hrm. Again, I don't think we should need to do this.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 1/9 V3] Remove support for the legacy DTS source file format.
Quoted 11 lines · David Gibson
Quoted 8 lines · Jon Loeliger
Now that all in-kernel-tree DTS files are properly /dts-v1/, remove direct support for the older, un-numbered DTS source file format.
Convert existing tests to /dts-v1/ and remove support for the conversion tests themselves.
For now, though, the conversion tool still exists.
Hrm. Again, I don't think we should need to do this.
Older dtc versions are still around for those that need them... IIUC, keeping the old syntax around will complicate the code when adding the new features.
-Scott
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH 1/9 V3] Remove support for the legacy DTS source file format.
Quoted 9 lines · Scott Wood
Quoted 8 lines · David Gibson
Quoted 7 lines · Jon Loeliger
Now that all in-kernel-tree DTS files are properly /dts-v1/, remove direct support for the older, un-numbered DTS source file format.
Convert existing tests to /dts-v1/ and remove support for the conversion tests themselves.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
For now, though, the conversion tool still exists.
Hrm. Again, I don't think we should need to do this.
Older dtc versions are still around for those that need them... IIUC, keeping the old syntax around will complicate the code when adding the new features.
I realise that, I'm just not all that convinced it's a good tradeoff at this time.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson