Elijah Miller的NEC V30在PI帽子上

2021-06-05 04:09:30

在谈论家庭时,BREW 8080和8086个在Discord的系统上eBay搜索将我带到了以Elijah的商店页面,那么这个小小的好奇心就是出售。这是一个覆盆子Pi帽子上的NEC v30,仅为15美元!有趣的是,V30可以在3.3V中运行,意味着在PI上的GPIO总线上不需要特殊硬件。这让我如此提醒我的CP / M墨盒为COMMOMORE 64,价格如此正确,我很快就会迅速订购一个,热切期待到2周发货到亚洲。

虽然我有PI 4,我运行Windows 10开启驾驶某些显示器& Power Point,我想使用稍微更快的PI400。 PI400具有兼容的GPIO扩展端口,因此就像墨盒一样,这是打开卡片的简单问题,加电和构建软件。虽然存在包含的二进制文件,但它是一个32bit 1,而我正在在pi400上运行manjaro以获得类似的外观/景象作为pinebook pro。无论如何,依赖是SDL2,以及一个odly命名为“WIRINPI”库,允许C程序接口GPIO。

您可以在Homebrew8088上下载仿真器,特别是Raspberry PI第二项目。最后一个'ver 2'下载具有配置为8086模拟的V30的项目,与V20不同,这是8088的V20。当物理地接地到处理器的事物,如此重要!

使用模拟器建造,很简单地击中它,并启动进入MS-DOS:

我必须承认我一开始就是一点点惊讶,因为我真的不知道这一点是为了工作。我和一个工程师朋友说话,他说直接进入GPIO总线的CPU,并切换连接实际模仿电路板既疯狂,没有任何电气缓冲器,它最有可能炒处理器,也许是pi也是如此。我怀疑这是低电压可能会备受舒缩,虽然我没有EE所以我不会假装知道。

加载Norton Si证实了Elijah在eBay上发布的是它的速度非常缓慢,约1/3速度XT的速度。现在我可能不知道关于硬件的任何东西,但这至少是一个探查者至少可以告诉我发生了什么,如果像我这样的人在巨人的肩膀上直升机可以看到一些东西。

这将构建一个仿真器的成本版本,这将让我们知道哪些函数被称为次数,以及多少时间。不了解其他任何仿真器的任何东西,通常的模式是您花费大多数时间获取和可能翻译内存;两者都在喂养指令和从堆栈和指针推出/弹出数据。等待通常用于初始化和IO。

一旦您运行了配置的可执行文件,它将转储二进制文件GMON.OUT,然后您可以使用GPROF格式化为如下文本文件:

然后查看报告,您可以看到顶级时间以及顶级呼叫的位置。有些事情只是花了一段时间,才能完成,他们经常被称为。

每个样本计数为0.01秒。 %累积自我自我总秒秒秒秒调用S /呼叫S /呼叫名称39.91 0.71 0.71 286883 0.71 286883 0.71 286883 0.00 0 0.00 0 0.200 0 0.200 0.291.30 1.00 0.29 1 0.29 1.02 START_SYSTEM_BUS(INT)12.37 1.22 0.22 1100374 0.22 1100374 0.22 1100374 0.22 1100374 0.22 1100374 0.22 1100374 0.22 1100374 0.22 1100374 0.22 1100374 0.22 1100374 0.23 0.00 data_bus_direction_8086_out()7.87 1.36 0.14 5954106 0.00 0 0.00 CLK()

正如预期的start_system_bus需要1秒钟,后跟一个1,100,374呼叫设置data_bus_direction_8086_out(毫无疑问,PI需要在读取和写入CPU之间交替),后跟CLK函数的5,954,106滴度。当然,真正的罪魁祸首是Print_char_9x16,它被称为286,883次,并负责近40%的Tuntime!

显然,对于简单的MS-DOS启动,屏幕不应在多次附近的任何地方调用任何打印字符。显然有些东西是不对劲。不知道我在print_char_9x16函数的顶部添加了一个简单的计数器,让它只执行1:1000次,我得到了这个:

显然它不对,这意味着罪魁祸首真的不是print_char_9x16,而是呼叫它。这是对每个模式的简单变化,只能呈现一小部分时间,并且我将其改为定义,让我更频繁地发射。这是一个简单的差异,假设WordPress不会拧紧。这不漂亮,但它得到了完成的工作。

