首页
书签
论坛
网盘
邮件
壁纸
影视
在线音乐
更多
直播
统计
个人微博
云笔记
云存储
图片视频
友链
留言
关于
Search
1
文档内容搜索哪家强? 15款文件搜索软件横向评测
13 阅读
2
常见系统部署(1)
11 阅读
3
makfile 知识汇总
8 阅读
4
欢迎使用 Typecho
5 阅读
5
打造Ventoy多功能多系统启动U盘
5 阅读
默认分类
数字电路
芯片后端
模拟电路
芯片验证
原型验证
算法与架构
DFX与量产
windows设置
Linux设置
MacOS设置
移动OS设置
软件方案
登录
Search
标签搜索
python
PyQT
systemverilog
Alist
Docker
cadence
sv
webdav
vscode
cpp
upf
ESL
TLM
浏览器
virtuoso
tsmc8rf
TSMC
CXL
PCIE
Yosys
bennyhe
累计撰写
46
篇文章
累计收到
8
条评论
首页
栏目
默认分类
数字电路
芯片后端
模拟电路
芯片验证
原型验证
算法与架构
DFX与量产
windows设置
Linux设置
MacOS设置
移动OS设置
软件方案
页面
书签
论坛
网盘
邮件
壁纸
影视
在线音乐
直播
统计
个人微博
云笔记
云存储
图片视频
友链
留言
关于
搜索到
9
篇与
的结果
2025-06-13
Verilog-AMS Verilog-A介绍
最近浅学了一下Verilog-AMS和Verilog-A的语法,记录一下自己理解:.Verilog-A是Verilog-AMS的子集,Verilog-A是只对analog电路进行建模的(运行基于Spice仿真器),而Verilog-AMS则可以对mixed- signal电路进行建模,包括了数字Verilog和Veirlog-A的语法 (运行基于 AMS混合信号仿真器).对于Verilog-A来说,其端口都是电器属性的,即类似于你从Spice里看到的那些模型一样;.对于Verilog-AMS来说,可以有logic类型的数字端口输入,然后electrical类型的模拟端口输出等等;.Verilog-AMS/A 可以从行为级和电路级对电路进行建模,简化了对于系统电路仿真时的复杂性;veirlog-AMS/Verilog-A中的关键概念:.分立信号转化为连续的信号 (对于数字只有0,1两种状态,但转化为连续信号,0->1过程值也会存在);.事件发生来触发信号变化(基于添加时间戳)(需解决设置的变量在事件未触发之前的初值问题);.在Verilog-A中,要时刻考虑Vth的特性,注意基于Verilog-A的model写法!.事件触发原理:在连续仿真器中,在发生事件处放置一个时间标记,从而将离散的仿真连续化;.model概念,branch概念,testbench概念(类似于verilog);一些关键代码:0. Verilog-A的阈值电压检测标准代码 (基于反相器):module inverter(out, in):output out;input in;electrical out, in;integer d_in; analog begin @(cross(V(in) - 0.5*V(vdd))) //穿越阈值电压写法(event statement),作用是在这个点建立时间戳,方便仿真器进行捕捉,否则捕捉不到这里发生的突变 ; //空白行,不在event发生时执行特定命令 d_in = V(in) > 0.5*V(vdd); //建立方波 V(out) <+ transition(!d_in, 0, 10n)*V(vdd); //用transition进行smooth处理 end endmodule.Model DAC (关键:electrical digital input -> (Vth) -> integer -> electrical analog differential output)module dac (out_p, out_n, in, clock, enable, vdda, gnda); output out_p, out_n; electrical out_p, out_n; input [7:0] in; electrical [7:0] in; input clock; electrical clock; input enable; electrical enable; input vdda; electrical vdda; input gnda; electrical gnda; integer code, en; real value;genvar i; analog begin // convert the input to a signed integer on positive clock edge @(cross(V(clock) - V(vdda)/2), +1) begin code = 0; for (i = 0; i < 8; i = i + 1) begin @(cross(V(in[i]) - V(vdda)/2)); if (V(in[i]) > V(vdda)/2) code = code + (1 << i); if (code >= 128) code = code - 256; value = code/256.0; end // reset output value when disabled @(cross(V(enable) - V(vdda)/2)) ; if (V(enable) < V(vdda)/2) value = 0; // drive the differential output V(out_p) <+ V(vdda)/2 + transition(value/2, 0, 10n); V(out_n) <+ V(vdda)/2 - transition(value/2, 0, 10n); end endmodule2. Model ADC (关键:electrical analog input -> (vth) -> integer -> electrical digital output)module adc (out, in, clk); output [5:0] out; input in, clk; electrical [5:0] out; electrical in, clk; parameter real vh = 1; parameter real vth = vh/2; parameter real tt = 100n from (0:inf); integer result; genvar i; analog begin @(cross(V(clk) - vth, +1)) begin result = 64*(V(in)+1)/2; if (result > 63) result = 63; else if (result < 0) result = 0; end for (i=0; i<6; i=i+1) V(out[i]) <+ transition(result & (1<<i) ? vh : 0, 0, tt); end endmodule3. Model Multiplexer: (关键:[3:0] sel 可以直接放入 @()中)module(out, in, sel); output out; electrical out; input [3:0] in; electrical [3:0] in; input [3:0] sel; logic [3:0] sel; analog begin @(sel) ; V(out) <+ V(in[0])*transition(sel === 0, 0, 100n); V(out) <+ V(in[1])*transition(sel === 1, 0, 100n); V(out) <+ V(in[2])*transition(sel === 2, 0, 100n); V(out) <+ V(in[3])*transition(sel === 3, 0, 100n); end endmodule4. 对于Cadence语法限制的标准处理方法:(Unfortunately, the Cadence simulator places unreasonable restrictions on event expressions in the analog block. Specifically, any digital signals used in an analog event expression must be preceded by either the posedge or negedge qualifiers. Thus, the model must be modified when intended for the Cadence simulator: )module cp (out, u, d): output out; electrical out; input u, d; logic u, d; reg sync = 0; always @(u or d) sync <= !sync; analog begin @(posedge sync or negedge sync) ; I(out) <+ 10u*(transition(d, 0, 1n) - transition(u, 0, 1n)); end endmodulean example of writing in Cadence:Cadence’s AMS simulator only supports discrete transitions filtered through posedge or negedge. Putting a discrete wire, discrete variable, or named event directly in a continuous event statement is not supported (as of 2014).real vgain;always @(gain) vgain = pow(10, (gain - 32.0)/20); real voffset;always @(offset) voffset = 1m*offset; reg break = 0;always @(vgain or voffset or en) break <= break; analog begin @(posedge break or negedge break) ; V(out) <+ transition(en ? vgain : 0, 0, 100n) * V(in) + voffset; endWith Cadence’s simulator, you can use the following for modeling multiplexers:module(out, in, sel); output out; electrical out; input [3:0] in; electrical [3:0] in; input [3:0] sel; logic [3:0] sel; reg sync = 0; always @(sel) sync <= !sync; analog begin @(posedge sync or negedge sync) ; V(out) <+ V(in[0])*transition(sel === 0, 0, 100n); V(out) <+ V(in[1])*transition(sel === 1, 0, 100n); V(out) <+ V(in[2])*transition(sel === 2, 0, 100n); V(out) <+ V(in[3])*transition(sel === 3, 0, 100n); end endmoduleTo implement a Verilog-A version of a multiplexer:module(out, in, sel); output out; electrical out; input [3:0] in; electrical [3:0] in; input [3:0] sel; logic [3:0] sel; parameter real vdd = 2.5; integer SEL; genvar i; analog begin // convert the input to an integer SEL = 0; for (i = 0; i < 2; i = i + 1) begin @(cross(V(sel[i]) - vdd/2)); if (V(sel[i]) > vdd/2) SEL = SEL + (1 << i); end V(out) <+ V(in[0])*transition(SEL == 0, 0, 100n); V(out) <+ V(in[1])*transition(SEL == 1, 0, 100n); V(out) <+ V(in[2])*transition(SEL == 2, 0, 100n); V(out) <+ V(in[3])*transition(SEL == 3, 0, 100n); end endmodule
2025年06月13日
5 阅读
0 评论
0 点赞
2025-06-13
vcs排除覆盖率虚高的方法
Synopsys vcs仿真器在收集覆盖率是怎么排除仿真glitch产生的覆盖率数据?在Synopsys VCS仿真器中,可以通过设置一些选项和参数来排除仿真glitch产生的覆盖率数据。以下是一些建议:使用-coverage exclude_glblck glitch选项:此选项将忽略由于glitch引起的全局时钟块的覆盖率。设置适当的仿真步长:使用较小的仿真步长可能会导致更多的glitch。尝试增加仿真步长以减少glitch的可能性。使用-vcs+lic+nowarn+assert选项:此选项会关闭所有警告,并启用所有的断言。这有助于捕获可能导致glitch的错误条件。调整覆盖率收集频率:通过调整-cm linecover或-cm togglecover等选项的频率,可以减少glitch的影响。在代码中添加额外的检查:如果可能,可以在设计代码中添加额外的检查,以确保信号稳定后再进行覆盖率收集。分析覆盖率报告:查看覆盖率报告并识别哪些区域可能存在glitch。然后,可以在这些区域中添加额外的测试用例,以更好地覆盖这些情况。请注意,这些方法可能无法完全消除由glitch引起的覆盖率数据问题,但它们可以帮助减少此类问题的发生。在Synopsys VCS仿真器中,排除由于glitch(瞬时信号跳变)产生的覆盖率数据可以通过使用特定的编译和仿真选项来实现。以下是一些方法,这些方法基于上述文档中的信息:1.使用-cm_glitch选项:这个选项可以用来过滤掉由于glitch导致的额外夏盖率数据。例如,设置-cm_glitch 0可以过滤掉在0时刻由于glitchi产生的夏盖率数据。2.利用$cm_coverage系统函数:在Verilog:或SystemVerilog代码中,可以通过$cm_coverage系统函数动态地查询或修改夏盖率选项。这个函数可以用来在运行时使能或关闭特定的夏盖率类型,从而避免收集由于gtch产生的夏盖率数据3。3.设置-covg_cont_on_error选项:当仿真运行到非法功能夏盖率bin时,使用这个选项可以让仿真继续运行,而不是停止。这样可以避免由于错误或异常情况导致的覆盖率数据被错误地收集。通过上述方法,用户可以有效地排除由于gtc产生的夏盖率数据,确保覆盖率结果的准确性和可靠性。这些选项和函数提供了灵活性,使得覆盖率收集可以专注于用户感兴趣的特定仿真行为和事件,同时避免由于仿真过程中的瞬时信号跳变而引入的噪声。Synopsys vcs仿真器在收集覆盖率是怎么排除仿真0时刻的覆盖率数据在Synopsys VCS仿真器中,可以通过以下方法来排除仿真0时刻的覆盖率数据:使用-cm_init选项:此选项允许您指定一个时间点(以模拟周期为单位),从该时间点开始收集覆盖率数据。例如,如果您希望从第一个时钟边沿开始收集覆盖率数据,可以使用以下命令:-cm_init=1这将忽略仿真开始时的0时刻覆盖率数据。使用条件覆盖率:您可以使用条件覆盖率(CCOV)选项来控制何时开始收集覆盖率数据。通过在设计代码中添加相应的条件语句,可以在满足特定条件后开始收集覆盖率数据。例如:initial begin @(posedge clk); if (reset == 1'b0) begin $set_coverage_control("start"); end end在代码中添加额外的检查:如果可能,可以在设计代码中添加额外的检查,以确保信号稳定后再进行覆盖率收集。这可以帮助避免在仿真开始时收集不准确的覆盖率数据。请注意,这些方法可能无法完全消除由仿真0时刻引起的覆盖率数据问题,但它们可以帮助减少此类问题的发生。当然,以下是更多关于如何在Synopsys VCS仿真器中排除仿真0时刻的覆盖率数据的方法:使用延迟初始化(Deferred Initialization):通过使用VCS的延迟初始化功能,可以在仿真开始时避免某些模块或信号被初始化。这可以帮助确保在收集覆盖率数据之前,所有必要的信号和模块都已经稳定。分析覆盖率报告:查看覆盖率报告并识别哪些区域可能存在由于仿真0时刻导致的问题。然后,可以针对这些区域编写额外的测试用例,以更好地覆盖这些情况。使用-cm_control选项:此选项允许您控制何时开始和停止收集覆盖率数据。您可以根据需要创建多个覆盖组,并为每个组设置不同的起始和结束时间点。例如:-cm_control "start_group1:2; end_group1:3" -cm_control "start_group2:5; end_group2:7"调整仿真步长:尝试增加仿真步长以减少由仿真0时刻引起的不准确的覆盖率数据。验证设计代码:检查您的设计代码,确保在仿真开始时没有触发任何不应发生的事件或状态变化。这可能包括复位、中断或其他可能导致覆盖率数据问题的条件。请记住,这些方法可能会有所帮助,但可能无法完全消除由仿真0时刻引起的覆盖率数据问题。在实际应用中,您可能需要结合多种方法来优化覆盖率数据的质量。在Synopsys VCS仿真器中,排除仿真0时刻的夏盖率数据可以通过设置特定的编译和仿真选项来实现。以下是一些方法和选项,这些方法基于上述文档中的信息:1.使用编译选项-cmhier来指定要收集覆盖率的模块、实例和子层次结构,以及要排除的源文件。例如,如果你想排除某个模块及其子模块的夏盖率,可以在-cm_hier配置文件中使用+tree instance_name[level_number]来指定只编译和收集夏盖率的实例和子实例,而忽略其他实例1。2.利用仿真选项-cm来控制覆盖率的收集。例如,如果你想排除0时刻的某些wys块的夏盖率,可以通过设置-cm选项来指定不收集特定类型的覆盖率,如tg1(翻转覆盖率)或1ine(代码行覆盖本)3.使用系统函数$cm_coverage()在仿真过程中动态地开启或关闭覆盖率的收集。通过在仿真脚本中设置条件,可以在0时刻之后开启夏盖率收集,从而排除0时刻的覆盖率数据1。4.在仿真脚本中设置条件,以确保在0时刻不执行某些测试用例或测试序列,这样可以避免在0时刻收集到不希望的夏盖率数据。5.使用urg命令行工具来合并覆盖率数据时,可以通过-dbname选项指定要合并的覆盖率数据库文件,而不包括0时刻的数据。此外,可以使用-orep0rt选项来阻止生成包含0时刻数据的夏盖率报告。通过上述方法,用户可以根据需要排除仿真0时刻的夏盖率数据,以便更准确地分析和评估仿真结果。这些方法提供了灵活性,使得覆盖率收集可以专注于用户感兴趣的特定仿真行为和事件。
2025年06月13日
3 阅读
0 评论
0 点赞
2025-06-06
SystemVerilog和SystemC协同验证环境介绍(2)
1、下载 uvmc (uvm connect)https://download.csdn.net/download/yp18792574062/88529417?spm=1001.2014.3001.55012、配置相关环境变量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 ./simv4、自己动手写一个 sc 到 sv 再到 sc 的例子因为对 system verilog 不熟悉,所以这里 sv 在接收到数据后就立马发送给 sc,实现一个数据的回传效果MakefileSYSCAN = 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: ./simvSystemc 发送模块// 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 endmodule5、编译运行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;附录: sc_module 在 verilog 中例化调用vcs 编译运行过程(1)先编译systemcsyscan -full64 -sysc=dpi_if -cpp g++ -l syscan.log -tlm2 -cflags -DVCS ${C_SRC} -cflags "${C_DEFINE} ${INCLUDE_PATH}" $(pwd)/Components/TOP.cpp:TOP 其中C_SRC 在makefile 中定义:C_SRC=$(shell find ./ -path "./csrc" -prune -o -path "./TEST" -prune -o -path "./Thirdparty" -prune -o -name '*TOP.cpp' -o -name 'main.cpp' -o -name '*.cpp' -print -o -name '*.c' -print -o -name '*.cc' -print | sed "s|^\.|$(pwd)|")C_SRC+=${VIP_ROOT_PATH}/3pt_utils/uvmc/src/connect/sc/uvmc.cppINCLUDE_PATH += -I$(VCS_HOME)/etc/systemc/accellera_install/systemc233-gcc7/include/tlm_utils(2)ln 到systemverilog 编译路径再编译systemverilog/verilogln -sTf ../../systemc/atomsimulator-main/csrc/sysc csrc/syscvcs $$XRUN_SYSC_FLIST $(COMP_OPTS) $(COMP_DEF) -f $(TBFILE) 2>&1 | tee cur_cmp.log 其中 XRUN_SYSC_FLIST="$(XRUN_SYSC_FLIST) -f ../systemc/atomsimulator-main/xrun.f"; \最后运行和一般只有systemverilog/verilog 没有区别./simv ${GUI} $(RUN_OPTS) $$COV_OPTS -l ./log/$(tc)_$$seed.log -ucli -do ../cfg/vcs_ucli.cfg \ +ntb_random_seed=$$seed +UVM_TESTNAME=$(tc) +WAVE_PATH=$(wave_path) +WAVE_MACRO=WAVE_$(wave_macro) +UVM_VERBOSITY=$(printlevel) $$VCS_FSDB_OPT $(FSDB_DBG_OTPS)附录: sc_module 在 verilog 中例化调用xrun 编译运行过程(1)生成文件列表,systemc可以和systemverilog 一起编译echo "-DSC_INCLUDE_DYNAMIC_PROCESSES -DXRUN -Wcxx,"${C_DEFINE}" ${INCLUDE_PATH} ${C_SRC} $(pwd)/Components/TOP.cpp $(pwd)/Components/TOP.v" | sed "s/ /\n/g" > xrun.ftlm 库路径:INCLUDE_PATH += -I$(XCELIUM_HOME)/tools/systemc/include/tlm_utils生成的文件列表 xrun.f 内容xrun 编译:xrun $$XRUN_SYSC_FLIST $(COMP_OPTS) $(COMP_DEF) -f $(TBFILE) 2>&1 | tee cur_cmp.log 其中:XRUN_SYSC_FLIST="$(XRUN_SYSC_FLIST) -f ../systemc/atomsimulator-main/xrun.f"; \运行和一般只有systemverilog/verilog 没有区别 xrun -R ${GUI} $(RUN_OPTS) $$COV_OPTS -l ./log/$(tc)_$$seed.log -input ../cfg/xrun_ucli.cfg \ -seed $$seed +ntb_random_seed=$$seed +WAVE_PATH=$(wave_path) +UVM_TESTNAME=$(tc) +WAVE_MACRO=WAVE_$(wave_macro) +UVM_VERBOSITY=$(printlevel) $(FSDB_DBG_OTPS); \附录: verilog module在sc 中例化调用,vcs 编译过程(顶层为sc)先编译verilog moudle 为 sc (就是转换为sc)vlogan -sysc -sc_model adder -sc_portmap the.map adder.v ${VLOGAN_EXTRA_SC} vlogan -sysc -sc_model multiplier -sc_portmap the.map multiplier.v ${VLOGAN_EXTRA_SC} 备注:VLOGAN_EXTRA_SC 可以为空然后再运行 syscsim -sysc -timescale=1ps/1ps -debug_access+all stimulus.cpp display.cpp subtracter.cpp top.cpp main.cpp -l comp.log ${SYSCAN_EXTRA} 如果verilog/systemverilog 和 sc 互相嵌套,可以在sc 调用verilog/systemverilog 中,将 verilog/systemverilog编译为sc,然后顶层如果verilog/systemverilog, 参考sc_module 在 verilog 中例化调用vcs 编译运行过程例子,编译后再运行。最后生成的fsdb 波形 可以显示systemc 时序描述这里u_TOP 就是systemc 顶层在verilog 中例化verdi 还不能直接debug systemc 源码,还需要研究————————————————部分来源于https://blog.csdn.net/yp18792574062/article/details/134375631
2025年06月06日
5 阅读
0 评论
0 点赞
2025-06-06
SystemVerilog和SystemC协同验证环境介绍(1)
先说结论:使用有公开源代码的uvmc,可以在不同仿真工具之间自由切换,vcs 也有自己的库但是只能在vcs 中使用,不能在xrun 和 子门子的EDA 仿真工具中使用。下图是一个典型的sv和sc协同验证环境的testbench。systemverilog大家都比较熟悉了,UVM就是基于sv创建的一个验证方法学的库。但是systemc用的就比较少。一般情况下,systemc用于:事务级别建模和验证HW / SW协同设计SOC架构分析和优化sv和sc协同验证环境,主要应用于:使用SystemC TL模型作为SystemVerilog测试平台中的参考模型(可重用)通过常用的SV测试平台确保RTL和SystemC TL模型的一致性SC和SV具有互操作性SC模块可以实例化SV,反之亦然具有混合语言组件的单模块层次结构SC和SV调度程序需要统一的语义混合语言系统应该像使用单一语言一样工作 引脚级:SC信号可以绑定到SV端口,反之亦然支持标准转化集使用简单,但很少能匹配设计流程要求TL:SC调用SV任务/函数,SV调用SC方法符合大多数设计流程要求更高的仿真和建模效率那么怎么将SV和SC两种不同的语言连接起来呢?大家都知道dpi可以作为c和sv之间互相访问的桥梁,那么它作为SV和SC之间的桥梁够用吗?当然不够。DPI只能调用非阻塞方法/任务/函数,但是不能调用耗时的任务/方法。仅指定C接口,而不能指定C ++,而不能指定SystemCDPI不能用于遍历SystemC层次结构,处理实例或对象不容易实现DPI构建为与单线程非时序的C程序的接口Mentor也开源了UVM Connect的库。UVM Connect是一个基于开源UVM的库,提供TLM1和TLM2连接以及SystemC和SystemVerilog UVM模型和组件之间的对象传递。它还提供了一个UVM Command API,用于从SystemC(或C或C ++)访问和控制UVM仿真。 UVM Connect允许您在UVM验证中重用SystemC架构模型作为参考模型和/或重用SystemVerilog UVM代理来验证SystemC中的模型。它还有效地扩展了您的VIP产品组合,因为您现在可以使用两种语言访问VIP。通过UVM Connect,您可以轻松开发集成的验证环境,从而充分利用每种语言的优势,最大限度地提高验证效率。UVM版本2.3增加了新的“快速打包程序”功能,可在通过TLM2连接传递通用有效负载时提高性能。它们还增加了对无限数据有效负载的支持以及对配置扩展的有限支持。附录:SV和SC语言之间的数据类型映射原文链接:https://blog.csdn.net/zhajio/article/details/81780576
2025年06月06日
2 阅读
0 评论
0 点赞
2025-06-03
sv中的功能覆盖率常用用法
下面是ieee文档自我提取的一些用法,这一篇的用法,更加全面:covergroup常用用法;covergroup cg_0; cp_name coverpoint signal_name{ bins bin_name0 = {[0:63],65};//两个bin, [0:63],65, 只要有里面的值收到了,就全覆盖 bins bin_name1[] = { [127:150],[148:191] }; // 65个bin,即[]中的每一个值都是一个bin; bins bin_name2 = { [1000:$] };//$表示结尾,即最大值; bins bin_name3[] = default;//其他的所有值,都划分到other, 也是要全部都收到; } endgroupbins with的用法; cp_name: coverpoint signal_name{ bins bin_name[] = {[0:255]} with (item % 3 == 0);//0-255中3的余数为0的部分,构成bin; } 也可以将with的内容封装成function; coverpoint b { bins func[] = b with (myfunc(item)); } wildcard; wildcard bins g12_15 = { 4'b11?? };//只要在1100~1111间的任何一个踩到了,就收到了; wildcard bins g12_15_array[] = { 4'b11?? };//加了[], 会给每一个符合条件的都产生一个bin ignore_bins; 当没有明确定义某一个coverpoint的bins时,EDA仿真工具会生成和收集所有可能的bins,当其中某些bins在RTL中永远都不可能覆盖到,可以使用ignore_bins进行忽略 covergroup cg23; coverpoint a { ignore_bins ignore_vals = {7,8};//不收集7,8; ignore_bins ignore_trans = (1=>3=>5);//不收集1,3,5这个序列; } endgroupillegal_bins; 某个值不可能收到,收到后报错;起到类似checker的作用; covergroup cg3; coverpoint b { illegal_bins bad_vals = {1,2,3}; illegal_bins bad_trans = (4=>5=>6); } endgroupcross;bit [31:0] a_var;bit [3:0] b_var;covergroup cov3 @(posedge clk); A: coverpoint a_var { bins yy[] = { [0:9] }; } CC: cross b_var, A;//两个coverpoint进行cross; endgroupcross中指定bins;int i,j;covergroup ct; coverpoint i { bins i[] = { [0:1] }; } coverpoint j { bins j[] = { [0:1] }; } x1: cross i,j; x2: cross i,j { ignore_bins i_zero = binsof(i) intersect { 0 };//i中不包含0; //binsof(x) intersect (y);//x的取值中,只收取为y的值; } endgroupbinsof 与 && / ||的组合;covergroup address_cov () @ (posedge ce); ADDRESS : coverpoint addr {bins addr0 = {0}; bins addr1 = {1};} CMD : coverpoint cmd {bins READ = {0}; bins WRITE = {1}; bins IDLE = {2};} CRS_USER_ADDR_CMD : cross ADDRESS, CMD {bins USER_ADDR0_READ = binsof(CMD) intersect {0};//默认的bins本来应该是2*3=6个,但是这里只定义了两个bins <addr0,READ> <addr1,READ> bins u2 = binsof(ADDRESS.addr0) || binsof(CMD.READ);// bins 数目为4,包括<addr0,READ>,<addr0,WRITE>,<addr0,IDLE>,<addr1,READ> bins u3 = binsof(ADDRESS.addr0) && binsof(CMD.READ);// bins 数目为1,包括<addr0,READ>} CRS_AUTO_ADDR_CMD : cross ADDRESS, CMD {ignore_bins AUTO_ADDR_READ = binsof(CMD) intersect {0}; ignore_bins AUTO_ADDR_WRITE = binsof(CMD) intersect {1} && binsof(ADDRESS) intersect{0};}(原文链接:https://blog.csdn.net/bleauchat/article/details/90445713)matches; 感觉上像是一个下线; bins apple = X with (a+b < 257) matches 127;// 127~257? 带参数的covergroup;module mod_m; logic [31:0] a, b; covergroup cg(int cg_lim); coverpoint a; coverpoint b; aXb : cross a, b { function CrossQueueType myFunc1(int f_lim); for (int i = 0; i < f_lim; ++i) myFunc1.push_back('{i,i}); endfunction bins one = myFunc1(cg_lim); bins two = myFunc2(cg_lim); function CrossQueueType myFunc2(logic [31:0] f_lim); for (logic [31:0] i = 0; i < f_lim; ++i) myFunc2.push_back('{2*i,2*i}); endfunction } endgroup cg cg_inst = new(3);//每一个例化的时候再指定参数; endmodule结果如下:cg_inst.aXb.one = <0.0> , <1.1>,<2.2>cg_inst.aXb.two = <0.0>,<2.2>,<4.4>,instance;每个覆盖率例化的时候,是所有的合在一起收集,还是每个例化的地方,单独收集对应的覆盖率; 每个覆盖率单独例化的时候,可以指定最终呈现的名字; covergroup g1 (int w, string instComment) @(posedge clk) ; // track coverage information for each instance of g1 in addition // to the cumulative coverage information for covergroup type g1 option.per_instance = 1; // comment for each instance of this covergroup option.comment = instComment; 一些基本的选项,通常不使用;//auto_bin_max, cross_auto_bin_max, goal, weight等等; //参考如下: (221条消息) [SV]SystemVerilog Coverage Options用法總結及案例_元直数字电路验证的博客-CSDN博客_coveragegroup option 也可以参考table 19-2; 设置采样时刻;一般来讲,是不指定采样时刻,然后再rm中比对通过后,手动sample, 可以保证采集数据的合理性和正确性; 也可以指定拍拍采集;covergroup g1 (int w, string instComment) @(posedge clk) ; 数据边界描述;[ $ : value ] => The set of values less than or equal to value[ value : $ ] => The set of values greater or equal to value————————————————版权声明:本文为CSDN博主「newyork major」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/zhangshangjie1/article/details/129121286
2025年06月03日
1 阅读
0 评论
0 点赞
1
2