<!doctype html>
<html lang="en">

<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

	<title>Emulating the Badge Under Renode</title>

	<link rel="stylesheet" href="dist/reset.css">
	<link rel="stylesheet" href="dist/reveal.css">
	<link rel="stylesheet" href="dist/theme/fossasia2023.css">

	<!-- Theme used for syntax highlighted code -->
	<link rel="stylesheet" href="plugin/highlight/zenburn.css">
</head>

<body>
	<div class="reveal">
		<div class="footer">
			<a class="url" href="https://p.xobs.io/c23/">p.xobs.io/fa23</a>
		</div>
		<div class="slides">
			<section>
				<h2>Emulating the Badge Under Renode</h2>
				<h3>(Eventually)</h3>
				<br />
				<h3>Sean "xobs" Cross</h3>
			</section>
			<section>
				<h2>About Me</h2>
				<img data-src="img/xobs-projects.jpg">
			</section>
			<section>
				<h2>Talk Outline</h2>
				<ol>
					<li>What is Renode?</li>
					<li>How is it extensible?</li>
					<li>What is the state of the badge?</li>
				</ol>
			</section>
			<section>
				<section>
					<h2>What is Renode?</h2>
				</section>
				<section>
					<h2>Whole-system Emulator</h2>
					<ul>
						<li>CPU cores</li>
						<li>Peripherals</li>
						<li>Interconnections</li>
					</ul>
				</section>
				<section>
					<h2>Target platforms</h2>
					<ul>
						<li>Windows</li>
						<li>Mac</li>
						<li>Linux</li>
						<li>
							<ul>
								<li>CI</li>
							</ul>
						</li>
					</ul>
				</section>
				<section>
					<h2>CPU Cores</h2>
					<ul>
						<li>x86</li>
						<li>arm</li>
						<li>arm64</li>
						<li>ppc</li>
						<li>riscv</li>
						<li>spark</li>
						<li>xtensa</li>
					</ul>
				</section>
				<section>
					<h2>Peripherals</h2>
					<img data-src="img/esp32s3-peripheral-list.png">
				</section>
				<section>
					<h2>Peripherals Are Just Special Memory</h2>
					<ul>
						<li>Writing to a memory address does a thing</li>
						<li>Reading from an address gets a result</li>
						<li>Interrupts are just GPIOs</li>
					</ul>
				</section>
				<section>
					<h2>10% of the Functionality Gets You 90% of the Way There</h2>
					<ul>
						<li>E.g. in a serial device, baudrate, timers, and parity/stop can be ignored</li>
						<li>Just "Tx", "Rx", and interrupt setup</li>
						<li>Most software works just fine if you return zeroes for invalid addresses</li>
					</ul>
				</section>
				<section>
					<h2>SVD files are your friend</h2>
					<ul>
						<li>Your chip probably comes with a SVD file</li>
						<li>This gives a map of RAM and peripherals</li>
						<li>Renode can parse this and use it for logging / defaults</li>
					</ul>
				</section>
				<section>
					<h2>Existing Peripherals in Renode</h2>
					<ul>
						<li>Built-in peripherals for a number of devices</li>
						<ul>
							<li>STM32</li>
							<li>NRF52</li>
							<li>IMXRT</li>
							<li>LiteX</li>
						</ul>
						<li>See
							https://github.com/renode/renode-infrastructure/tree/master/src/Emulator/Peripherals/Peripherals
							for more</li>
					</ul>
				</section>
				<section>
					<h2>Creating Peripherals</h2>
					<ul>
						<li>Renode is written in C#</li>
						<li>Like Java, C# has an `eval()` function</li>
						<li>Peripherals can be written and loaded at runtime</li>
					</ul>
				</section>
				<section>
					<h2>Networks in Renode</h2>
					<ul>
						<li>Built-in support for CAN, Ethernet, and Wireless</li>
						<li>Also possible to add networks at runtime</li>
						<li>No latency, just packets of data</li>
						<ul>
							<li>Different devices run at different speeds</li>
						</ul>
					</ul>
				</section>
				<section>
					<h2>Other Goodies</h2>
					<ul>
						<li>LCD monitor with touchscreen support</li>
						<li>Python interpreter for quick hacks</li>
						<li>Attach GDB to any CPU core</li>
						<li>Attach a serial port to a network connection</li>
						<li>Scriptable with Robot framework</li>
						<li>Log function calls</li>
					</ul>
				</section>
				<section>
					<h2>Shortcomings</h2>
					<ul>
						<li>Unable to unload modules</li>
						<ul>
							<li>Need to restart Renode when you change a file</li>
						</ul>
						<li>No real audio support</li>
						<ul>
							<li>Support for verifying I2S, but can't play it</li>
						</ul>
						<li>Only x64 hosts</li>
						<ul>
							<li>Runs under Rosetta on Mac</li>
						</ul>
						<li>Documentation needs work</li>
						<ul>
							<li>Use the source!</li>
						</ul>
					</ul>
				</section>
			</section>
			<section>
				<section>
					<h2>Extending Renode</h2>
				</section>
				<section>
					<h2>First, Betrusted</h2>
					<ul>
						<li>FPGA with VexRiscv</li>
						<li>2nd FPGA with smaller VexRiscv</li>
						<li>16-bit COM bus between them</li>
						<li>AES extensions</li>
						<li>x25519 "ENGINE" accelerator</li>
						<li>SHA accelerator</li>
						<li>Battery charger and manager</li>
						<li>Custom lcd, timers, and USB</li>
					</ul>
				</section>
				<section>
					<h2>Emulating it under Renode</h2>
					<ul>
						<li>Good enough to develop the OS!</li>
						<li>Good enough to catch bugs</li>
					</ul>
				</section>
				<section>
					<h2>ENGINE bug</h2>
					<ol>
						<li>Added test vectors to the OS</li>
						<li>Ran test vectors on physical device</li>
						<li>Got test vectors passing in Renode</li>
						<li>
							<ul>
								<li>Yay!</li>
							</ul>
						</li>
						<li>Someone (without a device!) decided to add more vectors</li>
						<li>Tested in Renode</li>
						<li>Passed</li>
						<li>Failed on hardware</li>
						<li>Bug in detecting overflow condition for normalization in hardware</li>
						<li>https://github.com/betrusted-io/gateware/commit/817e284a3d92037b8cb0686735578d2bb60853e9
						</li>
					</ol>
				</section>
				<section>
					<h2>Getting Started with Renode</h2>
					<ol>
						<li>Renode Platform Definition (<code>.repl</code>)</li>
						<li>Renode Script (<code>.resc</code>)</li>
					</ol>
				</section>
				<section>
					<h2>Example project repl</h2>
				</section>
				<section>
					<h2>Example project resc</h2>
				</section>
				<section>
					<h2>Running it</h2>
				</section>
				<section>
					<h2>How to Extend Renode</h2>
					<ol>
						<li>Find a peripheral that does what you want</li>
						<li>
							<ul>
								<li>You might even find a compatible peripheral!</li>
							</ul>
						</li>
						<li>Copy it to your project</li>
						<li>Change the constructor</li>
						<li>Change the register set</li>
						<li>Import the `.cs` file into Renode</li>
						<li>Add it to your platform file</li>
					</ol>
				</section>
			</section>
			<section>
				<section>
					<h1>Demonstration!</h1>
				</section>
			</section>
			<section>
				<section>
					<h2>Running Badge Software in Renode</h2>
				</section>
				<section>
					<h2>It Doesn't</h2>
				</section>
				<section>
					<h2>Xtensa is an Uncommon Architecture</h2>
					<ul>
						<li>Audio DSPs</li>
						<li>Possibly Intel?</li>
						<li>NXP</li>
					</ul>
				</section>
				<section>
					<h2>Extensive use of Boot ROM</h2>
					<ul>
						<img data-src="img/memory-maps.png">
					</ul>
				</section>
				<section>
					<h2>Extensive use of Boot ROM</h2>
					<ul>
						<pre><code class="wrap">$ esptool.py dump_mem \    
	0x3ff90000 \       
	65536 \
	irom.bin</code></pre>
					</ul>
				</section>
				<!-- <section>
					<ul>
						<li>Immediately get output</li>
						<li>Breaks immediately</li>
					</ul>
				</section> -->
				<section>
					<h2>Add a serial port</h2>
					<code><pre>
