Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Language Simulation License

English | 中文


corosim

corosim is a C++20 coroutine-based co-simulation engine for Verilator. It maps co_await to delta-cycle and timed-event scheduling, letting you write concurrent hardware testbenches without manual state machines or eval loops.

Features

  • Coroutine concurrencyco_await posedge(), co_await delay(), co_await any()
  • Non-blocking signalssig.next(val) with delta-cycle scheduling
  • Trigger-based processessim.always() for repeating triggers, sim.instance() for one-shot coroutines
  • Phase-aligned I/Osim.sample() / sim.drive() for BFM-style transactions
  • Software signals — cross-process sync without DUT binding

Quick Start

1. Install Dependencies

# macOS (with Homebrew)
brew install verilator

# Ubuntu/Debian
sudo apt-get install verilator g++ make

2. Clone and Run

git clone https://github.com/dozecat/corosim.git
cd corosim/examples/async_fifo/sim/tb

make        # Compile and run simulation

3. View Waveform

gtkwave waveform.vcd

Project Structure

corosim/
├── src/                        # Library source
│   ├── corosim.hpp             # Umbrella header
│   ├── core/                   # Kernel, Sim<TOP>, Dut
│   ├── signal/                 # Signal<T>, wide, helpers
│   ├── trigger/                # Edge, delay, any waiters
│   ├── process/                # Task, Process, ProcessManager
│   └── scheduler/              # Delta-cycle + timed event engine
└── examples/
    ├── async_fifo/             # Dual-clock async FIFO (basic)
    └── axis_async_fifo/        # AXI4-Stream async FIFO (advanced, with BFM)

API Reference

Sim<TOP> — User-Facing Facade

Most testbenches interact through Sim<TOP>, which owns a Kernel and provides signal binding, process registration, and clock generation:

#include "corosim.hpp"
using namespace corosim;

Vasync_fifo top;
Sim sim(top);                         // wrap the Verilator top

auto& clk = sim.sig(top.clk);         // bind a DUT signal
auto& rst = sim.sig<uint8_t>();       // software-only signal (no DUT)

sim.clock(clk, 10);                   // toggle clk every 5 time units

sim.run(500, [&](sim_time t) { tfp.dump(t); });

For pointer-to-member binding, use Dut<TOP>:

Dut<TOP> dut(top, sim.signals());
auto& clk = dut.sig(&TOP::clk);
auto& rst = dut.sig(&TOP::rst);

Signal — Verilator Field Binding

Signal<uint8_t>  sig(&top->sig_field);  // bind to a Verilator signal
Signal<bool>     flag;                  // software-only (no binding)

sig.next(val);    // non-blocking assignment (applied at delta end)
sig.read();       // read current value
auto v = sig;     // implicit read

// Mapping from Verilator types:
Signal<uint8_t>  rst(&top.rst);     // 1-bit   → CData
Signal<uint8_t>  data(&top.data);   // 8-bit   → CData
Signal<uint16_t> wide(&top.wide);   // 16-bit  → SData

For wide vectors (VlWide<N>), use Signal<VlWide<N>> — see signal/wide.hpp.

Triggers

Trigger Type constraint sim.always() co_await
posedge(sig) sizeof(T) <= 1
negedge(sig) sizeof(T) <= 1
change(sig) any Signal<T>
delay(n)

posedge/negedge require 1-byte signal types; change works with any signal width.

Processes

// Auto-repeat on trigger
sim.always(posedge(clk), [&] { cnt.next(cnt.read() + 1); });
sim.always(delay(5), [&] { clk.next(!clk.read()); });

// One-shot coroutine (lambda)
sim.instance([&]() -> Task {
    co_await delay(30);
    go.next(true);
});

// One-shot coroutine (standalone function)
sim.instance(reset, &rst, &wr_clk);

Coroutine functions support co_await for synchronization:

Task reset(Signal<uint8_t>* rst, Signal<uint8_t>* clk) {
    rst->next(1);
    for (int i = 0; i < 5; i++) co_await posedge(*clk);
    rst->next(0);
}

co_await delay(30);                   // wait 30 time units
co_await posedge(clk);                // wait for rising edge

// Multi-condition wait — returns winning trigger index
int w = co_await any(posedge(clk), delay(200));
// w == 0: posedge(clk) fired first
// w == 1: delay(200) fired first

For phase-aligned I/O, sample runs before DUT eval and drive runs after:

sim.sample(posedge(clk), [&] { bfm.sample_inputs(); });
sim.drive(posedge(clk),  [&] { bfm.drive_outputs(); });

Examples

async_fifo

Dual-clock asynchronous FIFO testbench demonstrating basic triggers, software signals, coroutine processes, and VCD dump.

cd examples/async_fifo/sim/tb
make

axis_async_fifo

AXI4-Stream async FIFO testbench using BFM with sample/drive phase hooks. Frame-fifo mode only (aux FIFO stores per-frame side-channel signals; bad frames are detected and discarded).

cd examples/axis_async_fifo/sim/tb
make

Dependencies

  • C++20 (coroutines)
  • Verilator 5.x
  • Make

