系统级建模和验证在如今规模庞大的SoC设计中占据越来越重要的地位。本文提供了一种算法与结构模块联合建模的系统级设计和验证方法。在SLD阶段将算法模型重用成RM模型,挂接到基于AMBA总线系统的架构上去进行仿真验证。将算法模块和双层总线架构模块连接,进行联合设计验证、及软硬件协同调试。
随着深亚微米时代的到来,SoC设计规模越来越复杂,技术上的不断演进和成熟,使系统级设计SLD(System Level Design)和验证技术及其应用受到日益广泛的关注。IC行业在数字设计系统方面将由RTL向SLD逐渐转移。SystemC作为一种适于高级建模和仿真的SLD事实标准语言,已被广泛应用于功能验证和软硬件件协同验证等多个领域。
SLD包括从系统规格开始的C/C++/SystemC输入、体系验证、功能验证、虚拟硬件原型生成、软硬件共同开发以及C/C++/SystemC、VHDL和Verilog的混合验证、软硬件的协同验证,直到寄存器级的HDL源码生成和验证。
SLD设计过程
在规格级阶段就执行SLD,可以防止在产品需求分析过程中产生有缺陷的规格(Spec),避免在后续的SOC设计流程中缺陷被不断放大,进而导致整个ASIC开发过程迭代或芯片出错。据业界统计,在SOC的设计过程中,Spec的错误可能会造成价值一百万美元的的损失。
SLD能完成SPEC阶段需求和性能分析,进行SOC架构需求和性能分析、算法需求和性能分析,避免Spec设计中的Bug。SLD将通过建立系统级的抽象模型,执行仿真验证分析和评估给出量化的指标和数据,从而对Spec阶段的需求和性能作出正确的设计,随后在SLD的基础上进行软硬件模块划分。建模是通过C /SystemC在不同抽象级别进行的,包括:无时序功能级UTF(Untimed Functional)、时序功能级TF(Timed Functional)、总线循环精确级BCA(Bus-Cycle Accurate)和循环精确级CA(Cycle Accurate)。
SLD可采用Synopsys的系统设计工具CoCentric System Studio(以下简称为CCSS)。CCSS可提供运算规则和架构的建模和仿真,另外在软硬件协同调试中可连接软件调试器,如ARM的ADU/AXD、Tornado等进行调试。系统级的DesignWare库包括ARM_Processor和AMBA的SystemC模型库。
在SystemC 综合方面,Sysnopsys提供支持SystemC综合的SystemC 编译器,目前支持RTL SystemC 综合和行为级SystemC 综合。
在进行算法链路建模仿真时,可以采用CCSS。CCSS中增加了OR、AND、GATED等多种控制模型(层次化有限状态机(FSM)模型)。Cossap的底层模块在CCSS中为PRIM模块,层次模块为数据流图(DFG)模块。
用CCSS执行算法链路建模仿真,具有多种优势:建模种类多,数据类型丰富;版本控制更容易;变速率模块编写简单,PRIM模块编程直接支持端口的变速率;CCSS仿真速度更快,调试方法更方便(例如:可以在编程时使用inline函数,或通过调用外部函数提高仿真速度;将仿真链路中的反馈部分用PRIM模块建模,其仿真速度快于SDS模块的仿真速度;在生成仿真时关闭调试选项,提高仿真速度)。
可以使用SystemC进行系统建模。SystemC是一种C++类库(包括C++程序、库、封装等),是用来模拟硬件包含DSP、ASIC、IP Core和接口的SOC设计方法学。它可以完成系统级设计功能:在抽象层建模,细化成硬件;模拟软件模型,如中断、异常处理;在系统级范围验证;硬件/软件联合验证;能利用IP。它还可提供VHDL和Verilog的所有优点:并发性如方式(methods)、线程、时钟线程;时钟的概念;位宽可变的bit_true数据类型等。目前采用2.0.1版。
SystemC能在任何支持ANSI C++的编译环境下编译产生可运行的程序,如Gnu g++的2.95及以后版本,Microsoft Visual C++ 6.0及以后版本。可以利用标准C/C++的调试工具进行代码级调试,例如Unix、Linux下的gdb、ddd、xgdb、dbx;Windows下的Visual C++集成开发环境。在代码中可以利用C++的I/O语句,也可以采用SystemC内嵌函数创建文件、记录波形,支持VCD、WIF和ISDB 三种标准格式。
SystemC的设计分为四层:(见图1)
UTF级:就是一个系统可以运行的系统规格书。系统被描述成一系列通过抽象的通信连接起来的进程,可以采用时序方式/并发方式或两者兼而有之,时间只是作为因果关系而引入。
TF级:是一个高层抽象性能模型,UTF中的进程和通信连接都分配了执行的时间,特别指时钟周期或实际时间,对应于HDL语言的架构级。
BCA级:对应于HDL语言的行为级。
CA级:对应于HDL语言的RTL级。
在SystemC系统设计中,系统由不同的模块组成,模块由一系列并发的进程构成,每个进程完成一定的功能,进程之间通过信号来通信。在SystemC中,模块是分解设计的最基本的功能单元,在开发组中将一个复杂系统分解成模块,交给不同的设计人员来完成。模块化的设计隐藏了内部的数据和算法,通过公共接口与其他模块进行通信,这就使得整个系统很容易改变和维护。例如设计人员可以改变一个模块的内部数据和实现方式,只要外部接口不变,模块所实现的功能不变,使用这模块的用户来就不知道模块内部已改变。这样就允许设计人员在内部进行优化。进程是SystemC可运行的基本单元,它被调用来模拟设备或系统的行为。
AHB周期级接口规范CLI(Cycle Level Interface:由ARM公司及其合作伙伴定义的一种接口标准)为AHB SystemC 接口,用于将SystemC 模型或用SystemC封装的IP连接到AHB总线结构上。AHB CLI定义了一组SystemC API,用户可以使用这些API来开发基于SystemC的AHB模型,如AHB主模型、AHB从模型、解码器和仲裁器等。AMBA AHB CLI 1.1.0可支持AHB多层总线结构,它覆盖了AMBA2.0,包括AHB Lite和ARM11扩展结构等。AHB CLI 1.1.0主要规定了主模型、从模型、总线模型的接口函数(其中总线模型规范用于传输执行和触发执行方式的方式序列),定义了地址解码器和仲裁器的IF接口函数,还规定了用于总线监测的的Monitor接口函数。
Synopsys提供SystemC的DesignWare,包括DW_AMBA_SC、DW_ARM_Processor_SC库。DW_ARM_Processor_SC处理器模型是交易层模型TLM(Transaction Level Modeling),包括如下接口:指令AHB 总线端口ibiu、数据AHB 总线端口dbiu、ITCM端口、DTCM端口、中断和复位端口(nIRQ、nFIQ、nReset)、初始化端口(VINITHI和INITRAM)、时钟端口。
DW_ARM_Processor_SC包括DW_arm926ejs 处理器模型、DW_arm946ejs处理器模型。DW_AMBA_APB库中主要包括AHB2APB 桥、APB BUS TLM模型、定时器、监测器等模块。DW_AMBA_AHB 库中含有主、从和总线功能模块。AHB总线上常用的模块在库中都有,例如仲裁器、解码器、FIFO读/写、Bus2Slave、Master2Bus、TMemory、监测器、StimuliGen、AHB 总线TLM(一般为BCA级)模型、双层AHB 互连矩阵(ICM)等SystemC模型。不过源代码对用户是不开放的,所以无法基于上述模型进行修改,形成自己需要的模型。DW_AMBA_AHB 库中还有一些例子,其SystemC 源代码是可见的。在IP_Router可以找到DMA模块等。
在基于ARM总线架构的SystemC硬件模块设计过程中,常用的架构可以通过DW_AMBA_SC模块搭建,当然需要进行处理器、仲裁器、解码器、监视器等的设置,其它的主、从模块需要采用供应商提供的SC的IP或自行设计。用户通常可以在dw_amba_sc这个层次上进行建模,在dw_amba_sc提供的模型不满足要求的情况下再涉及CLI编程。结构建模设计中的承接关系见图2。
目前硬件模型编译工作站CCSS上采用GNU g++2.95及以后版本,Windows系统采用Visual C++ 6.0及以后版本。CCSS上用g++进行编译界面不够友好,gmake编译速度较慢。
g++在执行编译时,总共需要4个步骤:
a. 预处理,生成.i的文件[预处理器cpp];
b. 将预处理后的文件转换成汇编语言,生成文件.s[编译器egcs];
c. 将汇编后的文件变为目标代码(机器代码),生成.o文件[汇编器as];
d. 连接目标代码,生成可执行程序[链接器ld];
在模块编译时,通常会遇到-g、-O、-c、-l、-L等编译选项问题,其中,-g表示编译器在编译时产生调试信息;-O是编译器的优化选项;0、1、2、3是编译器优化选项的4个级别;-O0表示没有优化;-O1为缺省值;-O3优化级别最高;-c表示只激活预处理、编译和汇编,即程序仅生成obj文件; -llibrary是指定编译时使用的库; -Ldir是指定编译时搜索库的路径。
在CCSS环境可采用ddd、gdb(命令行界面)、xgdb(图形界面)和dbx作为SystemC硬件模型调试器。在Windows环境中用Visual C++ 6.0及以后版本进行调试。ARM架构上的软件代码可用C/C++/SystemC编写。比如Synopsys提供的IP_Router例子的软件代码是用SystemC写的;软件代码编译采用ARM公司提供的编译器,包括armcc、armasm、armlink等。软件代码调试器可用ARM提供的ADU、AXD等。
通常系统设计流程经过反复迭代进行算法仿真和分析,确定算法结构,然后逐渐细化算法模块,使之成为可实现的逻辑模块。在上述过程中,建立起来的算法链路用途比较单一。而在现代复杂的系统开发过程中,由于在Spec阶段进行系统建模分析,采用已有的算法链路形成的参考模型(RM)将会节省大量的时间和人力。
实际项目中,在SLD阶段,原来由Cossap搭建的基带处理算法链路(可认为是SystemC阶段无时序模型,基于数据流驱动的模型)可重用成RM模型,通过对算法模型进行时序封装(加时序Wrapper),可以挂接到基于ARM的系统架构上。根据模块接口需求进行封装,RM模型需求的抽象程度可逐渐细化。例如,最初模型接口是粗糙的时序功能模型或总线精确级模型,算法模块被封装成时序级或总线级与总线的IF进行交互,就能逐渐细化到循环精确级模型,以接近更准确的接口时序。可以通过Wrapper的设计来完成模型的接口与真实硬件实现的逼近。例如,逼近逻辑模块与总线进行的事件及中断交互等。用算法建模仿真速度要比结构模型快10~100倍。(见表1)我们采用在CCSS环境中进行结构与算法模型联合建模仿真。
SLD级算法和结构的联合建模仿真
将UTF模块通过封装在架构中进行仿真。在SLD设计过程中,算法模块可以认为是抽象的RM(UTF),因此在算法模块外围通过封装时序接口的Wrapper,可以达到作为高层次抽象级的RM,以实现可执行的架构规格。
在SLD级实现可执行的架构规格有利于进行初步系统架构的性能分析;为逻辑设计提供接口参考,或者与逻辑设计部分协调好接口;可以逐步明确详细的软硬件划分方案;为后面的仿真、原型和验证等提供数据对比。
系统级软硬件划分(见图3)。基带结构包含了FDD 调制解调器绝大部分的功能子模块和层1软件程序,层1的软件与FDD 调制解调器功能模块进行控制流程序交互。图中发送器的功能是将信道编码作为输入作为物理信道的数据部分发送。
SLD建模可明确划分出图中层1逻辑模块与层1软件,确定层1硬件模块和软件部分进行交互的事件和中断。其中,硬件模块原型可由UTF的算法模块加上总线接口模型,作为UTF RM进行建模和仿真。在UTF基础上,可进一步利用SystemC改写算法模块和总线之间的接口模型,使该模型能够描述图中层1逻辑模块与层1软件/CPU进行交互的接口时序。
TLM级RM的建立
基带模块中,如小区搜索链路等顶层算法模型是一个封闭的链路,作为DFG的整体,Symbol没有输入和输出端口,而要将算法模型封装上的时序模型挂接到总线上,就需要将算法模型引出输入和输出端口,在原有数据源输入处将数据源去掉,改成输入端口,这样由Wrapper封装通过AMBA总线进行数据源输入,即通过总线上CPU模型执行指令代码将相应的数据配置送入作为硬件行为的算法数据流中。同样,输出端口可由Wrapper封装通过AMBA总线进行输出读取。
如图4所示,将顶层算法模型挂接到AHB 总线上,需要增加用于AHB总线操作的Wrapper,Wrapper与AHB 总线通过AHB 总线通道连接,Wrapper通过继承AHB_Slave接口类与AHB总线接口进行总线访问操作,通道为AHB_Slave_if类,Wrapper与顶层算法模型相接进行数据流交互,其间的通道为FIFO类型。
在基带物理层链路中小区搜索链路模型,输入为数据源,输出为扰码识别号。SCF约束文件中设置的最大仿真的模块数在联合仿真时可大幅缩小,以缩短算法模块仿真时间。另外,由原Cossap的ASN文件倒换过来的SCF文件存在小的语法错误,在启动仿真调用SCF文件时会出现提示,要根据提示修改SCF中相应的内容。
在SLD仿真中,系统编译结束后硬件仿真开始,启动ADU调用软件程序进行协同仿真,当总线访问到Wrapper封装的算法模块时,算法模块进行仿真,数据结果传送给Wrapper。Wrapper与AHB 总线之间通过通道连接,Wrapper作为从模型,通过SystemC函数完成寄存器配置和地址空间映射,通过继承AHB_Slave_IF类函数进行总线读、写、控制状态(control_info),如触发模式,以及Trans、Prot等行为。
Wrapper的头文件中继承了AHB总线接口Ahb_Slave_if类,通过通道连接Wrapper与AHB总线模型之间的接口,调用接口方式来操作与AHB总线的register_bus、set_data、response、read、write、control_info、get_address_map、name功能,从而完成对应的总线操作。构造体为Wrapper(sc_module_name, ahb_addr_t),需要初始设置的参数是SlaveID。Wrapper模块中定义了sc_module_name和基地址,使用该Slave时需要配置基地址,初始时需要配置SlaveID的值,以便解码器进行地址解码。在Slave配置接口中,函数register_port()用于获取Master的参数配置;register_bus()用于返回SlaveID的值;set_data()用于设置存储缓冲器的头指针,以表明用于读写Slave的地址;response响应Slave在上一个地址周期中读写的操作状态;read为Slave读操作;write为Slave写操作;control_info为总线控制信息;direct_read、direct_write作为Master的直接访问接口。(具体请参见CLI函数定义和说明)
RM模型与软件的协同调试
ARM架构是基于示例IP_Router进行修改的,Synopsys提供了一个IP Router的例子,其中最简单的SOC原型系统包括ARM926EJ-S处理器模型,独立的数据总线和指令总线,数据AHB BUS上有译码器和仲裁器。在此基础上我们裁剪并保留了ARM926EJ-S和双层总线系统,增加了RM模型,作为从模型挂接在DAHB总线上,其中需配置解码器对该从模型进行地址译码。Wrapper具有hclk和hresetn信号线。
CCSS在算法链路编译时,如果出现提示行“pre-compiled Cossap Library ...........*.a is imported and used in System Studio library MS_MODH, you might need to enter‘make lib’command to re-compile”,表明无法找到MS_MODH库,这时需要清空MS_MODH等库,重新构建目标代码后,生成-g、-u、-o等库,才可正确编译。若调试时出现诸如“no rule to make target‘.../ccsssystemc.h’”的提示,如果工程名为SLDwork,则删除lib-gccsparcOS5下的*lib-g目录下对应的工程名为SLDwork.a的文件,该文件在每次编译时都打包或增加每个子模块的.o编译结果(即cr -a每个子模块),当子模块被删除后,如果该工程的.a文件没有删除,则会继续按.a文件原模块的规则来构造目标。
软件模块非常简单,在对RM模型的Slave模块进行操作的部分中,RM Slave在存储器配置中为FIFO类型(寄存器),因此软件可用于读RM Slave对应地址的寄存器值,代码如下:
_start_address = get_destination_address();//获取RM Slave对应的存储器地址
read_memory( _start_address , &local_flags);//读取该地址的值
其中read采用AHB总线端口的Burst_Read类型的CLI函数:
burst_read( ahb_data_t, // 数据缓冲器
ahb_addr_t, // 起始地址
int, // 脉冲时间
ahb_hburst, // 触发模式
ahb_hsize = SIZE_32); // 传输数据大小
在软件编译和调试阶段,代码*.cpp、*.h通过Makefile编译成AXF文件,连接过程中需进行初始化文件init.s设置和向量表设置等。AXF文件通过ADU/AXD调试器载入Image文件后进行调试。
本文总结
系统级建模和验证在如今规模庞大的SoC设计中占据越来越重要的地位,通过建立系统级的抽象模型,仿真或验证给出定量的分析数据,从而可以指导SoC设计人员在系统规格阶段就能够根据系统的性能需求作出正确的设计,并在系统级设计的基础上进行软硬件模块划分等。
通常的设计流程需要在算法模型成为行为级/RTL代码级的逻辑模块之后,才能进行整体性能的分析,而无法实现在系统规格阶段即对系统性能需求,包括对算法性能需求进行分析。
本文提出一种新方法,可以在系统级设计阶段即可将算法和结构模块联合建模,从而建立基于架构的虚拟原型系统模型,并可进行仿真和性能分析。其主要思路是,在SLD设计阶段将算法模型(基于数据流驱动的模型)重用成RM模型,通过对算法模型进行时序封装,挂接到基于AMBA总线系统的架构上进行仿真验证。本文还阐述了将上述算法模块和以AMBA总线为基础,以ARM926EJS为核的双层总线架构模块连接,在CCSS环境下进行联合设计验证及软硬件协同调试的过程。
作者:韩泽耀
SoC系统设计工程师
Email: zeyaohan@
华为技术有限公司上海研究所