Debugging Systems-on-Chip: Communication-centric and Abstraction-based Techniques