That's true. In the case of Nintendo DS, I'm aligning doing line-based emulation; so I first serially emulate the two CPUs (I could in theory parallelize then, but I haven't properly design the emulator around this, so all memory-mapped callbacks are not concurrent safe), and then emulate the graphic subsystem for a single line, spreading the different layers across different goroutines.
This means that goroutines synchronize 263*60 times per second, which is something. I measure a high contention, so I'm not even sure it was worth in the end, but I thought it was a good experiment to attempt :)
where I configure the memory-mapped registers of the interrupt controller; "wcb" / "rcb" tags stand for write/read callbacks, which means that specific callbacks (with names matching the register names) will be called for each read/write operation; this is all achieved through reflection. The same applies to mapping the whole register bank, which is done here:
https://github.com/rasky/ndsemu/blob/master/nds9.go#L69
The memory subsystem handling these and more features is in emu/hwio, and I'm actually pretty proud of it. For the memory mapping itself, a radix tree is built which is quite quick to lookup and doesn't require much barcoding.
In fact, the whole "emu" package is a generic framework for emulators in Go, and I plan to reuse it in the future :)
This means that goroutines synchronize 263*60 times per second, which is something. I measure a high contention, so I'm not even sure it was worth in the end, but I thought it was a good experiment to attempt :)
Another Go-related thing I did was using struct tags to configure memory-mapped registers in a declarative way. See for instance: https://github.com/rasky/ndsemu/blob/master/irq.go#L13
where I configure the memory-mapped registers of the interrupt controller; "wcb" / "rcb" tags stand for write/read callbacks, which means that specific callbacks (with names matching the register names) will be called for each read/write operation; this is all achieved through reflection. The same applies to mapping the whole register bank, which is done here: https://github.com/rasky/ndsemu/blob/master/nds9.go#L69
The memory subsystem handling these and more features is in emu/hwio, and I'm actually pretty proud of it. For the memory mapping itself, a radix tree is built which is quite quick to lookup and doesn't require much barcoding.
In fact, the whole "emu" package is a generic framework for emulators in Go, and I plan to reuse it in the future :)