{"id":60,"date":"2025-01-23T10:04:38","date_gmt":"2025-01-23T10:04:38","guid":{"rendered":"https:\/\/www.soapyfrog.com\/?p=60"},"modified":"2025-01-23T10:05:08","modified_gmt":"2025-01-23T10:05:08","slug":"building-the-synthetic-cpu","status":"publish","type":"post","link":"https:\/\/www.soapyfrog.com\/index.php\/2025\/01\/23\/building-the-synthetic-cpu\/","title":{"rendered":"Building the synthetic CPU"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Following on the <a href=\"https:\/\/www.soapyfrog.com\/index.php\/2025\/01\/01\/on-the-dangers-of-an-unfocused-mind\/\" data-type=\"post\" data-id=\"55\">last post<\/a>, I&#8217;m keeping focus on the plan, which is to move SoapyBASIC from an interpreter written in Swift to a compiler written in Swift, tagging an Instruction Set Architecture (ISA) that I need to design, and of course the CPU to implement that ISA.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The ISA<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Three weeks in to 2025 and I&#8217;m settled in an ISA that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>RISC-inspired load\/store architecture<\/li>\n\n\n\n<li>32, 64-bit general purpose registers and 32, double precision floating point registers.<\/li>\n\n\n\n<li>Fixed size instructions (32-bit)<\/li>\n\n\n\n<li>Optional setting of condition flags on arithmetic and logic operations.<\/li>\n\n\n\n<li>Can work with different data sizes (64,32,16,8-bit integer and 64,32,16-bit floating point)<\/li>\n\n\n\n<li>Easy for humans to read and write in assembler\/mnemonic form. GET\/SET\/COPY\/ADD etc.<\/li>\n\n\n\n<li>CISC enough to be performant in a simulated CPU (let&#8217;s face it, this is never going to be silicon!)<\/li>\n\n\n\n<li>RISC enough so I don&#8217;t feel ill.<\/li>\n\n\n\n<li>Superuser \/ user protection, system calls<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">This design is just about done. Making a few tweaks here and there, but I want to stay focused and move on to implementation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The CPU<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">My CPU is written in Swift but I&#8217;m looking to implement parts in C. Indeed I may write the majority of it in C as C is so much more expressive at the bit level. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Everything works on macOS (Apple Silicon) and Linux (x86_64).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Work done so far:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Implementation of memory and addressing<\/li>\n\n\n\n<li>Instrument fetch and decode<\/li>\n\n\n\n<li>Partial implementation of the ISA (enough for arithmetic and looping)<\/li>\n\n\n\n<li>Debugging helpers.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Challenges<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Challenges so far&#8230;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Documentation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Annoyingly, one of the main challenges I faces was deciding whether to document my ISA in MarkDown or in an Apple Pages document!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The latter looks better, and is easier to read, but harder to version control well. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I flip-flopped between the two a few times, but ended up with Pages.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But once I wrote a Swift enum for representing the instructions, I started moving the documentation there. At least this way, if I make changes, the documentation follows automatically.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Swift 6 language<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Swift 6 language mode, along with its structure concurrency safety can be a right pain in the arse, and forces you to choose between unnatural architectural choices (for something that is inherently single-threaded) or label your code as crap (I think there&#8217;s a swift proposal to walk back on this).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve decided to go for the unnatural choices, partly because it&#8217;s not really wrong, and partly because I&#8217;m going to have to mix in with C or unsafe Swift during this process.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eg, Swift doesn&#8217;t have a fixed size array type ( <a href=\"https:\/\/github.com\/swiftlang\/swift-evolution\/blob\/main\/proposals\/0453-vector.md\">https:\/\/github.com\/swiftlang\/swift-evolution\/blob\/main\/proposals\/0453-vector.md<\/a> isn&#8217;t there yet ). Swift Array is too expensive, so I&#8217;m resorting to unsafe pointers to memory or structures.  But at that point you might as well mix in some C code. And at that point you might as well do it all in C!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Next Steps<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Complete core CPU implementation and a validation suite of tests. This includes full arithmetic and logic instructions, integer and floating point.<\/li>\n\n\n\n<li>Implement handlers for system calls for writing data out to host stdout.<\/li>\n\n\n\n<li>A very simple assembler to make writing test code easier.<\/li>\n\n\n\n<li>An working program to emit the mandlebrot set in text (see below).<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Mandelbrot test program<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">My SoapyBASIC interpreter runs a program to produce this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"954\" height=\"843\" src=\"https:\/\/www.soapyfrog.com\/wp-content\/uploads\/2025\/01\/mandelbrot-output2.png\" alt=\"\" class=\"wp-image-64\" srcset=\"https:\/\/www.soapyfrog.com\/wp-content\/uploads\/2025\/01\/mandelbrot-output2.png 954w, https:\/\/www.soapyfrog.com\/wp-content\/uploads\/2025\/01\/mandelbrot-output2-300x265.png 300w, https:\/\/www.soapyfrog.com\/wp-content\/uploads\/2025\/01\/mandelbrot-output2-768x679.png 768w\" sizes=\"auto, (max-width: 954px) 100vw, 954px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The program is:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"954\" height=\"741\" src=\"https:\/\/www.soapyfrog.com\/wp-content\/uploads\/2025\/01\/mandelbrot-output2-listing.png\" alt=\"\" class=\"wp-image-65\" srcset=\"https:\/\/www.soapyfrog.com\/wp-content\/uploads\/2025\/01\/mandelbrot-output2-listing.png 954w, https:\/\/www.soapyfrog.com\/wp-content\/uploads\/2025\/01\/mandelbrot-output2-listing-300x233.png 300w, https:\/\/www.soapyfrog.com\/wp-content\/uploads\/2025\/01\/mandelbrot-output2-listing-768x597.png 768w\" sizes=\"auto, (max-width: 954px) 100vw, 954px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In SoapyBASIC interpreted, this takes about 50ms on my old M1 MacBookPro.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The &#8220;machine code&#8221; version on my synthetic CPU should be at least ten times faster, I think &#8211; it&#8217;s still interpreted after all.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s see!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Following on the last post, I&#8217;m keeping focus on the plan, which is to move SoapyBASIC from an interpreter written in Swift to a compiler written in Swift, tagging an Instruction Set Architecture (ISA) that I need to design, and of course the CPU to implement that ISA. The ISA Three weeks in to 2025 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":67,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,16,15],"tags":[17,21,18,12,20],"class_list":["post-60","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-soapybasic","category-swift-lang","category-virtual-machines","tag-basic","tag-instruction-set-architecture","tag-retrocomputer","tag-soapybasic","tag-swift-lang"],"_links":{"self":[{"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/posts\/60","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/comments?post=60"}],"version-history":[{"count":3,"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/posts\/60\/revisions"}],"predecessor-version":[{"id":69,"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/posts\/60\/revisions\/69"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/media\/67"}],"wp:attachment":[{"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/media?parent=60"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/categories?post=60"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.soapyfrog.com\/index.php\/wp-json\/wp\/v2\/tags?post=60"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}