#ifdef HW_REVISION_1
#ifdef HW_REVISION_2
etc
You shouldn't clutter your code with ifdef. It makes it hard to think with.
If you look here http://plan9.bell-labs.com/sources/plan9/sys/src/9/
You can see that port & boot are the portable code. Each architecture can fall back on that less optimised code should it need to.
Then each of the directories: bcm, kw, mtx, omap, pc, pcboot, ppc, rb, teg
have platform specific c files
This greatly eases porting to a new architecture and also means cross compilation is significantly easier.
#ifdefs are rare in the source code and other pragmas are few and far between.
Conditional compilation is the enemy of readable code.
Using many small object files is my solution of choice but it pushes the if/else/endif problem into the Makefile instead.
I know people who use the file header to autodetect the right architecture but I found it too overkill and weird-bug-prone.
[1] At the risk of starting a flame war, this situation and those like it have really soured me on the rest of the industry's obsession with "big O" for complexity analysis. I have never found it useful; I always needed to pay attention to the stuff I was supposed to be dropping.
You are absolutely right. It's a real effort of architecture, and sometimes one of the marks of a great projects. EDIT (thinking of a bad experience of mine): Sometimes, this compartmentalization is also unnecessary and force the architecture to be far worse, too loosely coupled and hard to follow.
> There was no way to separate the code the way you describe without implementing it twice.
Your mileage may vary but implementing it twice can be the best solution if there was so many dependencies to the platform. You should then document the algorithm and reference this documentation in each implementation so that they don't diverge too much. That's not always the best solution, thought. There's no silver bullet in this world...
Well, the architecture of what I was working on was not going to win any awards. :P It was made worse because we were converting code that was originally implemented to run on DSPs.
> Your mileage may vary but implementing it twice can be the best solution if there was so many dependencies to the platform. You should then document the algorithm and reference this documentation in each implementation so that they don't diverge too much. That's not always the best solution, thought. There's no silver bullet in this world...
Standard practice was for systems engineers[1] to create Algorithm Description Documents and Algorithm Implementation Documents that explained in mathematical formulas (ADD) and pseudocode (AID) what the code was doing. At least. that was the theoretical practice. The actual practice was a mess. But yes, there is no silver bullet.
[1] Which was me, even though I got to write lots of code, too.
> At least. that was the theoretical practice. The actual practice was a mess. :( This another big problem yet to solve...
First was that the chips were fixed-point. That mainly changed the arithmetic of the individual algorithm steps, but it led to some really strange number packing schemes[1] that affected memory layout and added a bunch of code just for dealing with them.
Second was the concept of "on-chip" and "off-chip" memory. The chips did not have a conventional memory bus. Instead, the program had to manually make a DMA request to move data on-chip for processing. This was basically a stack memory space local to the DSP core. It was the only memory space the core could access directly, though. Thus, algorithms had to be implemented such that they moved memory on-chip in blocks, processed the data, then moved it back off-chip. Since these movements were expensive, the implementation also tried to chain as many things together on the core in order to minimize the DMA transactions.
Needless to say, these make for extremely inefficient code in some cases when you try to recompile on a real processor or controller that actually has an FPU and memory controller.
[1] If you have never tried working with complex numbers on a fixed-point processor, don't.