Flutter未知功能插件rohd_cosim的潜在用途探索

发布于 1周前 作者 zlyuanteng 来自 Flutter

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 模拟器:wrapcustomport

Wrap 配置

Wrap 配置是最简单的方式,适用于没有现有构建和模拟系统的情况。只需传递一个 CosimWrapConfig 对象给 Cosim.connectToSimulation 调用,并指定要使用的模拟器,ROHD Cosim 会自动处理其余部分,包括生成包装器和所有需要协同仿真的子模块。

Wrap Config Diagram

示例代码 example/main.dart 使用了 wrap 配置,是一个很好的入门参考。

Custom 配置

Custom 配置适用于已有构建系统的情况,希望尽量减少修改。传递一个 CosimCustomConfig 对象给 Cosim.connectToSimulation 调用,并提供如何启动模拟的信息,ROHD Cosim 会处理其余部分。

ROHD Cosim 会生成一个基于 cocotb 的 Python 连接器,由模拟器进程启动。ROHD Cosim 通过本地套接字与 Python 连接器通信,并监听来自 stdout 的端口信息。

Custom Config Diagram

Port 配置

Port 配置适用于不仅有自己的构建系统,还有自定义模拟运行系统的情况。传递一个 PortConfig 对象给 Cosim.connectToSimulation 调用,并指定要连接的 Unix 套接字端口。这样,ROHD Cosim 不再需要启动 SystemVerilog 模拟器,其他进程可以启动模拟器,然后 ROHD Cosim 会在指定端口上连接。

Port Config Diagram

完整示例 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

1 回复

更多关于Flutter未知功能插件rohd_cosim的潜在用途探索的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在探索Flutter中未知功能插件rohd_cosim的潜在用途时,我们可以从插件的名称和可能的领域入手进行分析。rohd_cosim这个名称可能代表“Register-Transfer Level (RTL) Hardware-Software Co-Simulation”,这是一种在硬件设计和软件开发中常用的技术,用于验证硬件与软件之间的交互。

虽然我们没有具体的插件文档或源代码,但我可以提供一个假设性的代码案例,展示如何在Flutter应用中集成一个假想的硬件模拟功能,这可能类似于rohd_cosim插件可能提供的功能。请注意,以下代码是概念性的,并不直接对应于实际的rohd_cosim插件,因为该插件的具体实现细节未知。

假设性的Flutter与硬件模拟集成代码案例

1. 添加依赖项(假设rohd_cosim已发布到pub.dev)

首先,我们需要在pubspec.yaml文件中添加对rohd_cosim的依赖项(注意:这一步是假设性的,因为实际插件可能不存在或名称不同):

dependencies:
  flutter:
    sdk: flutter
  rohd_cosim: ^x.y.z  # 假设的版本号

2. 初始化硬件模拟环境

在Flutter应用的某个组件或服务的初始化过程中,我们可以设置硬件模拟环境。以下是一个假设性的示例,展示如何初始化并使用模拟环境:

import 'package:flutter/material.dart';
import 'package:rohd_cosim/rohd_cosim.dart';  // 假设的导入路径

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('ROHD Co-Simulation Demo'),
        ),
        body: CoSimDemo(),
      ),
    );
  }
}

class CoSimDemo extends StatefulWidget {
  @override
  _CoSimDemoState createState() => _CoSimDemoState();
}

class _CoSimDemoState extends State<CoSimDemo> {
  late HardwareSimulationEnvironment _simEnv;

  @override
  void initState() {
    super.initState();
    // 初始化硬件模拟环境
    _simEnv = HardwareSimulationEnvironment();
    // 配置模拟环境(假设的方法)
    _simEnv.configureWithHardwareDescription(...);
    // 启动模拟
    _simEnv.startSimulation();
  }

  @override
  void dispose() {
    // 停止模拟并清理资源
    _simEnv.stopSimulation();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text('Hardware Simulation Status: $_simEnv.simulationStatus'),
          ElevatedButton(
            onPressed: () {
              // 触发某种硬件操作
              _simEnv.triggerHardwareEvent(...);
            },
            child: Text('Trigger Hardware Event'),
          ),
        ],
      ),
    );
  }
}

// 假设的硬件模拟环境类
class HardwareSimulationEnvironment {
  String _simulationStatus = 'Stopped';

  String get simulationStatus => _simulationStatus;

  void configureWithHardwareDescription(Map<String, dynamic> description) {
    // 配置硬件描述(假设的实现)
  }

  void startSimulation() {
    // 启动模拟逻辑
    _simulationStatus = 'Running';
    // 这里可以添加实际的模拟逻辑,比如定时器、事件循环等
  }

  void stopSimulation() {
    // 停止模拟逻辑
    _simulationStatus = 'Stopped';
    // 清理资源
  }

  void triggerHardwareEvent(Map<String, dynamic> event) {
    // 处理硬件事件(假设的实现)
    print('Hardware event triggered: $event');
  }
}

结论

上述代码案例是假设性的,旨在展示如何在Flutter应用中集成一个潜在的硬件模拟功能。实际的rohd_cosim插件可能有完全不同的API和用法。为了准确了解如何使用该插件,建议查阅其官方文档或源代码(如果可用)。如果rohd_cosim是一个私有或内部插件,那么获取相关文档和支持将至关重要。

回到顶部