EmbeddedRelated.com
Forums

Language feature selection

Started by Don Y March 5, 2017
On 2017-03-10, Walter Banks <walter@bytecraft.com> wrote:
> On 2017-03-09 5:54 PM, Les Cargill wrote: >> >> Hi Walter! No offense, but... >> >> This is utterly 1) inappropriate and 2) unnecessary. It's a >> *terrible* extension. > > Maybe "terrible" but a lot cleaner than a pointer to constant that is > expected to be optimized by a compiler to a simple load store.
Huh? The common method for accessing memory-mapped registers in C that's been discussed doesn't involve a "pointer to a constant". -- Grant
David Brown <david.brown@hesbynett.no> writes:

> On 09/03/17 17:15, Grant Edwards wrote: >> On 2017-03-09, David Brown <david.brown@hesbynett.no> wrote: >>> On 09/03/17 15:47, Grant Edwards wrote: >>>> On 2017-03-09, Walter Banks <walter@bytecraft.com> wrote: >>>> >>>>> Far less complex. A simple way to declare a variable at a specific >>>>> physical address. >>>>> >>>>> Every other variable attribute remains untouched. It is in the >>>>> symbol table, debug data and can be referenced like any other >>>>> variable. You can do address of, set a pointer to it assign and read >>>>> it. >>>> >>>> I leave the dermination of physical addresses up to the linker. If I >>>> want "real variables" at specific addresses, that belongs in the >>>> linker script (IMO). >>> >>> That's okay, if you don't mind the extra overhead because the compiler >>> can't see the address at compile time, and you are happy to declare your >>> registers twice (once in a header for C, and once in the linker file). >> >> Ah, I thought we were talking about variables, not registers. I think >> conflating the two is a grave mistake. > > Well, Walter did say "declare a /variable/ at a specific physical > address" - but far and away the most common need for something at a > fixed address is a hardware register. It is very rare that you would > want a normal variable at a fixed address (interfacing between > separately compiled and linked code, such as a bootloader and a main > program, is about the only case I can think of).
There are the variables normally already declared in linker scripts. __bss_start, __end__ and so forth. I have used them occasionally e.g. to replace or instrument memory management or system initialisation functions. But those too are not "normal".
> For a variable, I agree that a linker script might be a way to handle > it. More likely, I'd use C extensions to put the variable in a > specific named section, and use linker scripts or commands to put the > section at a specific address. > >> >>> Of course, this is rarely an issue in practice because in most >>> cases, people use ready-made chip header files from the device >>> manufacturers, and for most processors and compilers these will use >>> casted pointers to volatiles. >> >> Again, that's for accessing HW registers, which (IMO) should not be >> conflated with variables. Thinking that HW registes are "normal >> variables" is an excellent way to loose a foot. >> >> This, of course, raises the question why you would _need_ to place >> _variables_ at specific addresses when it's not for accessing HW >> registers. That need seems to me to be rare enough that adding a >> language feature to support it is foolish. >> > > Agreed. >
-- John Devereux
On 09/03/17 23:54, Les Cargill wrote:
> Walter Banks wrote: >> On 2017-03-05 5:03 PM, Don Y wrote: >>> A quick/informal/UNSCIENTIFIC poll: >>> >>> What *single* (non-traditional) language feature do you find most >>> valuable in developing code? (and, applicable language if unique to >>> *a* language or class of languages) >> >> The @ in various forms to tie a physical address to a symbolic variable. >> This construct more that any other single thing allows many high level >> languages have the ability broaden the range of potential applications >> from high level to close to the machine. >> > > Hi Walter! No offense, but... > > This is utterly 1) inappropriate and 2) unnecessary. It's a *terrible* extension > to ( I presume C, where I have seen it ). > > Even back on Borland, Microsoft, Tektronix and ... another VAX C compiler 30ish > years ago, you'd use a linker/locater to put specific structures at specific > locations. > > The source code itself doesn't need to know about where variables go[1]. > > Its part of the responsibility of tools that are invoked later > in the build cycle.
This is a philosophical difference. If something is important to the correct operation of the program, then I like it to be visible in the source code. A useful benefit is that the information is easily found and analysed by the IDEs and/or other source code manipulation tools around. In the same vein, in C I dislike having correct code operation being dependent on combinations of command line compiler arguments.
>> It is language independent and very easy to add to compilers without >> changing the basic form of the language. >> > > it very nearly destroys the portability of code that uses it...
That seems unimportant to me. I cannot think of a reason why you would need to nail down addresses in portable code. Of course "portable" is not a black and white concept! Any examples?
On 10.3.17 01:57, Les Cargill wrote:

