SystemC 学习之与 System Verilog 的混合仿真(九)

news2024/11/20 6:18:35

1、下载 uvmc (uvm connect)

https://download.csdn.net/download/yp18792574062/88529417?spm=1001.2014.3001.5501

2、配置相关环境变量

export UVM_HOME=${VCS_HOME}/etc/uvm
export UVMC_HOME=/home/yangpan/yangpan/uvmc/uvmc-2.3.1

然后执行 source ~/.zshrc 更新

3、编译 uvmc 自带的例子

编译之前需要更新 gcc 的版本,这里将 gcc 版本降低到 5.2.0,因为 vcs2018 只支持少数几个 gcc 版本,降低 gcc 的版本可以参考之前的文章

cd examples/converters
ln -sf Makefile.vcs Makefile
make comp EXAMPLE=sv2sc
./simv
make comp EXAMPLE=sc2sv
./simv

4、自己动手写一个 sc 到 sv 再到 sc 的例子

因为对 system verilog 不熟悉,所以这里 sv 在接收到数据后就立马发送给 sc,实现一个数据的回传效果

Makefile

SYSCAN = syscan -cpp g++ -cc gcc -tlm2                                          \
         -cflags -g                                                             \
         -cflags -DVCS                                                          \
         -cflags -std=c++11                                                     \
         -cflags -I${VCS_HOME}/etc/systemc/tlm/include/tlm/tlm_utils            \
         -cflags -I${UVMC_HOME}/src/connect/sc                                  \
         -cflags -I${UVMC_HOME}/src                                             \
         -cflags -Icpp                                                          \
         ${UVMC_HOME}/src/connect/sc/uvmc.cpp

VLOGAN = vlogan -q -sverilog                                                          \
         +incdir+${UVM_HOME}/src ${UVM_HOME}/src/uvm_pkg.sv                           \
         +incdir+${UVMC_HOME}/src/connect/sv ${UVMC_HOME}/src/connect/sv/uvmc_pkg.sv  \
         -timescale=1ns/1ps

VCS_ELAB = vcs -q -sysc=deltasync -lca                                          \
           -sysc -cpp g++ -cc gcc                                               \
           -timescale=1ns/1ps                                                   \
           -CFLAGS -DVCS ${UVM_HOME}/src/dpi/uvm_dpi.cc

CURRENT_DIR = $(shell pwd)
CPP_DIR = $(shell find $(CURRENT_DIR)/cpp -maxdepth 20 -type d)
SRCS_CPP += $(foreach dir, $(CPP_DIR), $(wildcard $(dir)/*.cpp))
SRCS_CC += $(foreach dir, $(CPP_DIR), $(wildcard $(dir)/*.cc))
SRCS_C += $(foreach dir, $(CPP_DIR), $(wildcard $(dir)/*.c))
SV_DIR = $(shell find $(CURRENT_DIR)/sv -maxdepth 20 -type d)
SRCS_SV += $(foreach dir, $(SV_DIR), $(wildcard $(dir)/*.sv))

comp:
    $(SYSCAN) -full64 $(SRCS_CPP) $(SRCS_CC) $(SRCS_C)
    $(VLOGAN) -full64 $(SRCS_SV) +define+UVM_OBJECT_MUST_HAVE_CONSTRUCTOR
    $(VCS_ELAB) -full64 sv_main sc_main  # 这里要写 verilog、sv、sc 对外的模块名字
    
clean:
    rm -rf simv* work csrc ucli.key vc_hdrs.h vcs.log AN* *.log *.log.cmp *.vpd DVE* .vlogan*
    
run:
    ./simv

Systemc 发送模块

// sender.h
#pragma once
#include "systemc.h"
#include <string>
#include <iomanip>
#include "uvmc.h"
using namespace uvmc;
#include <tlm.h>
using namespace sc_core;
using namespace tlm;
#include "simple_initiator_socket.h"
using tlm_utils::simple_initiator_socket;

class producer : public sc_module {
public:
    SC_HAS_PROCESS(producer);
    producer(sc_module_name ins_name);
    virtual ~producer();
    void run();

public:
    simple_initiator_socket<producer> out;
    tlm_analysis_port<tlm_generic_payload> ap;
    sc_event done;
};

class Sender : public producer {
public:
    SC_HAS_PROCESS(Sender);
    Sender(sc_module_name instname);
    ~Sender();
    void SendData();
};

// sender.cpp
#include "sender.h"

#include <string>

producer::producer(sc_module_name ins_name) : sc_module(ins_name), out("out"), ap("ap") {
    SC_THREAD(run);
}

producer::~producer() = default;

void producer::run() {
    for (int i = 0; i < 10; ++i) {
        std::string data = "xxxxx: " + std::to_string(i);
        tlm_generic_payload gp;
        gp.set_data_ptr((uint8_t*)data.c_str());
        gp.set_command(TLM_WRITE_COMMAND);
        gp.set_address(rand());
        sc_time delay = sc_time(10, SC_NS);
        gp.set_data_length(data.length());
        out->b_transport(gp, delay);
        ap.write(gp);
        wait(20, SC_NS);
    }
    done.notify();
}

Sender::Sender(sc_module_name instname) : producer(instname) {
    SC_THREAD(SendData);
}

Sender::~Sender() = default;

void Sender::SendData() {
    uvmc_raise_objection("run");
    wait(done);
    uvmc_drop_objection("run");
}

SystemC 接收模块

// receiver.h
#pragma once

#include <string>
#include <iomanip>
#include <systemc.h>
#include <tlm.h>
using namespace tlm;

#include "simple_target_socket.h"
using tlm_utils::simple_target_socket;

class Receiver : public sc_module {
public:
    SC_HAS_PROCESS(Receiver);
    Receiver(sc_module_name ins_name);
    ~Receiver();

    virtual void b_transport(tlm_generic_payload &gp, sc_time &t);

public:
    simple_target_socket<Receiver> in;
    tlm_analysis_port<tlm_generic_payload> ap;
};


// receiver.cpp
#include "receiver.h"

Receiver::Receiver(sc_module_name ins_name) : sc_module(ins_name), in("in"), ap("ap") {
    in.register_b_transport(this, &Receiver::b_transport);
}

Receiver::~Receiver() = default;

void Receiver::b_transport(tlm_generic_payload &gp, sc_time &t) {
    unsigned char* data = gp.get_data_ptr();
    int len = gp.get_data_length();
    std::cout << "receive data: " << (char*)data << std::endl;
    ap.write(gp);
}

sc_main

// main.cpp
#include <systemc.h>
#include "receiver.h"
#include "sender.h"

int sc_main(int argc, char* argv[]) {
    Sender sender("sender");
    uvmc_connect(sender.out, "42");
    Receiver receiver("receiver");
    uvmc_connect(receiver.in, "foo");
    sc_start(1000, SC_NS);
    return 0;
}

System Verilog 数据回传模块

// sv_loop.sv
import uvm_pkg::*; 
import uvmc_pkg::*;

`include "uvm_macros.svh"
class producer extends uvm_component;
    uvm_tlm_b_initiator_socket #() out;
    uvm_analysis_port #(uvm_tlm_gp) ap;
    uvm_phase run_ph;
    `uvm_component_utils(producer)
    function new(string name, uvm_component parent=null);
        super.new(name,parent);
        out = new("out", this);
        ap = new("ap", this);
        run_ph = uvm_run_phase::get();
    endfunction

    task send(uvm_tlm_gp t, uvm_tlm_time delay);
        run_ph.raise_objection(this);
        out.b_transport(t, delay);
        ap.write(t);
        run_ph.drop_objection(this);
    /*
        uvm_tlm_gp gp = new;
        uvm_tlm_time delay = new("del",1e-12);
        run_ph.raise_objection(this);
        delay.set_abstime(10,1e-9);
        assert(gp.randomize() with { gp.m_byte_enable_length == 0;
                                                 gp.m_length inside {[1:8]};
                                                 gp.m_data.size() == m_length; } );
        `uvm_info("PRODUCER/PKT/SEND",{"\n",gp.sprint()},UVM_MEDIUM)
        out.b_transport(gp,delay);
        ap.write(gp);
        #100;
        `uvm_info("PRODUCER/END_TEST", "Dropping objection to ending the test",UVM_LOW)
        run_ph.drop_objection(this);
    */
    endtask
endclass

class consumer extends uvm_component;
    uvm_tlm_b_target_socket #(consumer) in;
    uvm_analysis_port #(uvm_tlm_generic_payload) ap;
    producer prod;
    `uvm_component_utils(consumer)
    function new(string name, uvm_component parent=null);
        super.new(name,parent);
        in = new("in",  this);
        ap = new("ap", this);
        prod = new("prod");
        uvmc_tlm #()::connect(prod.out, "foo");
    endfunction

    virtual task b_transport(uvm_tlm_gp t, uvm_tlm_time delay);
        // `uvm_info("CONSUMER/PKT/RECV",{"\n",t.sprint()},UVM_MEDIUM)
        // #(delay.get_realtime(1ns,1e-9));
        // delay.reset();
        // ap.write(t);
        // uvm_phase phase;
        prod.send(t, delay);
    endtask
endclass

module sv_main;
    consumer cons = new("cons");
    // producer prod = new("prod");
    initial begin
        uvmc_tlm #()::connect(cons.in, "42");
        // uvmc_tlm #()::connect(prod.out, "foo");
        run_test();
    end
endmodule

5、编译运行

make comp
./simv

注意如果编译在 uvmc_connect.cpp 263 行报错,提示错误如下

那么需要将对应行代码修改为

cerr << "UVMC Error: Cannot open connections file '" << filename << "'" << endl;

打印输出

6、关键点

Systemc 和 System Verilog 的通信接口有点类似于 c++ 里面的 socket 通信一样,如果要通信,那么需要绑定到相同的一个端口上,这里的端口是一个字符串

// systemc
Sender sender("sender");
uvmc_connect(sender.out, "42");
Receiver receiver("receiver");
uvmc_connect(receiver.in, "foo");

// system verilog
consumer cons = new("cons");
uvmc_tlm #()::connect(cons.in, "42");
prod = new("prod");
uvmc_tlm #()::connect(prod.out, "foo");

 对于 sv 接收,需要重写 b_transport 方法,并且需要定义输入 socket 接口

uvm_tlm_b_target_socket #(consumer) in;
uvm_analysis_port #(uvm_tlm_generic_payload) ap;

virtual task b_transport(uvm_tlm_gp t, uvm_tlm_time delay);
endtask

 对于 sv 发送,需要定义输出 socket 接口,并且调用 b_transport 进行发送

uvm_tlm_b_initiator_socket #() out;
uvm_analysis_port #(uvm_tlm_gp) ap;

run_ph.raise_objection(this);
out.b_transport(t, delay);
ap.write(t);
run_ph.drop_objection(this);

 对于 sc 的接收端,需要定义输入 socket 接口,然后重写了 b_transport 方法接收数据

simple_target_socket<Receiver> in;
tlm_analysis_port<tlm_generic_payload> ap;

 对于 sc 的发送端,需要定义输出 socket 接口,然后调用 b_transport 发送

simple_initiator_socket<producer> out;
tlm_analysis_port<tlm_generic_payload> ap;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1210282.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

让公有云服务“宁安如梦”的“定心丸”在哪里?

电视剧《宁安如梦》正在热播中&#xff0c;该剧讲述了主人公在经历人生的重大风险后&#xff0c;重获新生再活一遍&#xff0c;以确定性的方式抵御和化解原有的重大风险。然而&#xff0c;在现实的生活中&#xff0c;却没有这样的重来机会。 2023年11月13日&#xff0c;Gartne…

二、服务拆分及远程调用

目录 一、注意事项&#xff1a; 1.单一职责: 2.数据独立: 3.面向服务&#xff1a; 二、服务拆分例子&#xff1a; 三、远程调用例子&#xff1a; 微服务调用方式&#xff1a; 四、提供者与消费者 服务调用关系&#xff1a; 一、注意事项&#xff1a; 1.单一职责: 不同…

某建筑网页js逆向分析过程(有坑)

某建筑网页&#xff1a; 网站&#xff1a; import base64 # 解码 website base64.b64decode(aHR0cHM6Ly9qenNjLm1vaHVyZC5nb3YuY24vZGF0YS9jb21wYW55.encode(utf-8)) print(website)JSON.parse() ​ 当你有一个包含JSON字符串的变量时&#xff0c;你可以使用JSON.parse()将…

No209.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

19 - 如何用协程来优化多线程业务?

近几年&#xff0c;国内很多互联网公司开始使用或转型 Go 语言&#xff0c;其中一个很重要的原因就是 Go 语言优越的性能表现&#xff0c;而这个优势与 Go 实现的轻量级线程 Goroutines&#xff08;协程 Coroutine&#xff09;不无关系。那么 Go 协程的实现与 Java 线程的实现有…

高效免费办公神器——ONLYOFFICE入手指南

前言&#xff1a; 作为开发者&#xff0c;有时候经常为寻找适合的开发工具而苦恼&#xff1b;或者因为高昂的费用而犹豫不决&#xff1b;亦或喜欢的办公产品只能在单一的平台上使用&#xff0c;与其把时间花在复杂的工具使用上&#xff0c;不如节省出时间投入思考和技术的提升。…

【洛谷算法题】P5711-闰年判断【入门2分支结构】

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5711-闰年判断【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格式&a…

js写轮播图,逐步完善

目录 1、自动轮播 2、点击更换 3、自动播放加左右箭头点击切换 4、完整版轮播图 1、自动轮播 用定时器setInterval()来写&#xff0c;可以实现自动播放 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><met…

一例plugx样本的分析(AcroRd32cWP)

这是一例plugx的样本&#xff0c;使用了一个合法签名的程序 &#xff0c;使用侧加载的方式加载一个恶意的dll&#xff0c;解密一个dat文件来&#xff0c;在内存中执行一个反射型dll来完成恶意功能。 这个病毒会使用摆渡的方式的来窃取内网的文档数据&#xff0c;具有严重的失泄…

Git新建分支

修改代码之Git策略思考&#xff1a; 有三种办法&#xff1a; 需要在主分支上新建一个分支&#xff0c;不合并新建版本。其实也是先新建一个分支&#xff0c;然后合并到主分支&#xff0c;再删除分支。直接新建远程仓库。 考虑&#xff0c;3&#xff09;最浪费&#xff0c;其…

QGIS之十七按范围选择要素

效果 步骤 1、准备数据 &#xff08;1&#xff09;、范围面 &#xff08;2&#xff09;、point 2、Qgis中裁剪 工具箱中搜索“裁剪” 注意编码问题 3、裁剪结果

Skybox天空盒子的更换教程_unity基础开发教程

Skybox天空盒子的更换 Skybox的下载与导入更换SkyboxSkybox属性自定义 Skybox的下载与导入 打开资源商店 搜索FREE Skybox 这里是我使用的是这一款资源&#xff0c;点击添加至我的资源 打开包管理器Package Manager Packages选择My Assets 搜索Sky 选择刚刚添加的天空盒子 点…

​TechSmith Camtasia 2024破解版功能介绍及使用教程

在现在的网络互联网时代&#xff0c;越来越多的人走上了自媒体的道路。有些自媒体人会自己在网络上录制精彩视频&#xff0c;也有一些人会将精彩、热门的电影剪辑出来再加上自己给它的配音&#xff0c;做成大家喜欢看的电影剪辑片段。相信不管大家是自己平时有独特的爱好也好、…

滚雪球学Java(63):Java高级集合之TreeSet:什么是它,为什么使用它?

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

【物联网】BDS/GNSS 全星座定位导航模块——ATGM332D-5N

随着科技的不断进步&#xff0c;导航系统已经成为我们日常生活中不可或缺的一部分。传统的导航系统往往只提供基本的地图和路线规划&#xff0c;对于一些特殊需求或个性化定位并不够满足。全星座定位导航模块的出现&#xff0c;为我们带来了全新的导航体验。通过结合星座学说和…

上海亚商投顾:沪指震荡反弹 鸿蒙、算力概念股集体爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日窄幅震荡&#xff0c;创业板指冲高回落&#xff0c;市场热点继续轮动。华为鸿蒙概念股继续活跃&#…

Leetcode刷题详解—— 图像渲染

1. 题目链接&#xff1a;733. 图像渲染 2. 题目描述&#xff1a; 有一幅以 m x n 的二维整数数组表示的图画 image &#xff0c;其中 image[i][j] 表示该图画的像素值大小。 你也被给予三个整数 sr , sc 和 newColor 。你应该从像素 image[sr][sc] 开始对图像进行 上色填充 。…

计算机组成原理——指令系统题库1-20

1、以下有关指令系统的说法中错误的是什么。 A、 指令系统是一台机器硬件能执行的指令全体 B、 任何程序运行前都要先转化为机器语言 C、 指令系统是计算机软件、硬件的界面 D、 指令系统和机器语言是无关的。 2、在CPU执行指令的过程中&#xff0c;指令的地址由什么给出。…

计算机缺失vcruntime140.dll如何修复?超简单的5个解决方法

在我们日常使用电脑的过程中&#xff0c;可能会遇到各种各样的问题和错误提示。其中&#xff0c;一个比较常见的错误提示就是“vcruntime140.dll丢失”。这个错误通常发生在我们尝试运行某个程序或应用时&#xff0c;系统无法找到或加载所需的vcruntime140.dll文件。 vcruntime…

又卷又累,救救一个将被随机拖死的程序员!

前两天在小红书上看到有人吐槽&#xff1a;“国内做程序员性价比不高&#xff0c;又卷又累&#xff0c;个人时间都被拖死了。” 现在普遍来讲&#xff0c;“卷”都是打工人的现状。 而至于国内程序员性价比不高的话&#xff0c;确实是肉少僧多。工作强度一加持&#xff0c;累自…