Testing multi-port memories: Theory and practice