The Elements of Computing Systems is a book that has the reader build a computer architecture in software, starting with only a NAND and DFF gate and culminating in creating a Java-like OOP programming language. Each chapter focuses on one layer of the architecture, with the user building his own implementation at the chapter's end. Given the book's expansive focus, its treatment of each topic is necessarily brief, but it still succeeded in granting me an appreciation of how the simplest logical elements give rise to the wonderful complexity of the modern computer. Futhermore, the book demonstrated excellent use of test-driven development, for test scripts accompanied each project, with the reader encouraged to iterate until his implementation passes all tests.
My implementations of the book's earlier projects, such as rudimentary logic gates and an arithmetical logic unit, are written in the book's own hardware description language, with later projects, such as an assembler, developed in Python.