> > One need only go back to the '80s/'90s to find Paradigm Locate, which > took Borland C/C++ objects and fixed certain .SEGMENTS[1] at certain > locations for this sort of thing. > > [1] like .BSS, .CODE, .DATA, whatever...
In the Intel x86 processor world the word 'segment' has several conflicting and confusing uses. It seems that the confusion has hit here. Paradigm Locate took a configuration file and a MS-DOS 16 bit .exe file and produced an absolute binary file (in many optional output formats, e.g. Intel hex). The MS-DOS exe file is a segment-relocatable format, segment here meaning a 16 byte aligned adddress base by the hardware segment registers (cs, ds, ss, es). It is possible to combine several program sections (.text, .data, .bss, .CODE, etc...) to groups which are addressed with common segment register contents. Paradigm Locate fixes the segments/groups in the exe file to locations determined in the configuration file, creating an absolute binary file. -- -TV PS. I think that I still have the tools somewhere in the back corner of the shed.
On 10/03/17 08:46, John Devereux wrote:
> David Brown <david.brown@hesbynett.no> writes: > >> On 09/03/17 17:15, Grant Edwards wrote: >>> On 2017-03-09, David Brown <david.brown@hesbynett.no> wrote: >>>> On 09/03/17 15:47, Grant Edwards wrote: >>>>> On 2017-03-09, Walter Banks <walter@bytecraft.com> wrote: >>>>> >>>>>> Far less complex. A simple way to declare a variable at a specific >>>>>> physical address. >>>>>> >>>>>> Every other variable attribute remains untouched. It is in the >>>>>> symbol table, debug data and can be referenced like any other >>>>>> variable. You can do address of, set a pointer to it assign and read >>>>>> it. >>>>> >>>>> I leave the dermination of physical addresses up to the linker. If I >>>>> want "real variables" at specific addresses, that belongs in the >>>>> linker script (IMO). >>>> >>>> That's okay, if you don't mind the extra overhead because the compiler >>>> can't see the address at compile time, and you are happy to declare your >>>> registers twice (once in a header for C, and once in the linker file). >>> >>> Ah, I thought we were talking about variables, not registers. I think >>> conflating the two is a grave mistake. >> >> Well, Walter did say "declare a /variable/ at a specific physical >> address" - but far and away the most common need for something at a >> fixed address is a hardware register. It is very rare that you would >> want a normal variable at a fixed address (interfacing between >> separately compiled and linked code, such as a bootloader and a main >> program, is about the only case I can think of). > > There are the variables normally already declared in linker > scripts. __bss_start, __end__ and so forth. I have used them > occasionally e.g. to replace or instrument memory management or system > initialisation functions. But those too are not "normal".
Those are not variables - they are linker-defined addresses, such as marking the start and end of sections. Usually you don't need to use them directly, but they are needed for things like the C startup code. You need them if you are writing your own startup code, or for fixing TI's broken compilers that don't clear uninitialised variables at startup.
> >> For a variable, I agree that a linker script might be a way to handle >> it. More likely, I'd use C extensions to put the variable in a >> specific named section, and use linker scripts or commands to put the >> section at a specific address. >> >>> >>>> Of course, this is rarely an issue in practice because in most >>>> cases, people use ready-made chip header files from the device >>>> manufacturers, and for most processors and compilers these will use >>>> casted pointers to volatiles. >>> >>> Again, that's for accessing HW registers, which (IMO) should not be >>> conflated with variables. Thinking that HW registes are "normal >>> variables" is an excellent way to loose a foot. >>> >>> This, of course, raises the question why you would _need_ to place >>> _variables_ at specific addresses when it's not for accessing HW >>> registers. That need seems to me to be rare enough that adding a >>> language feature to support it is foolish. >>> >> >> Agreed. >> >
On 10/03/17 01:54, Walter Banks wrote:
> On 2017-03-09 5:54 PM, Les Cargill wrote: >> >> Hi Walter! No offense, but... >> >> This is utterly 1) inappropriate and 2) unnecessary. It's a >> *terrible* extension. > > Maybe "terrible" but a lot cleaner than a pointer to constant that is > expected to be optimized by a compiler to a simple load store.
First, no one is using a "pointer to a constant" - they are using a constant pointer to a volatile: #define REG (*((volatile uint8_t*) 0x1234)) Secondly, the syntax here is not particularly bad, and it should be clear to anyone who understands C. And since in almost all cases, this sort of thing comes in pre-written headers, the developer is rarely going to have to write it themselves. Yes, I expect a compiler to optimise the use of such a REG. This is not 1980 - even the simplest compilers do a reasonable job on such common constructs. And the compiler has /exactly/ the same information here as it would have with an @ definition - there is no reason why it should be able to optimise one better than the other. (It is different for registers whose address is defined by linker scripts - there, the compiler has less information and cannot generate as optimal code.)
> >> it very nearly destroys the portability of code that uses it... > > and I assume that constant pointer doesn't destroy portability. C > specifically rarely has portable applications.
Some C code is massively portable, other C code is tied tightly to a particular compiler and particular target - C covers a wide span here. The use of the cast constant pointer is portable to any compiler that supports the appropriate types, and has the same interpretation of casting an integer literal to a pointer, and has the same concept of "volatile access". That covers pretty much every C compiler ever written - certainly anything for embedded systems (baring possible limitations on type sizes). The use of @ is limited to a few specific compilers, most of which are for outdated and limited cpu cores.
> > Better that applications be completely contained and either have include > files to define application specific information. The original role of > linkers was to be able to compiler large programs on small computers.
Linkers do a lot more than that - but that is a different argument. I agree that it is nicest to have as much as possible defined as part of the C code and header files, rather than in the linker file (though I accept that some people like to put their fixed addresses in a linker file). The standard method of defining hardware registers using cast pointers puts the addresses in a header file (or occasionally a C file). So again, the @ method gives absolutely no benefit over the standard method.
> > The current state of especially open source compilers is an awful lot of > duplication between the compiler and linkers in the tool sets.
Can you give specifics here, or is it just your prejudice against open source tools?
> Better > that a lot of the linker information be processed much earlier to > develop compile strategies.
If the compiler knows the addresses of the fixed registers at compile time, it can use that information to generate better code. If it knows that REG1 is at 0x1001, and REG2 is at 0x1002, then it can load a cpu pointer register X with 0x1001, and access these two hardware registers at X+0 and X+1 rather than working with their absolute addresses. This is absolutely true, and particularly relevant on more modern cpus with longer addresses and more registers where this sort of optimisation makes a bigger difference. That is why it makes sense to use the standard cast pointer syntax, the "kludge", rather than putting all your hardware addresses in a linker file. And that is one of the reasons why almost everyone /does/ define their hardware addresses that way. There is absolutely /nothing/ here to give any reason to suspect a difference between open source compilers and closed source compilers. And again, the @ method gives you absolutely /nothing/ here that you don't also get with standard C.
> > This is even more true in some of the more interesting ISA that are > currently being developed. I am working on a project that can have > hundreds or potentially thousands of heterogeneous processors being > compiled to from a single application. > > Address setting from application/processor specific header files allows > compilers to be written with far more flexibility and that is far less > computationally intensive. >
Again, the @ method gives you absolutely /nothing/ here that you don't also get with standard C. The @ syntax is a relic from the days of brain-dead compilers with poor optimisation and limited support for normal standard C, usually targeting brain-dead cpus that are also a relic. It is a little neater than the standard C method - defining macros is always ugly, as are pointer casts. But there are /no/ benefits from using the @ syntax like this for a decent compiler. The @ syntax does not give the compiler any more information, and it does not allow any more optimisation. The way it is implemented is often less flexible, since it is often limited to variables of a few specific types, and may require specific fixed formats for the address.
On 2017-03-09 10:07 PM, Grant Edwards wrote:
> Huh? The common method for accessing memory-mapped registers in C > that's been discussed doesn't involve a "pointer to a constant".
Absolutely true it is a constant pointer. w..
On 2017-03-09, Don Y <blockedofcourse@foo.invalid> wrote:
> On 3/9/2017 12:04 PM, Simon Clubley wrote: >> Representing register bitfields as Ada bitfields currently has one >> major limitation in that you cannot directly update multiple >> register bitfields in Ada in a single R-M-W sequence without either >> using a temporary variable or resorting to C style bitmasks. > > But, does that really buy you much -- unless you are sorely resource > (time/space) constrained? (Granted, this can be seen as a different > case of the PUSH/POP issue, above -- e.g., building a synchronization > primitive to wrap a set of *discrete* accesses, etc.) >
Some things you get with being able to update multiple fields within one assignment statement without having to use bitmasks: It allows you to update multiple fields in a device register as part of a single R-M-W sequence without having to use bitmasks or temporary variables. It allows the compiler to do additional error checks on what you are trying to do, which it can't do if you are changing what appears to the compiler as an opaque integer. It makes the code more readable and more robust.
> > One can always come up with new "features" that can have some merit > in some cases. What I'm looking for are the "wow" moments when some > feature made a radical difference in how you approach(ed) problems. >
Understood. Sometimes Don, the problem with these discussions is that you don't provide sufficient guidelines on what you are looking for so people have to guess and as such quite often don't give you the kinds of answers you are looking for. Simon. -- Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP Microsoft: Bringing you 1980s technology to a 21st century world
On 3/10/2017 7:19 AM, Simon Clubley wrote:
>> One can always come up with new "features" that can have some merit >> in some cases. What I'm looking for are the "wow" moments when some >> feature made a radical difference in how you approach(ed) problems. > > Understood. Sometimes Don, the problem with these discussions is that > you don't provide sufficient guidelines on what you are looking for > so people have to guess and as such quite often don't give you the > kinds of answers you are looking for.
What *I'm* looking for isn't important. I'm interested in hearing what *others* "looked for" (by way of "language features") and how they've rationalized their "value". E.g., some folks look for "features" that make debugging easier; some that make the application "terser"; some that make it more robust; etc. If I was interested in which language features... ... facilitate debugging... ... make for terser applications... ... enhance the durability of the application... etc., then I'd have asked those *specific* questions, right? By asking in more abstract terms ("valuable"), I let others decide what is important (in terms of criteria) AND, then, what features they deem "best suiting" THAT particular goal. My followup comments are merely to draw out more detail and "backup" for how they came to that conclusion, not as an assessment *of* their conclusion ("what's your favorite color, and why?")
On 3/10/2017 1:17 AM, Tom Gardner wrote:
> On 09/03/17 23:54, Les Cargill wrote: >> Walter Banks wrote: >>> On 2017-03-05 5:03 PM, Don Y wrote: >>>> A quick/informal/UNSCIENTIFIC poll: >>>> >>>> What *single* (non-traditional) language feature do you find most >>>> valuable in developing code? (and, applicable language if unique to >>>> *a* language or class of languages) >>> >>> The @ in various forms to tie a physical address to a symbolic variable. >>> This construct more that any other single thing allows many high level >>> languages have the ability broaden the range of potential applications >>> from high level to close to the machine. >>> >> >> Hi Walter! No offense, but... >> >> This is utterly 1) inappropriate and 2) unnecessary. It's a *terrible* extension >> to ( I presume C, where I have seen it ). >> >> Even back on Borland, Microsoft, Tektronix and ... another VAX C compiler 30ish >> years ago, you'd use a linker/locater to put specific structures at specific >> locations. >> >> The source code itself doesn't need to know about where variables go[1]. >> >> Its part of the responsibility of tools that are invoked later >> in the build cycle. > > This is a philosophical difference. > > If something is important to the correct operation of > the program, then I like it to be visible in the source > code. A useful benefit is that the information is easily > found and analysed by the IDEs and/or other source code > manipulation tools around.
I guess it depends on what you consider "source code". How do you treat makefiles, linker scripts, etc.? Clearly they are all important to the *intended* operation of the program -- as are the actual tools, themselves. How much of this cruft do you clutter the "sources" with in the attempt to ensure they accompany the sources? What about applications wherein multiple languages are combined; how do you nail down the "implementation defined" behavior of their interfaces? What order will your Java/C/Python/foo function build its stack frame? How will your FORTRAN/Pascal/ASM/bar module interface to it??
> In the same vein, in C I dislike having correct code > operation being dependent on combinations of command > line compiler arguments.
There's usually a difference between "correct" and "desired". It's unfortunate when "correct" relies on command line arguments to resolve some "implementation defined behavior" with which the compiler could, otherwise, take liberties. Likewise, if the order and locations at which objects can be bound can arbitrarily be altered and affect operation [These should be eschewed, IMO] (This is an issue on many processors, without concern for the actual I/O's) Of course, there's no way for the tool to know/enforce these constraints other than a suitable note to the future developer!
>>> It is language independent and very easy to add to compilers without >>> changing the basic form of the language. >> >> it very nearly destroys the portability of code that uses it... > > That seems unimportant to me. I cannot think of a > reason why you would need to nail down addresses > in portable code. Of course "portable" is not a > black and white concept!
Therein lies the rub. Code can be "portable" yet still tied to a particular processor (but a different implementation). E.g., reset_processor()...
> Any examples?