As embedded systems become more complex, designers face a number of challenges at different levels: they need to boost performance, while keeping energy consumption as low as possible, they need to reuse existent software code, and at the same time they need to take advantage of the extra logic available in the chip, represented by multiple processors working together. This book describes several strategies to achieve such different and interrelated goals, by the use of adaptability. Coverage includes reconfigurable systems, dynamic optimization techniques such as binary translation and trace reuse, new memory architectures including homogeneous and heterogeneous multiprocessor systems, communication issues and NOCs, fault tolerance against fabrication defects and soft errors, and finally, how one can combine several of these techniques together to achieve higher levels of performance and adaptability. The discussion also includes how to employ specialized software to improve this new adaptive system, and how this new kind of software must be designed and programmed.