cmodel模拟器开发

cmodel模拟器开发

对于一个公司来说,产品的设计周期就是生命线,一般来说都会在设计功能级仿真的c-model后直接转向RTL设计。

在目前的技术下,做cycle-by-cycle的设计和直接RTL设计的时间,感觉是差不太多的。nVidia同时维护functional and timing 的simulators。

第一个model是否能跑流行的game也是一个问题。
需要快速的开发,debug,不然就又到下一代产品了。

维护一个好的team,做算法,做架构的,做电路的,做实现的,互相讨论,互相了解彼此的领域。
用什么语言倒是无所谓,在大家讨论出结果时,各个工作组都有实现方案了,而且每组都可以用自己最熟悉的工具。

对于一个公司来说,产品的设计周期就是生命线,一般来说都会在设计功能级仿真的c-model后直接转向RTL设计。

对于GPU性能分析(Graphics Pipeline Performance Turing),就不一样了。用RTL来跑的话,不但占用License,而且比较耗费时间。对于一个不是特别大的公司来说,License还是比较贵的。如果RTL跑起来比较浪费时间的话,做性能分析的,一定会多开几个不同参数的RTL同时运行,一般来说,开个七八个任务同时运行测试场景是很正常的,如果一个组有好几个Performance Turing工程师,就要占用好几十个NCverilog License,而且还要占用相同数量的CPU时间。除了NV/AMD/Intel这种不在乎license数量的公司以外,小公司里别人还干不干活了。

Cmodel又不带时序,需要一个带有时序的Cmodel,对于公司内部某些特定需求的团队(比如性能调优相关的项目组)还是有意义的。

如果只是function 验证,可以用 verilator 来跑, 可用 systemc 来加速模拟 verilog 的行为,  之后再根据synthesis RTL 后的結果,分析出 critical path 部份. 就可以根据這结果修改 RTL verilog 再模拟. 其实就是不断的模拟验证..... ps: 不过也先要有前端的design 跟验证。

如果只是function 验证,可以用 verilator 来跑, 可用 systemc 来加速模拟 verilog 的行为。

对verilator很久经验么?跟别的工程师说过verilator,可能更相信carbon,更愿意花10w块美刀去买license……。

在传统的HW Design上,不外乎通过verilog 验证,跑跑RTL 的Function Check, 等Function 确定好后,用Design Compiler 转出Gate Level, 在验证Time 是否满足 setup time and hold time, 如不符合,就改Design,或者是改变設定的 constrain,就一直不断的Try and Test。相对的,会花很多时间在Debug上面。软件不像硬件一样,可以由断点分析,用software break 的方式,做Inside Register的 Debug。除非在HW中加入JTAG的机制。用ICE 来Emulator HW內部的flip-flop所暂存的值, 但在HW Design 初期, 根本不可能会把JTAG做进去,能不要每天加班就好了。在初期只能用NC-SIM 来模拟,看看Waveform写些TestBench去测。这样一来一往就话费了不少时间,如果能够用更快速的验证方式,通过软件来验证硬件的结果, 就可以减少在Design所花费的时间。

性能模型用处不大。

在设计中考虑性能的地方主要有:

1.设计方案的时候,这时候是要把性能计算好的。如果这里没有计算好,后期就麻烦大了。

2.开发时候,严格按照方案来做,可能会有一些方案没有想到的地方,及时反馈,修改。这时候按照方案里面的计算框架应该对开发有指导意义的。

3.测试的时候。在功能测试完毕后,但是这时候对于性能已经几乎没有什么能改进的了。

 

所以做方案的时候一定要把性能计算好。越到后期修改的可能性越小。

在上面三个阶段中,第一阶段主要是计算(计算可以用模型来仿真,觉得得不偿失,超大逻辑除外)。第二阶段是没有时间和精力来做性能仿真的。第三阶段应该fpga/asic已经完成了,性能仿真模型其实没有什么意义了,在实际的芯片上测试,比仿真模型要真实/快速/实际多了。

随着GPU可编程越来越灵活,人工计算的静态性能评估已经不那么有用了。很多时候性能和程序的特性相关,必须要针对主流应用来做优化,没有统计的方法,很难量化这个数据。只有拿到了主流应用的量化数据,才能优化和分配流水线上的资源。比如大多数应用对于“存储器访问”和“数据计算”比例是平均访问一次存储器后计算50条指令,那就要分配计算资源和缓存资源的比例,包括考虑到Cache尺寸多大才能满足一个合适的命中率,要支持多深的Non-blocking Cache访问才能隐藏延迟,并且不至于耗费太多的带宽,而这些都和应用的特性有关。如果这个比例在未来的主流应用中改变了行为,那还要变换参数。这个通过手工没有办法算出来,只能实际测试。

