在本文中,我们提出了一种快速方法,该方法允许将 SystemC 模块连接在一起。这些模块可以在不同的抽象级别上指定,并且我们获得了整个系统的可执行仿真模型。我们工作的独创性在于它不需要 SystemC 外部库。实际上,仿真模型生成仅基于:模块规范、SystemC 添加库和简单的规则描述语言。因此,使用我们的方法,我们通过实例化通用可配置 SystemC 类,以快速和自动的方式生成具有简单结构的仿真模块适配器。如果需要 SystemC 培训以及开发外包,欢迎联系微信 machinewarevp(请备注公司姓名和岗位)通常在硅片上获得 SoC 之前,系统在几个抽象级别(功能、逻辑、RT 等)上指定,每个规范称为模型。任何系统设计流程都包括或多或少自动地细化每个模型以获得另一个模型,从功能模型开始直到寄存器传输级 (RTL) 模型。因此,每个设计工具都必须包含模拟引擎,以便在改进模型之前验证每个模型 [Mef02]。但是,由于复杂系统主要是通过组装现有组件 (IP) 来设计的,因此设计人员有时只想向由一组现有 IP 构成的系统添加一些功能,以获得可扩展的 SoS。例如,如果此初始系统仅在 RT 级别可用,则从设计时间方面来看,仅设计从功能级别添加到系统的部分,而不是在高抽象级别再次指定所有应用程序,可能会非常有益。但是,需要一个多级仿真平台来验证整个系统(在高抽象级别添加的部分和在低级别添加的旧应用程序)。这就是我们工作的目标。本文组织如下:在第 2 节中,我们介绍了理解这项工作的一些必要基础知识。相关工作在第 3 节中介绍。第 4 节介绍了我们多级仿真模型生成的不同步骤。我们的方法应用于包含 RT 级描述的 SDRAM 和 UTF 级描述的处理器模块的系统(见第 5 节)。我们将在第 6 节结束本文。本文介绍的多级仿真方法仅涉及完全用 SystemC 描述的系统。在本节中,我们将介绍一些理解我们的方法如何工作所必需的基础知识。SystemC 设计流程允许主要在四个抽象级别描述系统模块 (IP) [Gro02]。以下段落描述了每个抽象级别的一般特征。在此级别,模型类似于可执行规范,但模型中不存在任何时间延迟。共享通信链路(如总线)不在 UTF 级别建模。模块之间的通信是点对点的,通常使用具有阻塞写入和读取方法的 FIFO 进行建模。TF 模型与 UTF 模型类似,模块之间的通信仍然是点对点的,没有共享通信链路。但是,在这个抽象级别,设计中的进程会添加定时延迟,以反映规范的定时约束以及目标架构的处理延迟。2.1.3. 事务级 Transaction Level在事务级规范中,模块之间的通信使用函数调用进行建模。在这个级别,通信模型在功能方面是准确的,通常在时间方面也是准确的。例如,在 SoC 事务级规范中,我们可以将片上总线支持的不同类型的事务建模为突发读/写事务,但我们不会对连接到总线的模块的引脚进行建模。2.1.4. 寄存器传输级 Register Transfer Level它是 SystemC 系统设计流程中最低的抽象级别。RT 级模型的内部结构准确反映了目标架构的寄存器和组合逻辑。模块之间的通信在所使用的协议和时间方面进行了详细描述。每个模块的行为都与物理组件的行为完全对应。RT 级别使用的数据类型主要是位(或位向量)。多级仿真模型是一种可执行规范,包含一组在不同抽象级别描述的模块。这种模型的问题是如何自动且低成本地连接两个(或多个)模块,这些模块使用不同的数据类型通过不同的通信协议进行通信。图 1 显示了包含两个模块的系统示例:模块 1 和模块 2。第一个模块在 UTF 级别指定,使用带有整数数据的阻塞 FIFO 通过 3 个端口进行通信,第二个模块使用带有位和位向量类型的多种协议(主从、Hand-shack 等)通过 11 个端口进行通信。因此,问题是如何转换数据类型和协议以允许这两个模块之间的通信。图 1:多级仿真问题
最近,许多学术和工业研究团队致力于嵌入式系统中的多级仿真问题。这种类型的模拟意味着一起执行在不同抽象级别描述的系统组件模型。在提出的解决方案中,总线功能模型 (BFM) [Sem00] 构成了将功能仿真模型和周期精确模型互连的传统方法,尤其是用于验证软件/硬件接口。遗憾的是,这种方法仅考虑了内存访问,但它根本不允许转换高级通信原语(例如 FIFO)。CoWare VPK 是一个提供多级协同仿真解决方案的环境。它允许使用两个抽象级别:BCA(总线周期精确),与 RTL 和 UT 级别非常相似(没有时间参考)。因此,我们提出了一个名为 BCASH 的概念,它是 UT 级别描述的子系统的包装器,允许估计其子例程的执行时间。只有当 UT 级别的子系统以软件为目标时,才能自动生成此包装器。(这意味着子系统将在处理器模拟器 ISS“指令集模拟器”上执行)。不幸的是,这是一个非常强的限制。转换接口的概念存在于 SystemC [Sys] 中。它可能允许通过远程过程调用 (RPC) 通信的模块与在 RT 级别描述的其他模块连接。该接口必须完全由设计人员手工编码,这当然可能非常耗时且容易出错。我们可以找到一些其他多级仿真环境,例如 Chinook [Cho95],它专注于在改变模块抽象级别时的动态性。VSI Alliance [Vsi] 致力于异构组件组装。它提出了不同抽象级别的规范和文档标准以及总线接口标准。但它还没有关注模拟适配器的生成。因此,COSY [Bru00] 是一个通用模型,它允许通过 VCI 总线模型接口互连 IP,但它仍然专注于系统级。文献中的一些最新研究处理了异构多处理器 SoC 多级仿真模型的自动生成问题。[Nic02] 中描述的工作是一个重要的例子。它允许自动生成模拟包装器,以使模块抽象级别适应模拟级别。不幸的是,它不针对特定类别的应用程序,包装器是通过组装来自外部库的基本组件构建的。这些模拟包装器的结构似乎很复杂,因为每个实例中都存在大量 SystemC 组件(进程)。我们的贡献是提出了一种通过模拟验证 SoC 的新方法。通过这种方法,我们可以对通过组装 IP 构建的系统进行快速且低成本的模拟。可以在不同的抽象级别描述 IP。我们方法的主要独创性在于它不需要任何外部 SystemC 库。它只使用内部 SystemC 库和一个小的规则描述语言。我们的仿真模型生成流程为每个模块生成一个仿真模块适配器,这些模块的抽象级别不同于我们想要执行系统反仿真的级别。例如,如果我们有一个由两个模块组成的 SoC:模块 1 在 UTF 级别指定,模块 2 在 RT 级别指定,并且我们想在 RT 级别对其进行仿真,我们的方法会自动为模块 1 生成一个仿真模块适配器,以便使其接口与模块接口相适应。我们的仿真模块适配器主要由三部分组成:真实端口、逻辑端口和无限 SystemC 进程,如图 2 所示。本节的其余部分将详细描述这些部分。图 2:仿真模块适配器的结构
它们对应于初始模块端口。它们具有与真实模块端口完全相同的特征(数据类型、通信协议等)。模拟模块适配器必须具有与要连接的模块的实际端口数量相同的逻辑端口数量。这些逻辑端口中的每一个都必须具有与要连接的模块的实际端口相同的特性。这是一个自动生成的 SystemC 进程,通过实例化和配置我们定义的通用 SystemC 类。它对将其连接到实际端口的信号很敏感。此进程从实际端口读取数据,将其转换为适合逻辑端口类型的数据。本节的其余部分介绍了模拟模块适配器的自动生成方法。有了要连接的每个模块的接口,我们的流程将生成一个多级仿真模型,如图 3 所示。图 3:多级系统仿真模型生成流程
我们的模拟模块适配器不是通过组装外部库的基本组件(如大多数文献工具中那样)构建的,而是通过规则组合生成的。在我们的仿真模型生成流程中,所有仿真模块适配器都是我们创建并称为“generic_interface”的 SystemC 类的实例。通用接口是一个可配置的 SystemC 类。与所有 SystemC 类一样,它由一个接口文件 (.h) 和一个实现/行为文件 (.cc) 组成。定义端口特性的接口文件是从初始系统规范中自动配置的,行为文件是通过一组规则的组合来构建和配置的。规则组合在本节中详细描述。我们在仿真生成流程中主要区分了三个引擎(图 3)。代码解析器引擎从设计人员那里获取要连接的模块的 SystemC 接口文件 (.h) 和仿真级别。它生成仿真参数。这些参数主要是逻辑和实际端口的数量、每个端口的通信协议以及设计人员想要执行系统仿真的仿真级别。在获得所有仿真参数(模块接口和仿真级别)后,仿真模块生成器引擎实例化并配置通用类,以获得使给定模块适应仿真级别的 SystemC 模块。所有必要的仿真适配器都是通过实例化 GenericInterface 生成的。这使得最终的仿真模型的结构简单,生成也容易。模块适配器由接口(描述模块适配器的端口)和行为文件(描述仿真模块适配器行为的 SystemC 无限过程)组成。第一个是使用关联规则生成的,第二个主要使用转换规则。这两种规则将在下一段中描述。仿真模块适配器的接口文件 (.h) 是通过为每个实际/逻辑端口实例化一个端口类生成的。例如,模块处理器的模块模拟适配器的接口文件中的以下语句创建了一个整数类型(32 位)的输入端口:processor.add_port(create_port<sc_in<sc_int<32 > > >);
在模拟模块接口上创建输出端口的语句与上述语句类似。因此,只有方向(输出/输入)和数据类型会发生变化。因此,通过以下语句创建一个位类型的输出端口:processor.add_port (create_port <sc_out<sc_bit > >);
add_port 和 create_port 是我们添加到 SystemC 库中的两种方法,目的是简化和自动化代码生成。这些规则是一组允许在端口上执行读/写操作的基本原语。因此,通常当在事务级别或 RT 级别指定模块时,通信或多或少是明确建模的,而对于在 UTF 或 TF 级别描述的模块则不是这种情况。因此,当我们必须在系统中同时在 RT 级别进行模拟时:一个模块(其中通信是明确建模的(RTL))和另一个模块(在 UTF 级别),并且我们想要在 RT 级别模拟系统,我们必须使用这些规则来关联这些不同的端口。关联规则是一些描述系统模块之间端口关联的简单规则。因此,例如,在 RTL 级别描述的内存通过一定数量的控制端口和地址和数据端口集进行通信,在 UTF 级别描述的处理器简单地到达具有地址端口和数据端口(均为整数类型)的内存,并且可能还有一些控制端口(例如 WriteEnable)。为了在 RT 级别模拟包含这两个模块的系统,关联规则允许将处理器数据端口(整数)与内存数据端口集(例如内存)相关联。假设处理器数据端口称为 PDP,内存端口分别称为 PMD0、PMD1、..PMD15,则关联规则将简单地通过以下表达式来表达:这意味着端口 PMD0 至 PMD15 从端口 PPD 接收数据。例如,以下语句是从关联规则生成的。它将整数 (32) 实端口与模拟模块适配器接口中的逻辑 (位向量 (32)) 端口关联起来。m1.add_trans_in (TRANS_GENE (sc_in<sc_int<32 > >, sc_out <sc_bv<32 > >, sc_bv<32 >, m1[0], m1[1]));
TRANS_GENE 是文件 (Association.h) 中定义的宏。它操纵定义的关联规则。模拟模块适配器的行为是一个无限的 SystemC 过程,它对其所有(或一组)自己的输入端口(真实端口)敏感。例如,以下 SystemC 语句使 m1 的行为对其输入端口敏感:其中 m1 是一个模拟模块适配器,set_processe_in() 是一个定义的方法,它使模块对其输入端口的任何变化敏感。之后,我们可以为模拟模块适配器指定一组特定的敏感端口。例如语句:m1.set_event (((sc_in<bool >*)m1[2])->default_event ());
使模块 m1 对其第二个输入端口 (m1[2]) 敏感,该端口是布尔值。因此,m1 的行为无限过程将在该端口上的每个新值处执行。与前面的规则一样,它们是相当简单的规则。它们主要定义系统模块之间的协议转换。因此,在内存和处理器的例子中,处理器数据端口上的值的变化意味着对某些内存数据端口的写入操作是按照相当精确的顺序进行的(内存访问协议由内存供应商提供)。以下转换规则示例意味着当处理器在其数据端口上写入数据时,必须在内存端口上执行三个有序的写入操作。因此,模拟模块适配器必须在同一周期内将数据写入内存控制端口 PMC0 和 PMC1,然后在下一个周期对内存数据端口 PMD0 至 PMD15 执行写入操作,最后在控制端口 PMC3 上执行写入操作。generic_container * gc = new generic_container;
…
gc.add_trans (TRANS_PUT_VALUE (sc_out<sc_bit>, 0, 1, m1[18]));
gc.add_trans (TRANS_PUT_VALUE (sc_out<sc_bit>, 1, 1, m1[19]));
gc.add_trans (ADD_WAIT (2));
gc.add_trans (TRANS_GENE_SET (sc_in<sc_int<32> >, sc_out<sc_bv<32> >, 0, 15, m1[0], m1[1]));
gc.add_trans (ADD_WAIT (2));
gc.add_trans (TRANS_PUT_VALUE (sc_out<sc_bit>, 3, 1, m1[21]));
...
m1.add_trans_in (gc);
其中 TRANS_PUT_VALUE 是一种允许将给予者端口设置为固定值的方法。
注意。目前,我们只是以文本格式指定规则,但我们正在研究一种特定的形式和语言来定义它们,以便使它们的定义和重用更简单、更容易。最后一个阶段包括将每个生成的模拟模块适配器与其关联的模块连接起来,然后将不同的模块连接在一起,最终形成一个可执行的模拟模型,允许模拟整个系统。我们希望通过模拟来验证一个 SoC,其中包含一个在 UTF 级别指定的传输模块和一个在 RT 级别描述的 SDRAM(同步动态随机存取存储器)。该内存是 Micron [Mic] 生产的现有物理模块,参考编号为 MT48LC16M16A2。这是一个 256 Mbits 内存,包含四个 64 Mbits 的块。每个块的特点是 8192 行和 512 列。内存字为 2 个字节。为了模拟这个系统,我们首先在各自的抽象级别指定两个模块(见表 1)。SDRAM 是一个现有模块,其功能和组成由其供应商指定。它由几个部分组成;最重要的是:控制逻辑、行、列和组解码器、输入/输出寄存器、屏蔽信号、刷新计数器和时钟信号。SDRAM 的通信接口由供应商定义。因此,为了将其与其他模块连接,我们必须严格遵守此接口(端口数量、端口感应和端口类型)。注意。供应商以每个操作的下限和上限形式给出了 SDRAM 上每个操作所需的时间。在我们的内存实现中,我们为每个操作时间选择两个界限的平均值。要向 SDRAM 发送任何命令,处理器必须在一组端口上发送信号。这些信号特定于每个命令。与每个命令相关的信号由供应商提供。因此,例如,为了对 SDRAM 执行写入操作,必须将信号 RAS 设置为 1 (H),并将信号 CS、CAS 和 WE 设置为 0 (L)。发送器模块是一个高级模块,专用于与 SDRAM 通信以验证其功能。发送器的接口由 5 个端口组成,如下所示:sc_out<sc_uint<addr_size>> addressTrans;
sc_in<bool>clock;
sc_out<bool>enable;
sc_out<bool>readwr;
sc_out<int>command;
sc_inout<sc_uint<data_size>>dataTrans;
命令端口用于指定发送器要在 SDRAM 上执行哪些操作。每个内存命令都与一个整数值相关联。我们选择在 RT 级别模拟我们的系统。因此,我们生成一个模拟模块适配器来封装处理器模块并允许它与 SDRAM 通信。关联规则包括将模拟模块适配器的实际端口与其逻辑端口关联。因此,所有内存端口都与至少一个发送器端口相关联。例如,以下两个规则:表示发送器的模拟模块适配器 ADDRESSTrans 的实际端口将与逻辑端口 ADDR、CAS、RAS、DMQH 和 DMQL 相关联。因此,这五个逻辑端口将从指定的实际端口获取它们的值。因此,对于此应用程序,我们为每个发送器端口定义了一个关联规则。转换规则都是定义供应商定义的 SDRAM 访问协议的规则。因此,我们定义了 11 条转换规则(每个内存命令一条)。这些规则中的每一条都定义了如何以及以何种顺序将实际端口上的值转换为写入逻辑端口上。生成的模块在其接口文件 (.h) 中包含 22 行,在描述无限进程“行为” (.cc) 中包含 90 行。如表 1 所示,与在 RT 级别指定 SDRAM 所需的代码相比,生成的代码具有非常可接受的代码。
| SD RAM | Processor | Sim. Mod. |
接口 | 42 | 60 | 22 |
行为 | 1200 | 170 | 90 |
在此步骤中,我们将生成的仿真模块适配器与处理器模块连接,然后将其与 SDRAM 模块连接。这仅包括将仿真适配器端口与两个系统模块的端口点对点链接。因此,模块链接器实例化 3 个信号以将其仿真模块适配器的实际端口连接到处理器,并实例化 10 个信号以将 SDRAM 与仿真模块适配器的逻辑端口连接起来。本应用表明,我们的神话允许以快速简单的方式同时模拟在 RT 级别 (SDRAM) 描述的现有工业模块和在高抽象级别指定的另一个模块。与要模拟的系统的初始规范相比,生成的多级仿真模型具有可接受的复杂性。在本文中,我们提出了一种用于 SoC 设计的自动多级仿真方法。我们的方法包括实例化和配置通用 C++ 类,以获得系统中每个模块的一个模拟模块适配器,这些模块在与模拟级别不同的抽象级别上描述。该方法的有效性已在一个由分别在 RT 和系统级别描述的 SDRAM 和处理器组成的示例中得到证明。REFERENCES
[Bru00] J-Y Brunel, W. M. Kruijtzer and al, “COSY Communication IP’s”, Proc. of the DAC, Los Angeles, CA, June 200.
[Cho95] P. H. Chou, R. B. Ortega and al. “The Chinook Hardware/Software Co-Synthesis System”, Proc. of the ISSS, 1995.
[Cow02] Coware. Inc., “N2C” available at http://www.coware.com/cowareN2C.html
[Gro02] T. Grotker, S. Liao and al, “System Design with SystemC”, Kluwer Academic Publishers, USA 2002.
[ITR00] International Technology Roadmap for Semiconductors.
[Mic] MICRON, http://www.micron.com
[Mef02] S. Meftali, “Architectures exploration and memory allocation/assignment for multiprocessor SoC”, PhD thesis, University Joseph Fourier, TIMA laboratory, France, 2002.
[Nic02] G. Nicolescu, “Specification and validation of heterogeneous embedded systems”, PhD thesis, INPG, TIMA laboratory, France, 2002.
[Sem00] L. Semeria and A. Ghosh, “Methodology for Hardware/Software Co-verification in C/C++”, Proc. of the ASPDAC, Jan. 2002.
[Sys] SystemC language and user guide, available at http://www.systemc.org
[Vsi] http://www.vsi.org/