你难过的太假装, 你凭什么念念不忘?

你难过的太假装, 你凭什么念念不忘? --陈雪凝《假装》

上一章讲了,呃。。。好像没讲什么东西,只是提到了一些只读寄存器的初始值。当然,停更许久之后的开篇也不能要求太高,毕竟我已经许久没有码字了。回去重新浏览了一遍之前写的文章,在对自己行文感到尴尬的同时,也发现自己的闲白水平其实局限在“吃喝”上了。当然,这本书是着重于技术的,所以不能谈论“嫖赌”(好像不是技术文章也不能哦),那么我会多讲一点“玩乐”。

其实我是一个不善于玩乐的人,无论是去参加大型party还是出去旅游,我都不是很乐忠于参加。特别是出去旅游,一天天走的要死要活,去看一些能够想象到的景象或者景观,实在是不那么吸引人。我最喜欢的旅游方式就是找一个人烟稀少的山区里,对着湖发呆,享受一点点安逸。那么是不是我也会喜欢海岛呢?答案是否定的,作为一个海边长大的人,对海对有一份热爱,但绝不是度假想要的感觉,海虽然美,但不够静。在我个人的感受里,真正的宁静只属于茂盛的草原湖畔和清凉干爽的山林,当然,还不能有蚊虫。无论是清晨还是傍晚,都是享受这种生活的绝佳时光。特别是从暮色将至的时候,总能让人忘掉一切烦恼,像极了做成了一件伟大的事业后退休的生活。

好吧,因为作者去度假了,此文结束。。。

讲完闲白是不是该讲正文了呢?其实不然,因为还没讲题目呀。这个题目看上去起的很无厘头,跟GPU Simulator没有什么必然联系,其实。。。联系确实不大,这篇文章会讲在假装GPU的时候做的取舍。首先我们必须明确一个概念,真的假不了,假的也真不了,我们所能做的,或者说是应该做的,是在需求的范围内,做到”基本表现相同“,不然的话了为什么不直接在真的GPU上写驱动呢? 明确了这一点,我们又需要说明,我们的需求是什么。不同于其他的那些用于仿真新的硬件设计的Simulator,我们是为了开发驱动方便(如果你还能记得这本书的初衷的话了)才去写的这个模拟器。所以我们有一个最重要的准则,就是不到万不得已不能去改原来驱动的代码,要让这个模拟器能完全适应现有的驱动。只有当模拟器开发完了,我们才去保持模拟器的代码不动,去测试新的驱动。

那么模拟器如何能让驱动的开发方便呢?其一便是我们能知道详细的GPU和驱动的交互,如果没有模拟器,我们只能知道驱动往GPU里写了什么指令,但是GPU发起的操作,却很难知道。除非我们在每个可能的地方都写一个print函数,但这样成本其实很高。其二,模拟出来的硬件不会panic,无论你进行了何种操作,这个操作都不会产生很糟糕的影响。最后,现有的集成了Mali GPU的平台性能都很孱弱,拿Hikey 970为例,只有4个大核和4个小核,即使是大核也只有区区2.36GHz的频率。习惯了有几十个核心的工作站之后,实在是不想在这样一个平台上进行编译。

在这些要求,模拟器的开发有两个主要问题,硬件的原子性和中断的处理。首先是硬件的原子性,根据我的观察,如果驱动向GPU写入一个命令,那么这个命令的结果必然能被下一次读取读到。比如说,如果我写入了一个POWER ON某个核心的命令,那么即使我立马去读取核心状态,这个核心也会被标记为已启动。在这种情况下,我们每次写一个寄存器,都要block住驱动,直至硬件方面完成操作。但我在实现这个功能的时候偷了懒,因为我直接在写入寄存器之后检查所有的寄存器,并进行相应的处理,如果处理过程中又写了寄存器,那么我们就递归的调用这个处理函数,直到寄存器状态不再改变。目前来看这个方法没有什么大问题。

另一方面,中断的处理也是个问题,其中的问题倒不是软件raise一个中断不那么方便,而是我们想知道中断更多的细节。运行在中断context的中断处理例程明显不是那么的令人满意。所以这个地方我没有装的特别像,每当要处理中断的时候,就有一个kthread被建立起来,这个新的thread会处理这个中断。这样,我们便能更清晰的知道中断是何时被调用,又是何时完成,并且我们也能更好的去控制中断内部发生的事情。