Wrapping XC in c++ is rubbish

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
Interactive_Matter
XCore Addict
Posts: 216
Joined: Wed Feb 10, 2010 10:26 am

Wrapping XC in c++ is rubbish

Post by Interactive_Matter »

... says folknology: https://twitter.com/folknology/status/50485987511500800 & https://twitter.com/folknology/status/50486656867909633

I personally think that C++ gives you a number of advantages over raw XC:
  • You hide the private configuration - e.g. as used by the spi_master_interface interface in the SPI library
  • You can introduce virtual functions and define contracts by it. So e.g. all implementations of programmable LED constant current drivers implement the interface 'LED_driver'.
Don't get me wrong I do not want to throw XC away. XC is a great low level programming language for XMOS devices. The C++ objects would be mere wrappers around those functions to make implementing everything easier in its place:
  • (some) algorithms, channel communication, timing and so on in XC
  • high level interface, high level wiring in C++
So this post is about asking folknology (and of course all of you what he/you/they think ...


User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

Wrapping XC in c++ is rubbish
First of all a slight correction, I didn't say it was rubbish, I merely indicated it wasn't the best solution, and that perhaps a behaviour/event model might be a better abstraction that an object oriented one.

However I would like to see a simple example of C++ wrapping XC from your self before I go further, do you have one like perhaps an SPI example?

regards
Al
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

This should also be included as it was part of the conversation
folknology

@interactmatter I think XC lacks protocols, modular namespace & perhaps closures but it has no need for object orientation IMHO
regards
Al
Last edited by Folknology on Wed Mar 23, 2011 10:53 am, edited 1 time in total.
User avatar
Interactive_Matter
XCore Addict
Posts: 216
Joined: Wed Feb 10, 2010 10:26 am

Post by Interactive_Matter »

Folknology wrote:
Wrapping XC in c++ is rubbish
First of all a slight correction, I didn't say it was rubbish, I merely indicated it wasn't the best solution, and that perhaps a behaviour/event model might be a better abstraction that an object oriented one.
OK, I confess I have put it a little drastic to make the topic more interesting. I completely respect your opinion and this post is about learning more
Folknology wrote: However I would like to see a simple example of C++ wrapping XC from your self before I go further, do you have one like perhaps an SPI example?

regards
Al
Sorry burried deep in my project around the Led strings - but experiments around this is on my to do list. But here is a theoretical sketch:

The SPI interface is an object, handing in the ports, clocks and clock division as parameters. Internaly they are stored for the XC implementation in the struct spi_master_interface. The constructor would call spi_init
The destructor would call spi_shutdown.

spi_out_* would be hidden in member function write(), function overloading would automatically select the right function spi_out_word, spi_out_short, spi_out_byte, spi_out_buffer.

I do not know if this would be done for the read function - because then you would need to hand in the result variable as reference not the nicest way. But perhaps the cleanest way in using overloading.

By that you can reduce the interface virtuall to two functions: read & write.
User avatar
octal
XCore Addict
Posts: 228
Joined: Thu Jan 27, 2011 3:30 pm
Location: Argenteuil - France

Post by octal »

I'll not discuss the C++ overhead as with actual optimizing compilers and by limiting ourselves to one level of inheritence, this becomes really negligible. Also if the compiler is written in a way to handle inheritance "statically", the overhead will almost become almost null.

I understand your point, you want to have something like the Arduino framework, but this is not the best way to program XMOS I think.

I don't think C++ will be a needed addition for programming XMOS devices.

Programming XMOS devices is more like dealing with event handling and behaviour description than handling entities (objects).
Nothing can forbid you from seeing SPI as an object (object means class implementation and instances when needed).
But for me, when I see an XMOS doing SPI, I see it the opposite way, I see it more as PORTS objects having a certain behaviour (the protocol), handling events and answering them than an SPI port (in old hardware devices on other mcu) doing communications.
What I mean is that the main entity is the PORT doing something and behaving in a certain way. The SPI, I2C, ... protocols here will become simple behaviours, not main actors!
XMOS enforces that in the fact that this "behaviour" can be changed on the fly since everything is software configurable (at certain limits).

Once you got this point of view, having protocols encapsulated in C++ classes becomes useless.
You'll find yourself mostly describing the port behaviour using almost linear descriptions (as is actually XC doing and doing it extremely well) than writing/dealing with hierarchies of objects.
Don't forgot also that, in that, with XMOS dev tools you have an extremely valuable tool, the timing analyzer. I think that this kind of tool becomes impossible to develop if it had to analyze your code through hierarchies (dynamic and virtual methods will make it mad).

I think that what is really needed to make code "cleaner" and more structured is namespaces and some privacy management!
Having namespaces will already change a lot of things.

As a personal tought, I know that C (and its derivatives) is THE FACTO standard in embedded world, so this makes things difficult to change. But I think that we need a clean programming language, with members cleanly private/public, and with some kind of encapsulation without loosing the "linearity" of algorithms in the XC way (to keep timing analyzing tools affective and less complex to develop).
(Don't kick me of :mrgreen: ), but I think that for such tasks, the best language that need to be ported to XMOS platform is something like Oberon7 or Modula2/3 !!!
It solves the pb of encapsulation (via modules and exported/private methods) without imposing inheritance and object orientation.
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

The SPI interface is an object, handing in the ports, clocks and clock division as parameters. Internaly they are stored for the XC implementation in the struct spi_master_interface. The constructor would call spi_init
The destructor would call spi_shutdown.
These are what I would classify as module lifecycle functionality, controlled by messages over channels

spi_out_* would be hidden in member function write(), function overloading would automatically select the right function spi_out_word, spi_out_short, spi_out_byte, spi_out_buffer.
Again I would use channels (and protocols) to output to an SPI module. Protocols would determine frame/width etc.. with the benefit of typing the interface (obviously we have to work around this for now as we lack protocols, but could use structured headers for example).
I do not know if this would be done for the read function - because then you would need to hand in the result variable as reference not the nicest way. But perhaps the cleanest way in using overloading.
This is important and a place I believe your plan may come unstuck please provide a basic example and I will expand.
By that you can reduce the interface virtuall to two functions: read & write
Or a single/dual channel/s interface (reading and writing is implicit)

regards
Al
User avatar
Interactive_Matter
XCore Addict
Posts: 216
Joined: Wed Feb 10, 2010 10:26 am

Post by Interactive_Matter »

octal wrote:I'll not discuss the C++ overhead as with actual optimizing compilers and by limiting ourselves to one level of inheritence, this becomes really negligible. Also if the compiler is written in a way to handle inheritance "statically", the overhead will almost become almost null.
Agreed. Embedded should embrace C++ since it is there for a (good) reason!
octal wrote: Programming XMOS devices is more like dealing with event handling and behaviour description than handling entities (objects).
Nothing can forbid you from seeing SPI as an object (object means class implementation and instances when needed).
But for me, when I see an XMOS doing SPI, I see it the opposite way, I see it more as PORTS objects having a certain behaviour (the protocol), handling events and answering them than an SPI port (in old hardware devices on other mcu) doing communications.
What I mean is that the main entity is the PORT doing something and behaving in a certain way. The SPI, I2C, ... protocols here will become simple behaviours, not main actors!
XMOS enforces that in the fact that this "behaviour" can be changed on the fly since everything is software configurable (at certain limits).
From my point of view this perhaps describes our point of view best:
I am looking at the XMOS as a system - and therefore wanting to implement a certain behaviour in it (the program). That you have ports with protocols on them is an easy way for me to flexibly use all the ports available.
Your description seems to me representing an FPGA like structure, that you have a chip with some pins and that is responds in a certain way if you dirve signals to the pins.

Did I get you right?
octal wrote: Don't forgot also that, in that, with XMOS dev tools you have an extremely valuable tool, the timing analyzer. I think that this kind of tool becomes impossible to develop if it had to analyze your code through hierarchies (dynamic and virtual methods will make it mad).
Never got that really working for me with XC - so still so much to learn for me ;)
octal wrote: I think that what is really needed to make code "cleaner" and more structured is namespaces and some privacy management!
Having namespaces will already change a lot of things.

As a personal tought, I know that C (and its derivatives) is THE FACTO standard in embedded world, so this makes things difficult to change. But I think that we need a clean programming language, with members cleanly private/public, and with some kind of encapsulation without loosing the "linearity" of algorithms in the XC way (to keep timing analyzing tools affective and less complex to develop).
(Don't kick me of :mrgreen: ), but I think that for such tasks, the best language that need to be ported to XMOS platform is something like Oberon7 or Modula2/3 !!!
It solves the pb of encapsulation (via modules and exported/private methods) without imposing inheritance and object orientation.
OK not enough experence with Oberon7 and Modula.
But how do you handle contracts then? E.g. you can have a contract of a 1 channel analogue digital converter and by implementing the contract you can swap the converter without changing much of your code.
The ADC contract woul then allow you t read a value and would give you information about timing and precision. Or is this again a too system-like point of view?
User avatar
Interactive_Matter
XCore Addict
Posts: 216
Joined: Wed Feb 10, 2010 10:26 am

Post by Interactive_Matter »

Folknology wrote:
The SPI interface is an object, handing in the ports, clocks and clock division as parameters. Internaly they are stored for the XC implementation in the struct spi_master_interface. The constructor would call spi_init
The destructor would call spi_shutdown.
These are what I would classify as module lifecycle functionality, controlled by messages over channels

spi_out_* would be hidden in member function write(), function overloading would automatically select the right function spi_out_word, spi_out_short, spi_out_byte, spi_out_buffer.
Again I would use channels (and protocols) to output to an SPI module. Protocols would determine frame/width etc.. with the benefit of typing the interface (obviously we have to work around this for now as we lack protocols, but could use structured headers for example).
I do not know if this would be done for the read function - because then you would need to hand in the result variable as reference not the nicest way. But perhaps the cleanest way in using overloading.
This is important and a place I believe your plan may come unstuck please provide a basic example and I will expand.
By that you can reduce the interface virtuall to two functions: read & write
Or a single/dual channel/s interface (reading and writing is implicit)

regards
Al
Omitting completely to respond your answer in detail I just read the following from it:
To make XC want me forget C++ we need in XC:
  • Modules with name spaces and private data
  • protocols to get around this 'encode data in channels' mess
If you add some kind of contract so that different modules can fulfill the same contract (see my example about ADCs above you got me ;)

Are contracts hierarchical? IS a multi input ADC a specialisation of a single input ADC?

Update: And would you instantiate modules?
User avatar
Interactive_Matter
XCore Addict
Posts: 216
Joined: Wed Feb 10, 2010 10:26 am

Post by Interactive_Matter »

Folknology wrote:
I do not know if this would be done for the read function - because then you would need to hand in the result variable as reference not the nicest way. But perhaps the cleanest way in using overloading.
This is important and a place I believe your plan may come unstuck please provide a basic example and I will expand.
By that you can reduce the interface virtuall to two functions: read & write
Or a single/dual channel/s interface (reading and writing is implicit)

regards
Al
Ok this needs a detailed answer. an Ovlerloaded read function could look like

void read(char &result);
void read(short &result);
void read(int &result);

Theoretical clean but probably a bit awkward to use
User avatar
Folknology
XCore Legend
Posts: 1274
Joined: Thu Dec 10, 2009 10:20 pm

Post by Folknology »

Omitting completely to respond your answer in detail I just read the following from it:
We do need to cover this, else we mis one of the most important advantages
To make XC want me forget C++ we need in XC:
Modules with name spaces and private data
protocols to get around this 'encode data in channels' mess
Yup modules with namespaces make stuff more readable and its a nice to have

Protocols are essential longterm so the compiler can check the contract, in the meantime we can use documentation and practice instead (think dynamic language approach)
If you add some kind of contract so that different modules can fulfill the same contract (see my example about ADCs above you got me
This is simpler than theSPI example really as it only inputs data, over a channel. The module does however support config/control via a channel.
Are contracts hierarchical? Is a multi input ADC a specialisation of a single input ADC?
It would be trivial for the ADC module to provide an array of input channels as manys as are required for the application configured at start up.

regards
Al
Last edited by Folknology on Wed Mar 23, 2011 11:36 am, edited 1 time in total.