Flutter未知功能插件rohd_cosim的潜在用途探索
Flutter未知功能插件rohd_cosim的潜在用途探索
ROHD Cosim简介
ROHD Cosim 是一个基于 Dart 的包,用于在 ROHD 模拟器和 SystemVerilog 模拟器之间进行协同仿真。它依赖于 ROHD 框架(Rapid Open Hardware Development),允许开发者在 ROHD 环境中实例化 SystemVerilog 模块并运行模拟。常见的使用场景包括:
- 在 ROHD 模块中实例化 SystemVerilog 模块并运行模拟。
- 使用 ROHD 和 ROHD 验证框架(ROHD-VF)为 SystemVerilog 模块构建测试平台。
- 将 ROHD 和 ROHD-VF 开发的功能模型连接到位于 SystemVerilog 层次结构中的空壳模块。
- 开发混合仿真模型,其中部分设计和/或测试平台用 ROHD/ROHD-VF 编写,其他部分用 SystemVerilog 或其他语言编写,并可以在 SystemVerilog 模拟器中运行或与其交互。
当在 ROHD 模拟器中实例化 SystemVerilog 模块时,从 ROHD 环境的其余部分来看,它与其他 ROHD 模块没有区别。你可以运行模拟、设置断点和调试等,即使 SystemVerilog 模拟器正在协同仿真中运行。
前置条件
ROHD Cosim 依赖于 Python 包 cocotb 及其 GPI 库与 SystemVerilog 模拟器通信。cocotb 库支持多种模拟器,并已被许多硅片和 FPGA 项目使用。安装 cocotb 的详细说明可以参考相关文档,通常只需要执行以下命令:
pip install cocotb
你还需要一个你喜欢的 SystemVerilog 模拟器来进行 ROHD 和 SystemVerilog 模块之间的协同仿真。ROHD Cosim 本身不进行任何 SystemVerilog 解析或模拟。
使用 ROHD Cosim
使用 ROHD Cosim 主要分为两个步骤:
1. 包装你的 SystemVerilog 模块
将你的 SystemVerilog 模块包装在 ROHD 的 ExternalSystemVerilogModule
中,并应用 Cosim
混合类。例如,以下是对应的 SystemVerilog 模块定义及其包装后的 Dart 代码:
SystemVerilog 模块:
// example_cosim_module.v
module my_cosim_test_module(
input logic a,
input logic b,
output logic a_bar,
output logic b_same,
output logic c_none
);
assign a_bar = ~a;
assign b_same = b;
assign c_none = 0;
endmodule
Dart 包装代码:
// example_cosim_module.dart
class ExampleCosimModule extends ExternalSystemVerilogModule with Cosim {
Logic get aBar => output('a_bar');
Logic get bSame => output('b_same');
[@override](/user/override)
List<String> get verilogSources => ['./example_cosim_module.v'];
ExampleCosimModule(Logic a, Logic b, {String name = 'ecm'})
: super(definitionName: 'my_cosim_test_module', name: name) {
addInput('a', a);
addInput('b', b);
addOutput('a_bar');
addOutput('b_same');
addOutput('c_none');
}
}
你可以使用任何机制添加输入和输出,包括 ROHD 的 Interface
。
2. 生成连接器并启动协同仿真
在 Module.build
之后调用 Cosim.connectToSimulation
函数,并传递适当的配置信息以连接到 SystemVerilog 模拟器。
协同仿真配置
有三种不同类型的配置可以用于连接到 SystemVerilog 模拟器:wrap
、custom
和 port
。
Wrap 配置
Wrap 配置是最简单的方式,适用于没有现有构建和模拟系统的情况。只需传递一个 CosimWrapConfig
对象给 Cosim.connectToSimulation
调用,并指定要使用的模拟器,ROHD Cosim 会自动处理其余部分,包括生成包装器和所有需要协同仿真的子模块。
示例代码 example/main.dart
使用了 wrap 配置,是一个很好的入门参考。
Custom 配置
Custom 配置适用于已有构建系统的情况,希望尽量减少修改。传递一个 CosimCustomConfig
对象给 Cosim.connectToSimulation
调用,并提供如何启动模拟的信息,ROHD Cosim 会处理其余部分。
ROHD Cosim 会生成一个基于 cocotb 的 Python 连接器,由模拟器进程启动。ROHD Cosim 通过本地套接字与 Python 连接器通信,并监听来自 stdout 的端口信息。
Port 配置
Port 配置适用于不仅有自己的构建系统,还有自定义模拟运行系统的情况。传递一个 PortConfig
对象给 Cosim.connectToSimulation
调用,并指定要连接的 Unix 套接字端口。这样,ROHD Cosim 不再需要启动 SystemVerilog 模拟器,其他进程可以启动模拟器,然后 ROHD Cosim 会在指定端口上连接。
完整示例 Demo
以下是一个完整的示例,展示了如何使用 CosimWrapConfig
进行协同仿真:
// Copyright (C) 2023 Intel Corporation
// SPDX-License-Identifier: BSD-3-Clause
//
// main.dart
// Example of using a `CosimWrapConfig` with ROHD Cosim.
//
// 2023 February 13
// Author: Max Korbel <max.korbel@intel.com>
// ignore_for_file: avoid_print
// Import the ROHD package.
import 'package:rohd/rohd.dart';
// Import the ROHD Cosim package.
import 'package:rohd_cosim/rohd_cosim.dart';
// Define a class Counter that extends ROHD's abstract
// `ExternalSystemVerilogModule` class and add the `Cosim` mixin.
class Counter extends ExternalSystemVerilogModule with Cosim {
// For convenience, map interesting outputs to short variable names for
// consumers of this module.
Logic get val => output('val');
// This counter was written with 8-bit width.
static const int width = 8;
// We must provide instructions for where to find the SystemVerilog that
// is used to build the wrapped module.
// Note that the path is relative to where we will configure the SystemVerilog
// simulator to be running.
[@override](/user/override)
List<String>? get verilogSources => ['../counter.sv'];
Counter(Logic en, Logic reset, Logic clk, {super.name = 'counter'})
// The `definitionName` is the name of the SystemVerilog module
// we're instantiating.
: super(definitionName: 'Counter') {
// Register inputs and outputs of the module in the constructor.
// These name *must* match the names of the ports in the SystemVerilog
// module that we are wrapping.
en = addInput('en', en);
reset = addInput('reset', reset);
clk = addInput('clk', clk);
addOutput('val', width: width);
}
}
// Let's simulate with this counter a little, generate a waveform, and take a
// look at generated SystemVerilog. This little simulation mirrors closely the
// original example from ROHD:
// https://github.com/intel/rohd/blob/main/example/example.dart
Future<void> main({bool noPrint = false}) async {
// Define some local signals.
final en = Logic(name: 'en');
final reset = Logic(name: 'reset');
// Generate a simple clock. This will run along by itself as
// the Simulator goes.
final clk = SimpleClockGenerator(10).clk;
// Make our cosimulated counter.
final counter = Counter(en, reset, clk);
// Before we can simulate or generate code with the counter, we need
// to build it.
await counter.build();
// **Important for Cosim!**
// We must connect to the cosimulation process with configuration information.
await Cosim.connectCosimulation(CosimWrapConfig(
// The SystemVerilog will simulate with Icarus Verilog
SystemVerilogSimulator.icarus,
// We can generate waves from the SystemVerilog simulator.
dumpWaves: !noPrint,
// Let's specify where we want our SystemVerilog simulation to run.
// This is the directory where temporary files, waves, and output
// logs may appear.
directory: './example/tmp_cosim/',
));
// Now let's try simulating!
// Let's start off with a disabled counter and asserting reset.
en.inject(0);
reset.inject(1);
// Attach a waveform dumper so we can see what happens in the ROHD simulator.
// Note that this is a separate VCD file from what the SystemVerilog simulator
// will dump out.
if (!noPrint) {
WaveDumper(counter, outputPath: './example/tmp_cosim/rohd_waves.vcd');
}
// Drop reset at time 25.
Simulator.registerAction(25, () => reset.put(0));
// Raise enable at time 45.
Simulator.registerAction(45, () => en.put(1));
// Print a message every time the counter value changes.
counter.val.changed.listen((event) {
if (!noPrint) {
print('Value of the counter changed @${Simulator.time}: $event');
}
});
// Print a message when we're done with the simulation!
Simulator.registerAction(100, () {
if (!noPrint) {
print('Simulation completed!');
}
});
// Set a maximum time for the simulation so it doesn't keep running forever.
Simulator.setMaxSimTime(100);
// Kick off the simulation.
await Simulator.run();
// We can take a look at the waves now.
if (!noPrint) {
print('To view waves, check out waves with a waveform viewer'
' (e.g. `gtkwave waves.vcd` and `gtkwave rohd_waves.vcd`).');
}
}
更多关于Flutter未知功能插件rohd_cosim的潜在用途探索的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html