You are here

VLM Optimisation

The VLM (Vital Logic Module) was the ladder logic processing module at the heart of a railway interlocking unit. As is so often the case, requirements had changed over the years and now more performance was needed. My brief was to find ways to increase its capacity, in effect to speed it up so that it could process more logic per cycle. The work fell into two parts, looking at hardware changes and looking at software changes. The hardware study of different processor options etc. was all standard stuff, it was the software changes study that was the most interesting.

In fact, I think that the study of the software was commissioned just be be thorough. The recursive logic processing routines had already been converted to assembler and it was not anticipated that any significant speed increase could be realised. The other software modules were all in a high level language but as most of the time was spent processing logic then they have little effect overall.

However, the assembler code used was straight out of the MASM book, that is guaranteed to always work but by no means the optimum. I made use of registers and kept variables that would be reused, short jumps, tree processing (i.e. testing as >8, >4, >2, rather than ==8, ==7, ==6, etc.) and using compares for multiple jumps (i.e. >8 followed by <8). The final result being a factor of 2 improvement in speed. An impressive improvement for little outlay.

Before leaving embedded software there is one other little example I think worthy of mention. This unit required that an input be sampled and the number of times it was above a threshold be counted. The standard way to do this would be:

mov ax, [input_address]
cmp ax, threshold_constant
jl $+1
inc cx

However the code was running on an 8086 processor which has a 4 word prefetch that it clears each time a jump is taken. Hence the loop time would vary depending on the state of the input, above the threshold and the loop time would be longer. This was not acceptable and neither was using interrupts. The solution I came up with was based on a hardware engineer's appreciation of how the processor actually worked. The compare was doing a subtraction but throwing away the result. The state of the carry bit determined the jump so it could be used instead. So the final code was:

mov ax, [input_address]
cmp ax, threshold_constant
adc cx,0

And with this code the loop time is constant.