namespace Antmicro.Renode.Peripherals.UART {
  public class ESP32_UART : UARTBase, IDoubleWordPeripheral,
							IKnownSize {
    private readonly DoubleWordRegisterCollection registers;
    public ESP32_UART(Machine machine) : base(machine) {
      registers = new DoubleWordRegisterCollection(this,
	  			new Dictionary&lt;long, DoubleWordRegister> {
        {0x00, new DoubleWordRegister(this).WithValueField(0,8,
				writeCallback: (_, v) => TransmitCharacter((byte)v))}
      });
    }</code></code>
				</section>
				<section>
					<h2>Add a serial port</h2>
					<code><pre>
{0x00, new DoubleWordRegister(this)
		.WithValueField(0, 8,
			writeCallback: (_, v) => TransmitCharacter((byte)v))}</code></code>
				</section>
				<section>
					<img data-src="img/esp32s3-uart.png">
				</section>
				<section>
					<h2>Load SVD file</h2>
					<pre><code>sysbus:
	init:
		ApplySVD @esp32s3.svd</code></pre>
				</section>
				<section>
					<h2>Load SVD file</h2>
					<pre><code style="word-wrap: break-word;">
extmem: Unhandled read from offset 0x64.
extmem: Unhandled write to offset 0x64, value 0x3.
sysbus: Read from an unimplemented register SYSTEM:SYSCLK_CONF
	(0x600C0060), returning a value from SVD: 0x1. (3)
sysbus: Read from an unimplemented register SYSTEM:PERIP_CLK_EN0
	(0x600C0018), returning a value from SVD: 0xF9C1E06F.
sysbus: Write of value 0xF9C1E06F to an unimplemented register
	SYSTEM:PERIP_CLK_EN0 (0x600C0018) generated from SVD.
sysbus: Read from an unimplemented register SYSTEM:PERIP_RST_EN0
	(0x600C0020), returning a value from SVD: 0x0.
sysbus: Write of value 0x0 to an unimplemented register SYSTEM:PERIP_RST_EN0 
	0x600C0020) generated from SVD.
sysbus: Read from an unimplemented register SYSTEM:PERIP_RST_EN0
	(0x600C0020), returning a value from SVD: 0x0.
sysbus: Write of value 0x4 to an unimplemented register SYSTEM:PERIP_RST_EN0 (0x600C0020) generated from SVD.						
					</code></pre>
				</section>
				<section>
					<h2>Add Peripherals</h2>
				</section>
				<section>
					<h2>Slowly Advance</h2>
					<img data-src="img/esp32s3-more-boot.png">
				</section>
				<section>
					<h2>GDB with ELF</h2>
					<img data-src="img/gdb-with-elf.png">
				</section>
				<section>
					<h2>What's Left?</h2>
					<ul>
						<li>SPI Controller</li>
						<li>Interrupt Controller</li>
					</ul>
				</section>
			</section>
			<section>
				<h2>Getting involved</h2>
				<ul>
					<li>Try Renode for your projects!</li>
					<li>Add CI tests for your firmware!</li>
					<li>Explore binaries for unknown targets!</li>
				</ul>
				<h2 class="fragment">Thank you</h2>
				<h3 class="fragment">Questions?</h3>
			</section>
		</div>
	</div>