如果非常容易手工计算的话,那么像NV这样的公司,有上千个GPU架构师(GPU Architect)。设计的第一代卡性能也是非常不靠谱的,往往要等到第二代第三代卡的时候才能有一个比较满意的设计,包括功耗和性能权衡。而这种优化离不开性能模拟器。

对很多GPU供应商来说,同样如此,比如客户需要更高性能的芯片,那好,为了使性能提高一倍,需要把流水线宽度(注意是宽度不是长度)增加4倍,并且显存带宽(bandwidth of video memory)增加数倍才可以。但是这里面就有一个落差,就是性能不能随着并行度的增加线性增长,这里面必然有瓶颈。那此时怎么办?怎么调整流水线的负载平衡(load banlance),靠手算么?流水线上每一级都是程序控制的,如果不分析程序在不同Stage都耗费了多少Cycle的话,那怎么知道哪里是瓶颈呢?首先,第一步要找到性能瓶颈,然后第二步才是改进。

怎么找?用手上的ASIC来找性能瓶颈,也许可以,但是这需要足够数量的performance counter,这个在设计制造之初有么?现在就算假设有,那么第二步,怎么知道那种改进方案是最优的呢?可能需要不断地尝试,比如,增加或者减少不同片上资源的数量,比如某个Cache的尺寸,某个FIFO的深度,或者是BUS上某个Local memory的容量,等等。从而调节流水线的负载平衡。而ASIC都是定制好的,怎么调?怎么观察性能的改变?难道用加速器么,加速器的编译时间本身就是很长。也许可以增量编译。但是加速器大家都在抢,首先要保证功能验证的需求,可能分给性能调试组的机时都非常少了,根本不够用。 如果在服务器上面仿真还要占用License,会导致很多麻烦,仿真时间长不说,而且七八不同参数尝试的实例同时跑,性能调试组N个人一起这么干,别人就别干活了。

性能模拟器就是为了完善这个而产生的,第一代产品只是为了抢市场,而第二代和第N代等后续产品,才是真正成熟的产品。而凭经验给参数的做法,在可编程器件上不那么好使,虽然不到和拍脑袋的那个级别,但是也是不够用的。架构级别不优化,结果产品出来功耗性能差,上面要发飙的。所以,做精细的性能模拟器,也是不得已而为之的事情。因为这是真正的可编程设备(programmable device),不是一个视频编解码那种不可编程的专用集成电路设计(ASIC Design)。

之前以为靠流片来改进性能很笨拙,一个MP4的公司,改进性能/验证性能改善结果的做法是频繁流片,疯狂的时候一个月流一次。

(又是一个不用C Model来改进性能的例子)

不过,比较好奇这种做法:

1. 每次流片的成本大概多少?

2. 对项目来说,实际效果如何?(毕竟理论上ASIC的可见度,没有C Model可见度高,也许通过分析算法,在ASIC的某些关键点做performance统计)。

首先,直接silicon级别的性能统计?那需要插很多性能计数器(performance counter)吧,不然怎么观测呢?分析方法是什么呢?

其次,投片(tape-out)一次最快流程也要1个月,但是这需要大晶圆厂才可以,比如SIMC或者TSMC,小的成本更低的晶圆厂往往都走三个月的流程。

以前还有门海(gate-sea)技术实现的投片,就是在衬底上吧晶体管都预先排列好,然后在没有客户的情况下预先生产,最后不同的客户只需要在预先准备好的衬底上,光刻出来不同的金属连线就可以了(就好像蛋糕店预先生产好蛋糕坯子,不同的客户就挤出来不同的奶油图案一样),所以流程更快(比一个月还要短),不过貌似在深亚微米级别好像没见过了,是不是因为线延迟增加的缘故。

最后,投片成本,5平方毫米的MPW一般五万到十万,能到0.18个工艺吧(不知道最近行情怎么样)。不过还有封装费用(如果管脚不多,可以直接封装在版子上降低成本),

另外,觉得如果需要2次MPW投片才能调整出来一个好的性能,那也就是2个月时间。有两个月时间,都可以直接调好C model性能模拟了,从而改进RTL了。并且方法学可以集成到下个项目中,好处多多。除非大这个项目组身兼好几个项目,所以这样做是为了省时间,破财免灾,不然老板就冤大头了。

性能模拟器能不能得到正确的书性能分析数据,这个在CPU性能模拟器这个问题中很常见。的确是需要按照需求来设计。

比如,对于传统的OGL ES1.1来说,没有复杂的数据回路,流水线基本都是生产者-消费者关系,那么首先对于一个新项目而言,要解决的问题就是在这些Stage 之间插入多少深度FIFO,才能做到流水线复杂均衡(load balance),这就是需求。像之前Cqq大牛描述那种私有框架,在基本的需求就在于此。

而现代GPU越来越复杂,如果用学术名词描述GPU架构的话,基本上可以说是“多核心的多线程向量处理器阵列”,不再像传统图形流水线,大大增加了性能模拟器的设计难度。从复杂性角度来说,的确在这种情况下就应该把性能模拟器和功能模拟器完全分开做。但两者不见得是文件级的数据传递。从项目进度的角度考虑,还是推崇由性能模拟器调用功能模拟器的方式。对于一个粗粒度的性能仿真来说,也许这需要在功能模拟器中多放置一些bool变量,这些只能标志位用于告诉性能模拟器,那些运算功能被使用到了。

最近考虑这个问题,主要是针对一款芯片更早的性能调整和性能分析(performance analyzing & tuning)。在传统的固定功能图形水流线(fixed function graphics pipeline)上,可以依照简单的带宽计算公式和经验来设计芯片,而不需要更多的测量流水线之间是否满足于性能平衡。因为在固定管线下,图形API调用程序的行为变换是很有限的,而存储器带宽和固定功能的计算公式就可以获得很好的预估精度。

但是在当前GPGPU的角度越来越近的情况下,这一情况发生了很大变化,面向通用计算(或是说流计算)后,无论是OCL还是Shader程序行为不再像固定功能图形流水线API那样的死板,变得非常灵活,从而使得可编程图形流水线(programmable graphcis pipeline),使得程序可以写出千变万化的效果。这导致传统的靠手工静态计算的性能分析,变得不再可靠。必须更细致的更量化的考虑当前大部分程序的行为,以及未来可能出现的程序行为,从而决定如何改进GPU,如何分配片上门电路资源(resource of gate-level circuit on-chip)给不同的流水线阶段(pipeline stage)。这就使得设计一个性能模拟器,在编写下一个版本的RTL之前是非常有必要的事情,对于IP供应商来说,这也有助于在制作好RTL释放包(release package)后,针对客户不同应用,给出不同的IP配置建议。

但是这里又有一个新问题,就是传统来说,在设计GPU C-Model的时候一般都不会加cycle信息在上面,传统的GPU c-model主要就是作为验证流程(verification flows)中黄金参考模型(golden reference model)来使用,验证平台(testbench)只需要针对不同的流水线阶段(或是模块)写出来不同的无周期行为级模型(或是硬件算法模型)就可以,不需要带有任何周期信息。所以,一般来说当前部分GPU设计公司都指挥维护一个不带有周期信息的GPU c-model。但是这个cmodel只能做功能仿真(functional simulation),并不不能做性能仿真(performance simulation)。

对于一个公司来说,产品的设计周期就是生命线,一般来说都会在设计功能级仿真的c-model后直接转向RTL设计,而不是在进行一个时钟精确(cycle-accurate cmodel)的性能模拟器设计,在产品进度上这是不允许的。而且维护两个c-model这也会导致公司运营的成本增加,并且项目管理的难度也大大增长!所以需要一个快速的性能模拟器方案。使用功能模拟器跟踪(trace)出来每个GPU独立模块模块,所接受到的图形软件程序的代码流,比如那些三角形触发了切割(cliping)操作哪些触发了剔除(culling)操作。这个trace出来的信息被送入一个单独的性能模拟器,这个性能模拟器不能执行程序,只能根据trace出来的代码流来积累时钟周期,从而计算出来流水线延迟和瓶颈。这样,就可以在原有的c-model上利用原有的资源来最小程度上获得一个早期的性能分析数据。并且把管理和维护成本做到最小。

这个性能模拟器可以使用systemc来实现,就是相当于一个大的计数器,针对不同的执行来累加不同的时钟消耗,而不需要填写任何与时序和执行流水线无关的 无关的功能算法。systemc的TLM可以很容易的实现这个功能。

 

上一篇:一文了解Vivado HLS


下一篇:数据后端之逻辑综合