jerome.martin.dev
2018-7-12 07:45:45

@soegaard2 Thanks for the link! I’m doing a 6800 emulator in Racket right now but I’m planning to support more MPUs. I made a s-expr DSL for writing MPUs so I can theoretically support any of them, except surely slower than a real dedicated emulator (I didn’t really test performance yet).


jerome.martin.dev
2018-7-12 07:46:22

As its my first time writing such software I was unaware of such tricks. I’ll see how they apply in Racket :slightly_smiling_face:


jerome.martin.dev
2018-7-12 07:48:30

I guess it won’t be that difficult to optimize basic perfs as most of the DSL is macros, so stuff gets inlined as it compiles.


jerome.martin.dev
2018-7-12 07:54:48

For example, right now operations are generated as class methods. I don’t know how it relates in performance to using a C switch, but classes in Racket are mostly compiled into closures I guess so the call overhead might not be that important. I’ll see when I get into optimization phase, right now I’m just focused on finishing the base implementation (even Decimal Adjust Accumulator, which is a pain, but I wanted to emulate everything :stuck_out_tongue: )


kennethdevel
2018-7-12 08:30:56

What is a macro?


notjack
2018-7-12 08:38:18

@kennethdevel this might not be a useful description, but: y’know how you can write functions and classes to abstract over patterns in what your code does when run? macros let you abstract over patterns in what your code does when compiled. like how “for” loops are really just an abstraction over writing “while” loops in a certain way


notjack
2018-7-12 08:39:42

or how pattern matching is an abstraction over lots of ifs, switches, and variable declarations


kennethdevel
2018-7-12 08:41:01

So we use macros to make coding easier?


notjack
2018-7-12 08:42:04

Macros make many things easier, but more importantly they make many more things possible that previously were impossible. Racket for loops and pattern matching are both implemented as macros in regular racket libraries - they’re not “language features” like in other languages. In a language without macros, if the language didn’t offer pattern matching there’s no way you could build it yourself.


notjack
2018-7-12 08:43:10

racket libraries can even create entire static type systems with compile-time checking and runtime type-directed optimizations


kennethdevel
2018-7-12 08:55:51

That’s pretty cool


notjack
2018-7-12 08:56:08

I think so too :)


kennethdevel
2018-7-12 09:01:46

Is there any examples of small and useful macros so I can see how they look?



githree
2018-7-12 09:08:05

Here are some examples of syntax-parse in use: http://docs.racket-lang.org/syntax-parse-example/index.html


kennethdevel
2018-7-12 09:33:15

Reading it now, interesting text.


jerome.martin.dev
2018-7-12 09:56:02

After checking racket/private/class-internal.rkt, it looks like (send) is doing a hash-ref then a vector-ref, so I guess it’s a bit slower than a C switch after all.


andreiformiga
2018-7-12 13:16:06

@jerome.martin.dev I was using a hash table for decoding, but wanted a jump table (something like a switch). I changed the decoder to use a vector, indexed by opcode, got a 30% speed up


jerome.martin.dev
2018-7-12 13:17:55

In the racket/class code it looks like method names are indexed in a hashtable that gives the method index, then the index is used to access a method vector.


andreiformiga
2018-7-12 13:18:01

profiling confirmed that decoding was one of the main bottlenecks



jerome.martin.dev
2018-7-12 13:21:53

I guess I’ll have to do the same kind of optimization as you then, if it happens to be a bottleneck for me too


andreiformiga
2018-7-12 13:29:05

another point is memory, the colecovision for example uses mirrored RAM where the RAM block is mirrored 8 times, so a memory access can’t be a single vector-ref


andreiformiga
2018-7-12 13:29:38

I have some ideas to optimize this that I’ll try later


jerome.martin.dev
2018-7-12 13:33:17

On my side, I’m letting the user provide a memory decoder specific to the machine he/she wants to emulate, so I don’t have to handle that, I just use a parameter like ((current-address-decoder) the-address) to get the data from memory


jerome.martin.dev
2018-7-12 13:33:56

the machine implementation can therefore use whatever data structure fits the best


andreiformiga
2018-7-13 04:49:22

sprites & graphics are working, but the emulation is still at ~8MHz


andreiformiga
2018-7-13 04:49:50

how do I add a few milliseconds of delay? (sleep 0.002) does not seem to work here


andreiformiga
2018-7-13 04:50:24

the delay is to sync the emulation with the real clock speed at 3.58MHz