	<script src="dist/reveal.js"></script>
	<script src="plugin/notes/notes.js"></script>
	<script src="plugin/zoom/zoom.js"></script>
	<script src="plugin/markdown/markdown.js"></script>
	<script src="plugin/highlight/highlight.js"></script>
	<script>
		/** This used to be a part of Reveal.js, but was removed at some point */
		function getQueryHash() {
			function deserialize(value) {
				if (typeof value === 'string') {
					if (value === 'null') return null;
					else if (value === 'true') return true;
					else if (value === 'false') return false;
					else if (value.match(/^-?[\d\.]+$/)) return parseFloat(value);
				}
				return value;
			}

			let query = {};
			location.search.replace(/[A-Z0-9]+?=([\w\.%-]*)/gi, a => {
				query[a.split('=').shift()] = a.split('=').pop();
			});
			// Basic deserialization
			for (let i in query) {
				let value = query[i];

				query[i] = deserialize(unescape(value));
			}

			// Do not accept new dependencies via query config to avoid
			// the potential of malicious script injection
			if (typeof query['dependencies'] !== 'undefined') delete query['dependencies'];

			return query;
		}
		var presenter = !!getQueryHash().s;
		var stream = !!getQueryHash().stream;

		// More info about initialization & config:
		// - https://revealjs.com/initialization/
		// - https://revealjs.com/config/
		reveal_dependencies = [
			{ src: 'https://reveal-multiplex.glitch.me/socket.io/socket.io.js', async: true },
		];
		if (presenter) {
			reveal_dependencies.push({ src: 'https://reveal-multiplex.glitch.me/master.js', async: true },);
		} else {
			reveal_dependencies.push({ src: 'https://reveal-multiplex.glitch.me/client.js', async: true });
		}
		Reveal.initialize({
			hash: true,

			controls: presenter ? false : (stream ? false : true),
			progress: true,
			history: true,
			center: true,
			controlsTutorial: presenter ? false : (stream ? false : true),

			slideNumber: presenter ? null : (stream ? null : 'c/t'),

			// The "normal" size of the presentation, aspect ratio will be preserved
			// when the presentation is scaled to fit different resolutions. Can be
			// specified using percentage units.
			width: 1280,
			height: 840,

			// Factor of the display size that should remain empty around the content
			margin: 0.1,

			multiplex: {
				// Example values. To generate your own, see the socket.io server instructions.
				secret: getQueryHash().s || null,
				id: '863f0948d18284f3',
				url: 'https://p.xobs.io/'
			},


			// Bounds for smallest/largest possible scale to apply to content
			minScale: 0.02,
			maxScale: 5.5,

			defaultTiming: 41,

			transition: 'slide', // none/fade/slide/convex/concave/zoom

			// Don't forget to add the dependencies
			dependencies: reveal_dependencies,

			// Learn about plugins: https://revealjs.com/plugins/
			plugins: [RevealMarkdown, RevealHighlight, RevealZoom, RevealNotes]
		});
	</script>
</body>

</html>