License

MIT License — see LICENSE.


corosim

corosim 是一个基于 C++20 协程的 Verilator 协同仿真引擎。它将 co_await 映射为 delta 周期和定时事件调度,用于编写并发硬件测试台。

特性

  • 协程并发co_await posedge()co_await delay()co_await any()
  • 非阻塞信号sig.next(val),delta 周期调度
  • 触发进程sim.always() 重复触发,sim.instance() 一次性协程
  • 相位 I/Osim.sample() / sim.drive() 用于 BFM 总线事务
  • 软件信号 — 无需 DUT 绑定的跨进程同步

快速开始

1. 安装依赖

# macOS (使用 Homebrew)
brew install verilator

# Ubuntu/Debian
sudo apt-get install verilator g++ make

2. 克隆并运行

git clone https://github.com/dozecat/corosim.git
cd corosim/examples/async_fifo/sim/tb

make        # 编译并运行仿真

3. 查看波形

gtkwave waveform.vcd

项目结构

corosim/
├── src/                        # 库源码
│   ├── corosim.hpp             # 总头文件
│   ├── core/                   # 引擎核心、Sim<TOP>、Dut
│   ├── signal/                 # Signal<T>、wide、helpers
│   ├── trigger/                # 边沿、延时、多条件等待
│   ├── process/                # Task、Process、ProcessManager
│   └── scheduler/              # delta 周期 + 定时事件调度
└── examples/
    ├── async_fifo/             # 双时钟异步 FIFO(基础)
    └── axis_async_fifo/        # AXI4-Stream 异步 FIFO(高级,带 BFM)

API 参考

Sim<TOP> — 用户接口

大部分测试台通过 Sim<TOP> 与引擎交互:

#include "corosim.hpp"
using namespace corosim;

Vasync_fifo top;
Sim sim(top);

auto& clk = sim.sig(top.clk);         // 绑定 DUT 信号
auto& rst = sim.sig<uint8_t>();       // 纯软件信号

sim.clock(clk, 10);                   // 每 5 时间单位翻转 clk

sim.run(500, [&](sim_time t) { tfp.dump(t); });

使用 Dut<TOP> 进行成员指针绑定:

Dut<TOP> dut(top, sim.signals());
auto& clk = dut.sig(&TOP::clk);
auto& rst = dut.sig(&TOP::rst);

Signal — Verilator 信号绑定

Signal<uint8_t>  sig(&top->sig_field);  // 绑定 Verilator 信号
Signal<bool>     flag;                  // 纯软件信号

sig.next(val);    // 非阻塞赋值(delta 结束时提交)
sig.read();       // 读当前值
auto v = sig;     // 隐式读取

// Verilator 类型映射:
Signal<uint8_t>  rst(&top.rst);     // 1-bit   → CData
Signal<uint8_t>  data(&top.data);   // 8-bit   → CData
Signal<uint16_t> wide(&top.wide);   // 16-bit  → SData

宽向量(VlWide<N>)使用 Signal<VlWide<N>>

触发事件

触发器 类型限制 sim.always() co_await
posedge(sig) sizeof(T) <= 1
negedge(sig) sizeof(T) <= 1
change(sig) 任意 Signal<T>
delay(n)

posedge/negedge 仅支持 1 字节信号;change 支持任意宽度。

进程

// 触发重复执行
sim.always(posedge(clk), [&] { cnt.next(cnt.read() + 1); });
sim.always(delay(5), [&] { clk.next(!clk.read()); });

// 一次性协程 (lambda)
sim.instance([&]() -> Task {
    co_await delay(30);
    go.next(true);
});

// 一次性协程 (独立函数)
sim.instance(reset, &rst, &wr_clk);

协程函数中使用 co_await 同步:

Task reset(Signal<uint8_t>* rst, Signal<uint8_t>* clk) {
    rst->next(1);
    for (int i = 0; i < 5; i++) co_await posedge(*clk);
    rst->next(0);
}

co_await delay(30);
co_await posedge(clk);

// 多条件等待 — 返回先触发的索引
int w = co_await any(posedge(clk), delay(200));
// w == 0: posedge(clk) 先到
// w == 1: delay(200) 先到

sample 在 DUT eval 前执行,drive 在 eval 后执行:

sim.sample(posedge(clk), [&] { bfm.sample_inputs(); });
sim.drive(posedge(clk),  [&] { bfm.drive_outputs(); });

示例

async_fifo

双时钟异步 FIFO 测试,演示基本触发、软件信号、协程进程和 VCD 波形。

cd examples/async_fifo/sim/tb
make

axis_async_fifo

AXI4-Stream 异步 FIFO 测试,使用 BFM + sample/drive 相位钩子。仅 frame-fifo 模式(aux FIFO 存储帧级 side-channel 信号,检测并丢弃坏帧)。

cd examples/axis_async_fifo/sim/tb
make

依赖

  • C++20(协程支持)
  • Verilator 5.x
  • Make

版权说明

MIT License — 见 LICENSE

About

Coroutine simulation engine for verilator

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages