1 vitis使用c实现代码,分4步:
1) 流程设计,主要是思考实现相关功能如何按照硬件方式实现,主要考虑怎么分级、组合以及每个分级间数据流位宽等情况,另外有一些原则需要考虑:
a 尽可能从数据流拿到数据立刻进行相关运算,这样好处可以避免ram访问时间上过于集中,另外可以流水流起来;缺点是写起来比较复杂,需要对处理的每个字段进行第几拍的判断
b 尽可能减少逐级嵌套,避免层次太深,导致组合电路时序不够,原则是有常量或固定参数最外层,然后逐级代入
c 尽可能实现前后逻辑不相关,这样的好处是减少耦合,功能实现相互独立,逻辑电路控制也比较好做而且时延也不会增加
2)实现软件代码并验证,根据流程设计实现软件代码并验证功能,这部分主要是检验代码实现 的正确性,用软件的好处是可以快速发现逻辑问题、修改,以及对比验证工具的实现
3) 实现硬件代码,添加一些控制宏,降低延时和时序约束,综合通过后继续和软件功能验证。
4) 将内核整合到工程中,测试功能正确性,并完成版本。
实现基本模型设计:
1 将收到的整条消息放入ram,然后通过数据流传递到下一级解码处理,好处是实现最简单;缺点是数据长度不能超过512字节,否则编译不过
2 数据按照固定字节(8字节整倍数)通过数据流向下一级传递,下一级收到数据放入ram,并根据到达第几拍处理对应字段,完成数据的处理,比如:需要处理的字段跨1、2两拍,可以判断当取完第二拍再处理对应字段。好处是可以流水起来并且组合电路不会特别长,缺点是需要添加很多判断逻辑;另外还可能有增加整个循环延时的风险,需要写个模型验证下
3 结合1、2两个方案,折中处理,方法是根据数据特征来管理数据流,做到任何一个字段不会跨两拍,这样可以分别对不同拍写代码处理,好处是比较灵活,也不用特别多的判断逻辑,缺点是可移植性比较差,一旦协议中间添加字段就比较难处理,适合比较简单的逻辑。
关于连线的一些认识:
今天遇到个奇怪的问题,需要实现一个功能,里面的switch分支非常多,按照软件的思维,将代码分成两大部分,一部分专门选择路由(把switch集中起来,全面内联),另一部分是具体处理数据的分支,总体上设想硬件应该会综合成两大部分的模块。但是综合出来发现时序一直不好,查了很久,甚至怀疑编译器是不是不支持switch。
原因就是因为还是软件的思维,然后无论switch多少调路径,执行就一条路径。但是硬件是需要连线的,所有的可能都要有一条路径,这样导控制ram控制特别复杂,连线需要绕来绕去,分析报告发现switch的不同分支函数居然要前后调用,可想而知这个连线多么复杂。
后面再遇到switch、if这种判断特别多的时候需要评估ram操作的复杂度,如果无法支持需要copy多个副本给不同分支用,减少ram连线复杂度。
/
遇到连续特别复杂怎么办?
其实可以考虑间接的方式,比如:上面例子共有8*8*6=384种场景;最终执行体有8*6=48种,如果映射关系特别复杂,可以先将384种场景写个函数产生一个统一编号,然后编号在去对应48种情况,这样把功能整体分成两部分,综合就好办了。
另外对于多种场景连寄存器的场景,处理起来比较复杂,要么是多个寄存器或者占一个bit(每种场景一个寄存器),或者寄存器与结果按位与或按位或。
对于连接ram更复杂一些,需要好好研究下