$ diff -run ver2 / vga.cpp ver2-j / vga.cpp --- ver2 / vga.cpp 2020-07-29 10:36:51.000000000 +0800 +++ ver2-j / vga.cpp 2021-06- 04 01:51:33.546124473 + 0800 @@ -1,5 +1,9 @@ #include" vga.h" + static int do9x16 = 0; +#定义Vidu 5000 ++ void print_char_18x16(sdl_render *渲染器,int x,int y,无符号char ascii_value){for(int i = 0; i< 9; i ++)@@ -23 ,6 +27,12 @@ void mode_0_40x25(sdl_renderer *渲染器,char * video_memory,char * cursor_position){+ do9x16 ++; + if(do9x16> vidu)+ {do9x16 = 0;} + else + {return;} + int inde = 0; for(int j = 0; j< 25; j ++){@@ -36,6 +46,7 @@ print_char_18x16(渲染器,(cursor_position [0] * 18),(cursor_position [1] * 16),0xdb ); sdl_rederpresent(渲染器); } + void print_char_9x16(sdl_renderer *渲染器,int x,int y,unsigned char ascii_value){for(int i = 0; i< 9; i ++)@@ -57,6 +68,12 @@} void mode_2_80x25( sdl_rederer *渲染器,char * video_memory,char * cursor_position){+ do9x16 ++; + if(do9x16> vidu)+ {do9x16 = 0; +否则+ {return;} + int index = 0; for(int j = 0; j + 25; j ++){@@ -102,6 +119,1212 @@ void graphics_mode_320_200_palette_0(sdl_renderer * renderer,char * video_memory){+ do9x16 ++; + if(do9x16> vidu)+ {do9x16 = 0;} +否则+ {return;} + sdl_renderclear(渲染器); int index = 0; for(int j = 0; j< 100; j ++)@@ -156,6 +179,1212 @@} void graphics_mode_320_200_palette_1(sdl_renderer *渲染器,char * video_memory){+ do9x16 ++; + if(do9x16> vidu)+ {do9x16 = 0;} +否则+ {return;} + sdl_renderclear(渲染器); int index = 0; for(int j = 0; j< 100; j ++)

虽然在控制台上感觉更敏感,但它仍然令人难以置信的速度。 SI返回相同的速度,这意味着我们在尽可能靠近附近的任何地方击中屏幕,但它仍然太多。它真的是GPIO公交限制吗?我不知道。但是下一个函数当然是时钟。

首先,我尝试将浏览的半人数分为一半,也许它不会被称为足够的话。并跑步透露,我从0.3到0.1开始!显然这不是所需的效果!所以我乘以四分之一的鸿沟:

diff -Run Ver2 / Timer.cpp ver2-j / timer.cpp --- ver2 / timer.cpp 2020-08-12 00:32:13.000000000 +0800 ++ ver2-j / timer.cpp 2021-06-04 02:06:25.505904407 + 0800 @@ -7,7 +7,7 @@ {wher(stop_flag!= true){ - elleep(54926); + ULEEP(54926 * 4); IRQ0(); }}

现在它得分1.5!显然这些都是“魔法数字”并绑定到PI400,更重要的是我根本没有研究代码,我不是在尝试贬低或任何东西,如果这只是一个快速的例子,为什么分析你的代码是这样的重要的!与此同时,试图运行游戏是如此令人难以置信的速度慢我甚至不知道我的变化是否对速度的任何实际影响,因为基准的模拟可能是如此的Finickie的事情。

我的goto游戏,Battletech 3025 Crescent Hawks初始加载到第一个飞溅但似乎挂起。我可能会不耐烦,或者可能有进一步的问题,但我只是带有C编译器的一些不耐烦的旅游者......

每个样本计数为0.01秒。 %累积自我自我总时间秒秒拨打我们/呼叫美国/呼叫名称95.41 129.23 129.23 22696621 5.69 5.69 READ_MEMORY_ARRAY(无符号长长,CHAR *,INT)2.90 133.15 3.92 START_SYSTEM_BUS(INT)0.88 134.34 1.19 64369074 0.02 0.0.020 0.0202 0.0202 134.74 0.40键盘()0.16 134.96 0.22 412873 0.53 0.53 PRINT_CHAR_9X16(SDL_RENTERER *,INT,INT,INT,无符号CHAR)0.08 135.07 0.11 11273939 0.01 0.01 0.01 0.01 0.010101010100100.01 0.01 0.01

现在是我对现在调用Read_Memory的大部分仿真的预期,当然,当然我们的命名屏幕渲染器(虽然它仍然太多了!),但数据_bus_direction正在列表中进一步下降。毫无疑问,在呼叫之间发生了一些双重缓冲和检查,可以很长一段时间来优化它,就像实际研究源代码一样。

关于这一点的那么很酷的是,如果我想写一个PC仿真器,请让我的信心让CPU不仅仅是100%的循环准确,而是因为我们使用物理处理器,这是Bug准确的100%错误。